Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164645527
D20300.id57504.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D20300.id57504.diff
View Options
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -407,6 +407,7 @@
fhreadlink;
getfhat;
funlinkat;
+ pidgetpd;
};
FBSDprivate_1.0 {
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -652,7 +652,7 @@
* However, don't do this until after fork(2) can no longer fail.
*/
if (fr->fr_flags & RFPROCDESC)
- procdesc_new(p2, fr->fr_pd_flags);
+ procdesc_new(p2, fr->fr_pd_flags | PD_WAITOK);
/*
* Both processes are set up, now check if any loadable modules want
Index: sys/kern/kern_prot.c
===================================================================
--- sys/kern/kern_prot.c
+++ sys/kern/kern_prot.c
@@ -1593,6 +1593,21 @@
return (cr_cansignal(td->td_ucred, p, signum));
}
+/*-
+ * Determine whether td may deliver the specified signal to p.
+ * Returns: 0 for permitted, an errno value otherwise
+ * Locks: Sufficient locks to protect various components of td and p
+ * must be held. td must be curthread, and a lock must be
+ * held for p.
+ * References: td and p must be valid for the lifetime of the call
+ */
+int
+p_cangetpd(struct thread *td, struct proc *p)
+{
+
+ return (p_cansignal(td, p, SIGKILL));
+}
+
/*-
* Determine whether td may reschedule p.
* Returns: 0 for permitted, an errno value otherwise
Index: sys/kern/sys_procdesc.c
===================================================================
--- sys/kern/sys_procdesc.c
+++ sys/kern/sys_procdesc.c
@@ -61,8 +61,6 @@
* Open questions:
*
* - How to handle ptrace(2)?
- * - Will we want to add a pidtoprocdesc(2) system call to allow process
- * descriptors to be created for processes without pdfork(2)?
*/
#include <sys/cdefs.h>
@@ -181,6 +179,72 @@
return (pd->pd_pid);
}
+int
+sys_pidgetpd(struct thread *td, struct pidgetpd_args *uap)
+{
+ int flag;
+
+ flag = uap->flag;
+ if ((flag & ~PD_ALLOWED_AT_PDGETPID) != 0)
+ return (EINVAL);
+
+ return (kern_pidgetpd(td, uap->pid, uap->flag));
+}
+
+int
+kern_pidgetpd(struct thread *td, pid_t pid, int flag)
+{
+ struct proc *proc;
+ struct procdesc *procdesc;
+ struct file *fp;
+ int fd, error;
+
+ proc = pfind_any(pid);
+ if (proc == NULL)
+ return (ESRCH);
+ error = p_cangetpd(td, proc);
+ if (error != 0) {
+ PROC_UNLOCK(proc);
+ return (error);
+ }
+ if ((proc->p_flag2 & P2_PD_CLOSED) != 0) {
+ PROC_UNLOCK(proc);
+ return (ESRCH);
+ }
+
+ if (proc->p_procdesc == NULL) {
+ /*
+ * We create a new process descriptors as DAEMON that
+ * it will not be killed when the pd will be closed.
+ */
+ if (procdesc_new(proc, PD_DAEMON) != 0) {
+ PROC_UNLOCK(proc);
+ return (ENOMEM);
+ }
+ }
+
+ procdesc = proc->p_procdesc;
+ refcount_acquire(&procdesc->pd_refcount);
+ PROC_UNLOCK(proc);
+
+ error = procdesc_falloc(td, &fp, &fd, flag, NULL);
+ if (error == 0) {
+ /*
+ * If we alloc a new procdesc instance and we can't assign it
+ * we don't care about freeing procdesc. We can reuse it
+ * later.
+ */
+ refcount_release(&procdesc->pd_refcount);
+ return (error);
+ }
+
+ procdesc_finit(procdesc, fp);
+ fdrop(fp, td);
+
+ td->td_retval[0] = fd;
+ return (0);
+}
+
/*
* Retrieve the PID associated with a process descriptor.
*/
@@ -225,12 +289,16 @@
* chance to set up the process descriptor. Failure is not permitted at this
* point, so procdesc_new() must succeed.
*/
-void
+int
procdesc_new(struct proc *p, int flags)
{
struct procdesc *pd;
- pd = uma_zalloc(procdesc_zone, M_WAITOK | M_ZERO);
+ pd = uma_zalloc(procdesc_zone, M_ZERO |
+ ((flags & PD_WAITOK) != 0 ? M_WAITOK : 0));
+ if (pd == NULL)
+ return (-1);
+
pd->pd_proc = p;
pd->pd_pid = p->p_pid;
p->p_procdesc = pd;
@@ -244,7 +312,9 @@
* Process descriptors start out with two references: one from their
* struct file, and the other from their struct proc.
*/
- refcount_init(&pd->pd_refcount, 2);
+ refcount_init(&pd->pd_refcount, 1);
+
+ return (0);
}
/*
@@ -274,7 +344,7 @@
}
static void
-procdesc_free(struct procdesc *pd)
+_procdesc_free(struct procdesc *pd)
{
/*
@@ -283,16 +353,20 @@
* detach the descriptor before the process dies if the descript is
* closed, as we can't wait synchronously.
*/
- if (refcount_release(&pd->pd_refcount)) {
- KASSERT(pd->pd_proc == NULL,
- ("procdesc_free: pd_proc != NULL"));
- KASSERT((pd->pd_flags & PDF_CLOSED),
- ("procdesc_free: !PDF_CLOSED"));
-
- knlist_destroy(&pd->pd_selinfo.si_note);
- PROCDESC_LOCK_DESTROY(pd);
- uma_zfree(procdesc_zone, pd);
- }
+ KASSERT(pd->pd_proc == NULL, ("procdesc_free: pd_proc != NULL"));
+ KASSERT((pd->pd_flags & PDF_CLOSED), ("procdesc_free: !PDF_CLOSED"));
+
+ knlist_destroy(&pd->pd_selinfo.si_note);
+ PROCDESC_LOCK_DESTROY(pd);
+ uma_zfree(procdesc_zone, pd);
+}
+
+static void
+procdesc_free(struct procdesc *pd)
+{
+
+ if (refcount_release(&pd->pd_refcount))
+ _procdesc_free(pd);
}
/*
@@ -377,9 +451,6 @@
fp->f_data = NULL;
sx_xlock(&proctree_lock);
- PROCDESC_LOCK(pd);
- pd->pd_flags |= PDF_CLOSED;
- PROCDESC_UNLOCK(pd);
p = pd->pd_proc;
if (p == NULL) {
/*
@@ -387,47 +458,56 @@
* collected and procdesc_reap() was already called.
*/
sx_xunlock(&proctree_lock);
- } else {
- PROC_LOCK(p);
- AUDIT_ARG_PROCESS(p);
- if (p->p_state == PRS_ZOMBIE) {
- /*
- * If the process is already dead and just awaiting
- * reaping, do that now. This will release the
- * process's reference to the process descriptor when it
- * calls back into procdesc_reap().
- */
- proc_reap(curthread, p, NULL, 0);
- } else {
- /*
- * If the process is not yet dead, we need to kill it,
- * but we can't wait around synchronously for it to go
- * away, as that path leads to madness (and deadlocks).
- * First, detach the process from its descriptor so that
- * its exit status will be reported normally.
- */
- pd->pd_proc = NULL;
- p->p_procdesc = NULL;
- procdesc_free(pd);
-
- /*
- * Next, reparent it to its reaper (usually init(8)) so
- * that there's someone to pick up the pieces; finally,
- * terminate with prejudice.
- */
- p->p_sigparent = SIGCHLD;
- proc_reparent(p, p->p_reaper, true);
- if ((pd->pd_flags & PDF_DAEMON) == 0)
- kern_psignal(p, SIGKILL);
- PROC_UNLOCK(p);
- sx_xunlock(&proctree_lock);
+ procdesc_free(pd);
+ return (0);
+ }
+
+ PROC_LOCK(p);
+ AUDIT_ARG_PROCESS(p);
+ if (p->p_state == PRS_ZOMBIE) {
+ /*
+ * If the process is already dead and just awaiting
+ * reaping, do that now. This will release the
+ * process's reference to the process descriptor when it
+ * calls back into procdesc_reap().
+ */
+ PROCDESC_LOCK(pd);
+ pd->pd_flags |= PDF_CLOSED;
+ PROCDESC_UNLOCK(pd);
+ proc_reap(curthread, p, NULL, 0);
+ return (0);
+ } else if (refcount_release(&pd->pd_refcount)) {
+ /*
+ * If the process is not yet dead, we need to kill it,
+ * but we can't wait around synchronously for it to go
+ * away, as that path leads to madness (and deadlocks).
+ * First, detach the process from its descriptor so that
+ * its exit status will be reported normally.
+ */
+ PROCDESC_LOCK(pd);
+ pd->pd_flags |= PDF_CLOSED;
+ PROCDESC_UNLOCK(pd);
+ pd->pd_proc = NULL;
+ p->p_procdesc = NULL;
+
+ /*
+ * Reparent it to init(8) so that there's someone
+ * to pick up the pieces; finally, terminate with
+ * prejudice.
+ */
+ p->p_sigparent = SIGCHLD;
+ proc_reparent(p, initproc, true);
+ if ((pd->pd_flags & PDF_DAEMON) == 0) {
+ p->p_flag2 |= P2_PD_CLOSED;
+ kern_psignal(p, SIGKILL);
}
+
+ _procdesc_free(pd);
}
- /*
- * Release the file descriptor's reference on the process descriptor.
- */
- procdesc_free(pd);
+ PROC_UNLOCK(p);
+ sx_xunlock(&proctree_lock);
+
return (0);
}
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -758,6 +758,7 @@
#define P2_ASLR_ENABLE 0x00000040 /* Force enable ASLR. */
#define P2_ASLR_DISABLE 0x00000080 /* Force disable ASLR. */
#define P2_ASLR_IGNSTART 0x00000100 /* Enable ASLR to consume sbrk area. */
+#define P2_PD_CLOSED 0x00000200 /* Enable ASLR to consume sbrk area. */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
@@ -1048,6 +1049,7 @@
void maybe_yield(void);
void mi_switch(int flags, struct thread *newtd);
int p_candebug(struct thread *td, struct proc *p);
+int p_cangetpd(struct thread *td, struct proc *p);
int p_cansee(struct thread *td, struct proc *p);
int p_cansched(struct thread *td, struct proc *p);
int p_cansignal(struct thread *td, struct proc *p, int signum);
Index: sys/sys/procdesc.h
===================================================================
--- sys/sys/procdesc.h
+++ sys/sys/procdesc.h
@@ -97,8 +97,9 @@
*/
int procdesc_exit(struct proc *);
int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **);
+int kern_pidgetpd(struct thread *, pid_t pid, int flag);
int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp);
-void procdesc_new(struct proc *, int);
+int procdesc_new(struct proc *, int);
void procdesc_finit(struct procdesc *, struct file *);
pid_t procdesc_pid(struct file *);
void procdesc_reap(struct proc *);
@@ -135,5 +136,8 @@
#define PD_CLOEXEC 0x00000002 /* Close file descriptor on exec. */
#define PD_ALLOWED_AT_FORK (PD_DAEMON | PD_CLOEXEC)
+#define PD_ALLOWED_AT_PDGETPID (PD_CLOEXEC)
+
+#define PD_WAITOK 0x10000000 /* Allow to wait while creating. */
#endif /* !_SYS_PROCDESC_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Aug 3, 9:07 PM (5 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35837078
Default Alt Text
D20300.id57504.diff (9 KB)
Attached To
Mode
D20300: Introducing pdopen.
Attached
Detach File
Event Timeline
Log In to Comment