The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/sys_procdesc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2009 Robert N. M. Watson
    3  * All rights reserved.
    4  *
    5  * This software was developed at the University of Cambridge Computer
    6  * Laboratory with support from a grant from Google, Inc.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*-
   31  * FreeBSD process descriptor facility.
   32  *
   33  * Some processes are represented by a file descriptor, which will be used in
   34  * preference to signaling and pids for the purposes of process management,
   35  * and is, in effect, a form of capability.  When a process descriptor is
   36  * used with a process, it ceases to be visible to certain traditional UNIX
   37  * process facilities, such as waitpid(2).
   38  *
   39  * Some semantics:
   40  *
   41  * - At most one process descriptor will exist for any process, although
   42  *   references to that descriptor may be held from many processes (or even
   43  *   be in flight between processes over a local domain socket).
   44  * - Last close on the process descriptor will terminate the process using
   45  *   SIGKILL and reparent it to init so that there's a process to reap it
   46  *   when it's done exiting.
   47  * - If the process exits before the descriptor is closed, it will not
   48  *   generate SIGCHLD on termination, or be picked up by waitpid().
   49  * - The pdkill(2) system call may be used to deliver a signal to the process
   50  *   using its process descriptor.
   51  * - The pdwait4(2) system call may be used to block (or not) on a process
   52  *   descriptor to collect termination information.
   53  *
   54  * Open questions:
   55  *
   56  * - How to handle ptrace(2)?
   57  * - Will we want to add a pidtoprocdesc(2) system call to allow process
   58  *   descriptors to be created for processes without pfork(2)?
   59  */
   60 
   61 #include <sys/cdefs.h>
   62 __FBSDID("$FreeBSD: releng/9.1/sys/kern/sys_procdesc.c 225617 2011-09-16 13:58:51Z kmacy $");
   63 
   64 #include "opt_procdesc.h"
   65 
   66 #include <sys/param.h>
   67 #include <sys/capability.h>
   68 #include <sys/fcntl.h>
   69 #include <sys/file.h>
   70 #include <sys/filedesc.h>
   71 #include <sys/kernel.h>
   72 #include <sys/lock.h>
   73 #include <sys/mutex.h>
   74 #include <sys/poll.h>
   75 #include <sys/proc.h>
   76 #include <sys/procdesc.h>
   77 #include <sys/resourcevar.h>
   78 #include <sys/stat.h>
   79 #include <sys/sysproto.h>
   80 #include <sys/sysctl.h>
   81 #include <sys/systm.h>
   82 #include <sys/ucred.h>
   83 
   84 #include <security/audit/audit.h>
   85 
   86 #include <vm/uma.h>
   87 
   88 #ifdef PROCDESC
   89 
   90 FEATURE(process_descriptors, "Process Descriptors");
   91 
   92 static uma_zone_t procdesc_zone;
   93 
   94 static fo_rdwr_t        procdesc_read;
   95 static fo_rdwr_t        procdesc_write;
   96 static fo_truncate_t    procdesc_truncate;
   97 static fo_ioctl_t       procdesc_ioctl;
   98 static fo_poll_t        procdesc_poll;
   99 static fo_kqfilter_t    procdesc_kqfilter;
  100 static fo_stat_t        procdesc_stat;
  101 static fo_close_t       procdesc_close;
  102 static fo_chmod_t       procdesc_chmod;
  103 static fo_chown_t       procdesc_chown;
  104 
  105 static struct fileops procdesc_ops = {
  106         .fo_read = procdesc_read,
  107         .fo_write = procdesc_write,
  108         .fo_truncate = procdesc_truncate,
  109         .fo_ioctl = procdesc_ioctl,
  110         .fo_poll = procdesc_poll,
  111         .fo_kqfilter = procdesc_kqfilter,
  112         .fo_stat = procdesc_stat,
  113         .fo_close = procdesc_close,
  114         .fo_chmod = procdesc_chmod,
  115         .fo_chown = procdesc_chown,
  116         .fo_flags = DFLAG_PASSABLE,
  117 };
  118 
  119 /*
  120  * Initialize with VFS so that process descriptors are available along with
  121  * other file descriptor types.  As long as it runs before init(8) starts,
  122  * there shouldn't be a problem.
  123  */
  124 static void
  125 procdesc_init(void *dummy __unused)
  126 {
  127 
  128         procdesc_zone = uma_zcreate("procdesc", sizeof(struct procdesc),
  129             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  130         if (procdesc_zone == NULL)
  131                 panic("procdesc_init: procdesc_zone not initialized");
  132 }
  133 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL);
  134 
  135 /*
  136  * Return a locked process given a process descriptor, or ESRCH if it has
  137  * died.
  138  */
  139 int
  140 procdesc_find(struct thread *td, int fd, cap_rights_t rights,
  141     struct proc **p)
  142 {
  143         struct procdesc *pd;
  144         struct file *fp;
  145         int error;
  146 
  147         error = fget(td, fd, rights, &fp);
  148         if (error)
  149                 return (error);
  150         if (fp->f_type != DTYPE_PROCDESC) {
  151                 error = EBADF;
  152                 goto out;
  153         }
  154         pd = fp->f_data;
  155         sx_slock(&proctree_lock);
  156         if (pd->pd_proc != NULL) {
  157                 *p = pd->pd_proc;
  158                 PROC_LOCK(*p);
  159         } else
  160                 error = ESRCH;
  161         sx_sunlock(&proctree_lock);
  162 out:
  163         fdrop(fp, td);
  164         return (error);
  165 }
  166 
  167 /*
  168  * Function to be used by procstat(1) sysctls when returning procdesc
  169  * information.
  170  */
  171 pid_t
  172 procdesc_pid(struct file *fp_procdesc)
  173 {
  174         struct procdesc *pd;
  175 
  176         KASSERT(fp_procdesc->f_type == DTYPE_PROCDESC,
  177            ("procdesc_pid: !procdesc"));
  178 
  179         pd = fp_procdesc->f_data;
  180         return (pd->pd_pid);
  181 }
  182 
  183 /*
  184  * Retrieve the PID associated with a process descriptor.
  185  */
  186 int
  187 kern_pdgetpid(struct thread *td, int fd, cap_rights_t rights, pid_t *pidp)
  188 {
  189         struct file *fp;
  190         int error;
  191 
  192         error = fget(td, fd, rights, &fp);
  193         if (error)
  194                 return (error);
  195         if (fp->f_type != DTYPE_PROCDESC) {
  196                 error = EBADF;
  197                 goto out;
  198         }
  199         *pidp = procdesc_pid(fp);
  200 out:
  201         fdrop(fp, td);
  202         return (error);
  203 }
  204 
  205 /*
  206  * System call to return the pid of a process given its process descriptor.
  207  */
  208 int
  209 sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
  210 {
  211         pid_t pid;
  212         int error;
  213 
  214         AUDIT_ARG_FD(uap->fd);
  215         error = kern_pdgetpid(td, uap->fd, CAP_PDGETPID, &pid);
  216         if (error == 0)
  217                 error = copyout(&pid, uap->pidp, sizeof(pid));
  218         return (error);
  219 }
  220 
  221 /*
  222  * When a new process is forked by pdfork(), a file descriptor is allocated
  223  * by the fork code first, then the process is forked, and then we get a
  224  * chance to set up the process descriptor.  Failure is not permitted at this
  225  * point, so procdesc_new() must succeed.
  226  */
  227 void
  228 procdesc_new(struct proc *p, int flags)
  229 {
  230         struct procdesc *pd;
  231 
  232         pd = uma_zalloc(procdesc_zone, M_WAITOK | M_ZERO);
  233         pd->pd_proc = p;
  234         pd->pd_pid = p->p_pid;
  235         p->p_procdesc = pd;
  236         pd->pd_flags = 0;
  237         if (flags & PD_DAEMON)
  238                 pd->pd_flags |= PDF_DAEMON;
  239         PROCDESC_LOCK_INIT(pd);
  240 
  241         /*
  242          * Process descriptors start out with two references: one from their
  243          * struct file, and the other from their struct proc.
  244          */
  245         refcount_init(&pd->pd_refcount, 2);
  246 }
  247 
  248 /*
  249  * Initialize a file with a process descriptor.
  250  */
  251 void
  252 procdesc_finit(struct procdesc *pdp, struct file *fp)
  253 {
  254 
  255         finit(fp, FREAD | FWRITE, DTYPE_PROCDESC, pdp, &procdesc_ops);
  256 }
  257 
  258 static void
  259 procdesc_free(struct procdesc *pd)
  260 {
  261 
  262         /*
  263          * When the last reference is released, we assert that the descriptor
  264          * has been closed, but not that the process has exited, as we will
  265          * detach the descriptor before the process dies if the descript is
  266          * closed, as we can't wait synchronously.
  267          */
  268         if (refcount_release(&pd->pd_refcount)) {
  269                 KASSERT(pd->pd_proc == NULL,
  270                     ("procdesc_free: pd_proc != NULL"));
  271                 KASSERT((pd->pd_flags & PDF_CLOSED),
  272                     ("procdesc_free: !PDF_CLOSED"));
  273 
  274                 PROCDESC_LOCK_DESTROY(pd);
  275                 uma_zfree(procdesc_zone, pd);
  276         }
  277 }
  278 
  279 /*
  280  * procdesc_exit() - notify a process descriptor that its process is exiting.
  281  * We use the proctree_lock to ensure that process exit either happens
  282  * strictly before or strictly after a concurrent call to procdesc_close().
  283  */
  284 int
  285 procdesc_exit(struct proc *p)
  286 {
  287         struct procdesc *pd;
  288 
  289         sx_assert(&proctree_lock, SA_XLOCKED);
  290         PROC_LOCK_ASSERT(p, MA_OWNED);
  291         KASSERT(p->p_procdesc != NULL, ("procdesc_exit: p_procdesc NULL"));
  292 
  293         pd = p->p_procdesc;
  294 
  295         PROCDESC_LOCK(pd);
  296         KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == initproc,
  297             ("procdesc_exit: closed && parent not init"));
  298 
  299         pd->pd_flags |= PDF_EXITED;
  300 
  301         /*
  302          * If the process descriptor has been closed, then we have nothing
  303          * to do; return 1 so that init will get SIGCHLD and do the reaping.
  304          * Clean up the procdesc now rather than letting it happen during
  305          * that reap.
  306          */
  307         if (pd->pd_flags & PDF_CLOSED) {
  308                 PROCDESC_UNLOCK(pd);
  309                 pd->pd_proc = NULL;
  310                 p->p_procdesc = NULL;
  311                 procdesc_free(pd);
  312                 return (1);
  313         }
  314         if (pd->pd_flags & PDF_SELECTED) {
  315                 pd->pd_flags &= ~PDF_SELECTED;
  316                 selwakeup(&pd->pd_selinfo);
  317         }
  318         PROCDESC_UNLOCK(pd);
  319         return (0);
  320 }
  321 
  322 /*
  323  * When a process descriptor is reaped, perhaps as a result of close() or
  324  * pdwait4(), release the process's reference on the process descriptor.
  325  */
  326 void
  327 procdesc_reap(struct proc *p)
  328 {
  329         struct procdesc *pd;
  330 
  331         sx_assert(&proctree_lock, SA_XLOCKED);
  332         KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL"));
  333 
  334         pd = p->p_procdesc;
  335         pd->pd_proc = NULL;
  336         procdesc_free(pd);
  337 }
  338 
  339 /*
  340  * procdesc_close() - last close on a process descriptor.  If the process is
  341  * still running, terminate with SIGKILL (unless PD_DAEMON is set) and let
  342  * init(8) clean up the mess; if not, we have to clean up the zombie ourselves.
  343  */
  344 static int
  345 procdesc_close(struct file *fp, struct thread *td)
  346 {
  347         struct procdesc *pd;
  348         struct proc *p;
  349 
  350         KASSERT(fp->f_type == DTYPE_PROCDESC, ("procdesc_close: !procdesc"));
  351 
  352         pd = fp->f_data;
  353         fp->f_ops = &badfileops;
  354         fp->f_data = NULL;
  355 
  356         sx_xlock(&proctree_lock);
  357         PROCDESC_LOCK(pd);
  358         pd->pd_flags |= PDF_CLOSED;
  359         PROCDESC_UNLOCK(pd);
  360         p = pd->pd_proc;
  361         PROC_LOCK(p);
  362         if (p->p_state == PRS_ZOMBIE) {
  363                 /*
  364                  * If the process is already dead and just awaiting reaping,
  365                  * do that now.  This will release the process's reference to
  366                  * the process descriptor when it calls back into
  367                  * procdesc_reap().
  368                  */
  369                 PROC_SLOCK(p);
  370                 proc_reap(curthread, p, NULL, 0, NULL);
  371         } else {
  372                 /*
  373                  * If the process is not yet dead, we need to kill it, but we
  374                  * can't wait around synchronously for it to go away, as that
  375                  * path leads to madness (and deadlocks).  First, detach the
  376                  * process from its descriptor so that its exit status will
  377                  * be reported normally.
  378                  */
  379                 pd->pd_proc = NULL;
  380                 p->p_procdesc = NULL;
  381                 procdesc_free(pd);
  382 
  383                 /*
  384                  * Next, reparent it to init(8) so that there's someone to
  385                  * pick up the pieces; finally, terminate with prejudice.
  386                  */
  387                 p->p_sigparent = SIGCHLD;
  388                 proc_reparent(p, initproc);
  389                 if ((pd->pd_flags & PD_DAEMON) == 0)
  390                         kern_psignal(p, SIGKILL);
  391                 PROC_UNLOCK(p);
  392                 sx_xunlock(&proctree_lock);
  393         }
  394 
  395         /*
  396          * Release the file descriptor's reference on the process descriptor.
  397          */
  398         procdesc_free(pd);
  399         return (0);
  400 }
  401 
  402 static int
  403 procdesc_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
  404     int flags, struct thread *td)
  405 {
  406 
  407         return (EOPNOTSUPP);
  408 }
  409 
  410 static int
  411 procdesc_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
  412     int flags, struct thread *td)
  413 {
  414 
  415         return (EOPNOTSUPP);
  416 }
  417 
  418 static int
  419 procdesc_truncate(struct file *fp, off_t length, struct ucred *active_cred,
  420     struct thread *td)
  421 {
  422 
  423         return (EOPNOTSUPP);
  424 }
  425 
  426 static int
  427 procdesc_ioctl(struct file *fp, u_long com, void *data,
  428     struct ucred *active_cred, struct thread *td)
  429 {
  430 
  431         return (EOPNOTSUPP);
  432 }
  433 
  434 static int
  435 procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
  436     struct thread *td)
  437 {
  438         struct procdesc *pd;
  439         int revents;
  440 
  441         revents = 0;
  442         pd = fp->f_data;
  443         PROCDESC_LOCK(pd);
  444         if (pd->pd_flags & PDF_EXITED)
  445                 revents |= POLLHUP;
  446         if (revents == 0) {
  447                 selrecord(td, &pd->pd_selinfo);
  448                 pd->pd_flags |= PDF_SELECTED;
  449         }
  450         PROCDESC_UNLOCK(pd);
  451         return (revents);
  452 }
  453 
  454 static int
  455 procdesc_kqfilter(struct file *fp, struct knote *kn)
  456 {
  457 
  458         return (EOPNOTSUPP);
  459 }
  460 
  461 static int
  462 procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
  463     struct thread *td)
  464 {
  465         struct procdesc *pd;
  466         struct timeval pstart;
  467 
  468         /*
  469          * XXXRW: Perhaps we should cache some more information from the
  470          * process so that we can return it reliably here even after it has
  471          * died.  For example, caching its credential data.
  472          */
  473         bzero(sb, sizeof(*sb));
  474         pd = fp->f_data;
  475         sx_slock(&proctree_lock);
  476         if (pd->pd_proc != NULL) {
  477                 PROC_LOCK(pd->pd_proc);
  478 
  479                 /* Set birth and [acm] times to process start time. */
  480                 pstart = pd->pd_proc->p_stats->p_start;
  481                 timevaladd(&pstart, &boottime);
  482                 TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim);
  483                 sb->st_atim = sb->st_birthtim;
  484                 sb->st_ctim = sb->st_birthtim;
  485                 sb->st_mtim = sb->st_birthtim;
  486                 if (pd->pd_proc->p_state != PRS_ZOMBIE)
  487                         sb->st_mode = S_IFREG | S_IRWXU;
  488                 else
  489                         sb->st_mode = S_IFREG;
  490                 sb->st_uid = pd->pd_proc->p_ucred->cr_ruid;
  491                 sb->st_gid = pd->pd_proc->p_ucred->cr_rgid;
  492                 PROC_UNLOCK(pd->pd_proc);
  493         } else
  494                 sb->st_mode = S_IFREG;
  495         sx_sunlock(&proctree_lock);
  496         return (0);
  497 }
  498 
  499 static int
  500 procdesc_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
  501     struct thread *td)
  502 {
  503 
  504         return (EOPNOTSUPP);
  505 }
  506 
  507 static int
  508 procdesc_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
  509     struct thread *td)
  510 {
  511 
  512         return (EOPNOTSUPP);
  513 }
  514 
  515 #else /* !PROCDESC */
  516 
  517 int
  518 sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
  519 {
  520 
  521         return (ENOSYS);
  522 }
  523 
  524 #endif /* PROCDESC */

Cache object: e5f249f34721aebbb9411f377af82ca9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.