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/10.2/sys/kern/sys_procdesc.c 280258 2015-03-19 13:37:36Z rwatson $");
   63 
   64 #include "opt_procdesc.h"
   65 
   66 #include <sys/param.h>
   67 #include <sys/capsicum.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_sendfile = invfo_sendfile,
  117         .fo_flags = DFLAG_PASSABLE,
  118 };
  119 
  120 /*
  121  * Initialize with VFS so that process descriptors are available along with
  122  * other file descriptor types.  As long as it runs before init(8) starts,
  123  * there shouldn't be a problem.
  124  */
  125 static void
  126 procdesc_init(void *dummy __unused)
  127 {
  128 
  129         procdesc_zone = uma_zcreate("procdesc", sizeof(struct procdesc),
  130             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  131         if (procdesc_zone == NULL)
  132                 panic("procdesc_init: procdesc_zone not initialized");
  133 }
  134 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL);
  135 
  136 /*
  137  * Return a locked process given a process descriptor, or ESRCH if it has
  138  * died.
  139  */
  140 int
  141 procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp,
  142     struct proc **p)
  143 {
  144         struct procdesc *pd;
  145         struct file *fp;
  146         int error;
  147 
  148         error = fget(td, fd, rightsp, &fp);
  149         if (error)
  150                 return (error);
  151         if (fp->f_type != DTYPE_PROCDESC) {
  152                 error = EBADF;
  153                 goto out;
  154         }
  155         pd = fp->f_data;
  156         sx_slock(&proctree_lock);
  157         if (pd->pd_proc != NULL) {
  158                 *p = pd->pd_proc;
  159                 PROC_LOCK(*p);
  160         } else
  161                 error = ESRCH;
  162         sx_sunlock(&proctree_lock);
  163 out:
  164         fdrop(fp, td);
  165         return (error);
  166 }
  167 
  168 /*
  169  * Function to be used by procstat(1) sysctls when returning procdesc
  170  * information.
  171  */
  172 pid_t
  173 procdesc_pid(struct file *fp_procdesc)
  174 {
  175         struct procdesc *pd;
  176 
  177         KASSERT(fp_procdesc->f_type == DTYPE_PROCDESC,
  178            ("procdesc_pid: !procdesc"));
  179 
  180         pd = fp_procdesc->f_data;
  181         return (pd->pd_pid);
  182 }
  183 
  184 /*
  185  * Retrieve the PID associated with a process descriptor.
  186  */
  187 int
  188 kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp)
  189 {
  190         struct file *fp;
  191         int error;
  192 
  193         error = fget(td, fd, rightsp, &fp);
  194         if (error)
  195                 return (error);
  196         if (fp->f_type != DTYPE_PROCDESC) {
  197                 error = EBADF;
  198                 goto out;
  199         }
  200         *pidp = procdesc_pid(fp);
  201 out:
  202         fdrop(fp, td);
  203         return (error);
  204 }
  205 
  206 /*
  207  * System call to return the pid of a process given its process descriptor.
  208  */
  209 int
  210 sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
  211 {
  212         cap_rights_t rights;
  213         pid_t pid;
  214         int error;
  215 
  216         AUDIT_ARG_FD(uap->fd);
  217         error = kern_pdgetpid(td, uap->fd,
  218             cap_rights_init(&rights, CAP_PDGETPID), &pid);
  219         if (error == 0)
  220                 error = copyout(&pid, uap->pidp, sizeof(pid));
  221         return (error);
  222 }
  223 
  224 /*
  225  * When a new process is forked by pdfork(), a file descriptor is allocated
  226  * by the fork code first, then the process is forked, and then we get a
  227  * chance to set up the process descriptor.  Failure is not permitted at this
  228  * point, so procdesc_new() must succeed.
  229  */
  230 void
  231 procdesc_new(struct proc *p, int flags)
  232 {
  233         struct procdesc *pd;
  234 
  235         pd = uma_zalloc(procdesc_zone, M_WAITOK | M_ZERO);
  236         pd->pd_proc = p;
  237         pd->pd_pid = p->p_pid;
  238         p->p_procdesc = pd;
  239         pd->pd_flags = 0;
  240         if (flags & PD_DAEMON)
  241                 pd->pd_flags |= PDF_DAEMON;
  242         PROCDESC_LOCK_INIT(pd);
  243 
  244         /*
  245          * Process descriptors start out with two references: one from their
  246          * struct file, and the other from their struct proc.
  247          */
  248         refcount_init(&pd->pd_refcount, 2);
  249 }
  250 
  251 /*
  252  * Initialize a file with a process descriptor.
  253  */
  254 void
  255 procdesc_finit(struct procdesc *pdp, struct file *fp)
  256 {
  257 
  258         finit(fp, FREAD | FWRITE, DTYPE_PROCDESC, pdp, &procdesc_ops);
  259 }
  260 
  261 static void
  262 procdesc_free(struct procdesc *pd)
  263 {
  264 
  265         /*
  266          * When the last reference is released, we assert that the descriptor
  267          * has been closed, but not that the process has exited, as we will
  268          * detach the descriptor before the process dies if the descript is
  269          * closed, as we can't wait synchronously.
  270          */
  271         if (refcount_release(&pd->pd_refcount)) {
  272                 KASSERT(pd->pd_proc == NULL,
  273                     ("procdesc_free: pd_proc != NULL"));
  274                 KASSERT((pd->pd_flags & PDF_CLOSED),
  275                     ("procdesc_free: !PDF_CLOSED"));
  276 
  277                 PROCDESC_LOCK_DESTROY(pd);
  278                 uma_zfree(procdesc_zone, pd);
  279         }
  280 }
  281 
  282 /*
  283  * procdesc_exit() - notify a process descriptor that its process is exiting.
  284  * We use the proctree_lock to ensure that process exit either happens
  285  * strictly before or strictly after a concurrent call to procdesc_close().
  286  */
  287 int
  288 procdesc_exit(struct proc *p)
  289 {
  290         struct procdesc *pd;
  291 
  292         sx_assert(&proctree_lock, SA_XLOCKED);
  293         PROC_LOCK_ASSERT(p, MA_OWNED);
  294         KASSERT(p->p_procdesc != NULL, ("procdesc_exit: p_procdesc NULL"));
  295 
  296         pd = p->p_procdesc;
  297 
  298         PROCDESC_LOCK(pd);
  299         KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == initproc,
  300             ("procdesc_exit: closed && parent not init"));
  301 
  302         pd->pd_flags |= PDF_EXITED;
  303 
  304         /*
  305          * If the process descriptor has been closed, then we have nothing
  306          * to do; return 1 so that init will get SIGCHLD and do the reaping.
  307          * Clean up the procdesc now rather than letting it happen during
  308          * that reap.
  309          */
  310         if (pd->pd_flags & PDF_CLOSED) {
  311                 PROCDESC_UNLOCK(pd);
  312                 pd->pd_proc = NULL;
  313                 p->p_procdesc = NULL;
  314                 procdesc_free(pd);
  315                 return (1);
  316         }
  317         if (pd->pd_flags & PDF_SELECTED) {
  318                 pd->pd_flags &= ~PDF_SELECTED;
  319                 selwakeup(&pd->pd_selinfo);
  320         }
  321         PROCDESC_UNLOCK(pd);
  322         return (0);
  323 }
  324 
  325 /*
  326  * When a process descriptor is reaped, perhaps as a result of close() or
  327  * pdwait4(), release the process's reference on the process descriptor.
  328  */
  329 void
  330 procdesc_reap(struct proc *p)
  331 {
  332         struct procdesc *pd;
  333 
  334         sx_assert(&proctree_lock, SA_XLOCKED);
  335         KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL"));
  336 
  337         pd = p->p_procdesc;
  338         pd->pd_proc = NULL;
  339         p->p_procdesc = NULL;
  340         procdesc_free(pd);
  341 }
  342 
  343 /*
  344  * procdesc_close() - last close on a process descriptor.  If the process is
  345  * still running, terminate with SIGKILL (unless PDF_DAEMON is set) and let
  346  * init(8) clean up the mess; if not, we have to clean up the zombie ourselves.
  347  */
  348 static int
  349 procdesc_close(struct file *fp, struct thread *td)
  350 {
  351         struct procdesc *pd;
  352         struct proc *p;
  353 
  354         KASSERT(fp->f_type == DTYPE_PROCDESC, ("procdesc_close: !procdesc"));
  355 
  356         pd = fp->f_data;
  357         fp->f_ops = &badfileops;
  358         fp->f_data = NULL;
  359 
  360         sx_xlock(&proctree_lock);
  361         PROCDESC_LOCK(pd);
  362         pd->pd_flags |= PDF_CLOSED;
  363         PROCDESC_UNLOCK(pd);
  364         p = pd->pd_proc;
  365         if (p == NULL) {
  366                 /*
  367                  * This is the case where process' exit status was already
  368                  * collected and procdesc_reap() was already called.
  369                  */
  370                 sx_xunlock(&proctree_lock);
  371         } else if (p->p_state == PRS_ZOMBIE) {
  372                 /*
  373                  * If the process is already dead and just awaiting reaping,
  374                  * do that now.  This will release the process's reference to
  375                  * the process descriptor when it calls back into
  376                  * procdesc_reap().
  377                  */
  378                 PROC_LOCK(p);
  379                 PROC_SLOCK(p);
  380                 proc_reap(curthread, p, NULL, 0);
  381         } else {
  382                 /*
  383                  * If the process is not yet dead, we need to kill it, but we
  384                  * can't wait around synchronously for it to go away, as that
  385                  * path leads to madness (and deadlocks).  First, detach the
  386                  * process from its descriptor so that its exit status will
  387                  * be reported normally.
  388                  */
  389                 PROC_LOCK(p);
  390                 pd->pd_proc = NULL;
  391                 p->p_procdesc = NULL;
  392                 procdesc_free(pd);
  393 
  394                 /*
  395                  * Next, reparent it to init(8) so that there's someone to
  396                  * pick up the pieces; finally, terminate with prejudice.
  397                  */
  398                 p->p_sigparent = SIGCHLD;
  399                 proc_reparent(p, initproc);
  400                 if ((pd->pd_flags & PDF_DAEMON) == 0)
  401                         kern_psignal(p, SIGKILL);
  402                 PROC_UNLOCK(p);
  403                 sx_xunlock(&proctree_lock);
  404         }
  405 
  406         /*
  407          * Release the file descriptor's reference on the process descriptor.
  408          */
  409         procdesc_free(pd);
  410         return (0);
  411 }
  412 
  413 static int
  414 procdesc_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
  415     int flags, struct thread *td)
  416 {
  417 
  418         return (EOPNOTSUPP);
  419 }
  420 
  421 static int
  422 procdesc_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
  423     int flags, struct thread *td)
  424 {
  425 
  426         return (EOPNOTSUPP);
  427 }
  428 
  429 static int
  430 procdesc_truncate(struct file *fp, off_t length, struct ucred *active_cred,
  431     struct thread *td)
  432 {
  433 
  434         return (EOPNOTSUPP);
  435 }
  436 
  437 static int
  438 procdesc_ioctl(struct file *fp, u_long com, void *data,
  439     struct ucred *active_cred, struct thread *td)
  440 {
  441 
  442         return (EOPNOTSUPP);
  443 }
  444 
  445 static int
  446 procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
  447     struct thread *td)
  448 {
  449         struct procdesc *pd;
  450         int revents;
  451 
  452         revents = 0;
  453         pd = fp->f_data;
  454         PROCDESC_LOCK(pd);
  455         if (pd->pd_flags & PDF_EXITED)
  456                 revents |= POLLHUP;
  457         if (revents == 0) {
  458                 selrecord(td, &pd->pd_selinfo);
  459                 pd->pd_flags |= PDF_SELECTED;
  460         }
  461         PROCDESC_UNLOCK(pd);
  462         return (revents);
  463 }
  464 
  465 static int
  466 procdesc_kqfilter(struct file *fp, struct knote *kn)
  467 {
  468 
  469         return (EOPNOTSUPP);
  470 }
  471 
  472 static int
  473 procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
  474     struct thread *td)
  475 {
  476         struct procdesc *pd;
  477         struct timeval pstart;
  478 
  479         /*
  480          * XXXRW: Perhaps we should cache some more information from the
  481          * process so that we can return it reliably here even after it has
  482          * died.  For example, caching its credential data.
  483          */
  484         bzero(sb, sizeof(*sb));
  485         pd = fp->f_data;
  486         sx_slock(&proctree_lock);
  487         if (pd->pd_proc != NULL) {
  488                 PROC_LOCK(pd->pd_proc);
  489 
  490                 /* Set birth and [acm] times to process start time. */
  491                 pstart = pd->pd_proc->p_stats->p_start;
  492                 timevaladd(&pstart, &boottime);
  493                 TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim);
  494                 sb->st_atim = sb->st_birthtim;
  495                 sb->st_ctim = sb->st_birthtim;
  496                 sb->st_mtim = sb->st_birthtim;
  497                 if (pd->pd_proc->p_state != PRS_ZOMBIE)
  498                         sb->st_mode = S_IFREG | S_IRWXU;
  499                 else
  500                         sb->st_mode = S_IFREG;
  501                 sb->st_uid = pd->pd_proc->p_ucred->cr_ruid;
  502                 sb->st_gid = pd->pd_proc->p_ucred->cr_rgid;
  503                 PROC_UNLOCK(pd->pd_proc);
  504         } else
  505                 sb->st_mode = S_IFREG;
  506         sx_sunlock(&proctree_lock);
  507         return (0);
  508 }
  509 
  510 static int
  511 procdesc_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
  512     struct thread *td)
  513 {
  514 
  515         return (EOPNOTSUPP);
  516 }
  517 
  518 static int
  519 procdesc_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
  520     struct thread *td)
  521 {
  522 
  523         return (EOPNOTSUPP);
  524 }
  525 
  526 #else /* !PROCDESC */
  527 
  528 int
  529 sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
  530 {
  531 
  532         return (ENOSYS);
  533 }
  534 
  535 #endif /* PROCDESC */

Cache object: d685d22887cda01cd1412d730685dca2


[ 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.