Page MenuHomeFreeBSD

D20300.id57504.diff
No OneTemporary

D20300.id57504.diff

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

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)

Event Timeline