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/kern_procctl.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) 2014 John Baldwin
    3  * Copyright (c) 2014, 2016 The FreeBSD Foundation
    4  *
    5  * Portions of this software were developed by Konstantin Belousov
    6  * under sponsorship from the FreeBSD Foundation.
    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 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/capsicum.h>
   36 #include <sys/lock.h>
   37 #include <sys/mutex.h>
   38 #include <sys/priv.h>
   39 #include <sys/proc.h>
   40 #include <sys/procctl.h>
   41 #include <sys/sx.h>
   42 #include <sys/syscallsubr.h>
   43 #include <sys/sysproto.h>
   44 #include <sys/wait.h>
   45 
   46 #include <vm/vm.h>
   47 #include <vm/pmap.h>
   48 #include <vm/vm_map.h>
   49 #include <vm/vm_extern.h>
   50 
   51 static int
   52 protect_setchild(struct thread *td, struct proc *p, int flags)
   53 {
   54 
   55         PROC_LOCK_ASSERT(p, MA_OWNED);
   56         if (p->p_flag & P_SYSTEM || p_cansched(td, p) != 0)
   57                 return (0);
   58         if (flags & PPROT_SET) {
   59                 p->p_flag |= P_PROTECTED;
   60                 if (flags & PPROT_INHERIT)
   61                         p->p_flag2 |= P2_INHERIT_PROTECTED;
   62         } else {
   63                 p->p_flag &= ~P_PROTECTED;
   64                 p->p_flag2 &= ~P2_INHERIT_PROTECTED;
   65         }
   66         return (1);
   67 }
   68 
   69 static int
   70 protect_setchildren(struct thread *td, struct proc *top, int flags)
   71 {
   72         struct proc *p;
   73         int ret;
   74 
   75         p = top;
   76         ret = 0;
   77         sx_assert(&proctree_lock, SX_LOCKED);
   78         for (;;) {
   79                 ret |= protect_setchild(td, p, flags);
   80                 PROC_UNLOCK(p);
   81                 /*
   82                  * If this process has children, descend to them next,
   83                  * otherwise do any siblings, and if done with this level,
   84                  * follow back up the tree (but not past top).
   85                  */
   86                 if (!LIST_EMPTY(&p->p_children))
   87                         p = LIST_FIRST(&p->p_children);
   88                 else for (;;) {
   89                         if (p == top) {
   90                                 PROC_LOCK(p);
   91                                 return (ret);
   92                         }
   93                         if (LIST_NEXT(p, p_sibling)) {
   94                                 p = LIST_NEXT(p, p_sibling);
   95                                 break;
   96                         }
   97                         p = p->p_pptr;
   98                 }
   99                 PROC_LOCK(p);
  100         }
  101 }
  102 
  103 static int
  104 protect_set(struct thread *td, struct proc *p, int flags)
  105 {
  106         int error, ret;
  107 
  108         switch (PPROT_OP(flags)) {
  109         case PPROT_SET:
  110         case PPROT_CLEAR:
  111                 break;
  112         default:
  113                 return (EINVAL);
  114         }
  115 
  116         if ((PPROT_FLAGS(flags) & ~(PPROT_DESCEND | PPROT_INHERIT)) != 0)
  117                 return (EINVAL);
  118 
  119         error = priv_check(td, PRIV_VM_MADV_PROTECT);
  120         if (error)
  121                 return (error);
  122 
  123         if (flags & PPROT_DESCEND)
  124                 ret = protect_setchildren(td, p, flags);
  125         else
  126                 ret = protect_setchild(td, p, flags);
  127         if (ret == 0)
  128                 return (EPERM);
  129         return (0);
  130 }
  131 
  132 static int
  133 reap_acquire(struct thread *td, struct proc *p)
  134 {
  135 
  136         sx_assert(&proctree_lock, SX_XLOCKED);
  137         if (p != curproc)
  138                 return (EPERM);
  139         if ((p->p_treeflag & P_TREE_REAPER) != 0)
  140                 return (EBUSY);
  141         p->p_treeflag |= P_TREE_REAPER;
  142         /*
  143          * We do not reattach existing children and the whole tree
  144          * under them to us, since p->p_reaper already seen them.
  145          */
  146         return (0);
  147 }
  148 
  149 static int
  150 reap_release(struct thread *td, struct proc *p)
  151 {
  152 
  153         sx_assert(&proctree_lock, SX_XLOCKED);
  154         if (p != curproc)
  155                 return (EPERM);
  156         if (p == initproc)
  157                 return (EINVAL);
  158         if ((p->p_treeflag & P_TREE_REAPER) == 0)
  159                 return (EINVAL);
  160         reaper_abandon_children(p, false);
  161         return (0);
  162 }
  163 
  164 static int
  165 reap_status(struct thread *td, struct proc *p,
  166     struct procctl_reaper_status *rs)
  167 {
  168         struct proc *reap, *p2, *first_p;
  169 
  170         sx_assert(&proctree_lock, SX_LOCKED);
  171         bzero(rs, sizeof(*rs));
  172         if ((p->p_treeflag & P_TREE_REAPER) == 0) {
  173                 reap = p->p_reaper;
  174         } else {
  175                 reap = p;
  176                 rs->rs_flags |= REAPER_STATUS_OWNED;
  177         }
  178         if (reap == initproc)
  179                 rs->rs_flags |= REAPER_STATUS_REALINIT;
  180         rs->rs_reaper = reap->p_pid;
  181         rs->rs_descendants = 0;
  182         rs->rs_children = 0;
  183         if (!LIST_EMPTY(&reap->p_reaplist)) {
  184                 first_p = LIST_FIRST(&reap->p_children);
  185                 if (first_p == NULL)
  186                         first_p = LIST_FIRST(&reap->p_reaplist);
  187                 rs->rs_pid = first_p->p_pid;
  188                 LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) {
  189                         if (proc_realparent(p2) == reap)
  190                                 rs->rs_children++;
  191                         rs->rs_descendants++;
  192                 }
  193         } else {
  194                 rs->rs_pid = -1;
  195         }
  196         return (0);
  197 }
  198 
  199 static int
  200 reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp)
  201 {
  202         struct proc *reap, *p2;
  203         struct procctl_reaper_pidinfo *pi, *pip;
  204         u_int i, n;
  205         int error;
  206 
  207         sx_assert(&proctree_lock, SX_LOCKED);
  208         PROC_UNLOCK(p);
  209         reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p;
  210         n = i = 0;
  211         error = 0;
  212         LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling)
  213                 n++;
  214         sx_unlock(&proctree_lock);
  215         if (rp->rp_count < n)
  216                 n = rp->rp_count;
  217         pi = malloc(n * sizeof(*pi), M_TEMP, M_WAITOK);
  218         sx_slock(&proctree_lock);
  219         LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) {
  220                 if (i == n)
  221                         break;
  222                 pip = &pi[i];
  223                 bzero(pip, sizeof(*pip));
  224                 pip->pi_pid = p2->p_pid;
  225                 pip->pi_subtree = p2->p_reapsubtree;
  226                 pip->pi_flags = REAPER_PIDINFO_VALID;
  227                 if (proc_realparent(p2) == reap)
  228                         pip->pi_flags |= REAPER_PIDINFO_CHILD;
  229                 if ((p2->p_treeflag & P_TREE_REAPER) != 0)
  230                         pip->pi_flags |= REAPER_PIDINFO_REAPER;
  231                 i++;
  232         }
  233         sx_sunlock(&proctree_lock);
  234         error = copyout(pi, rp->rp_pids, i * sizeof(*pi));
  235         free(pi, M_TEMP);
  236         sx_slock(&proctree_lock);
  237         PROC_LOCK(p);
  238         return (error);
  239 }
  240 
  241 static void
  242 reap_kill_proc(struct thread *td, struct proc *p2, ksiginfo_t *ksi,
  243     struct procctl_reaper_kill *rk, int *error)
  244 {
  245         int error1;
  246 
  247         PROC_LOCK(p2);
  248         error1 = p_cansignal(td, p2, rk->rk_sig);
  249         if (error1 == 0) {
  250                 pksignal(p2, rk->rk_sig, ksi);
  251                 rk->rk_killed++;
  252                 *error = error1;
  253         } else if (*error == ESRCH) {
  254                 rk->rk_fpid = p2->p_pid;
  255                 *error = error1;
  256         }
  257         PROC_UNLOCK(p2);
  258 }
  259 
  260 struct reap_kill_tracker {
  261         struct proc *parent;
  262         TAILQ_ENTRY(reap_kill_tracker) link;
  263 };
  264 
  265 TAILQ_HEAD(reap_kill_tracker_head, reap_kill_tracker);
  266 
  267 static void
  268 reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2)
  269 {
  270         struct reap_kill_tracker *t;
  271 
  272         t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK);
  273         t->parent = p2;
  274         TAILQ_INSERT_TAIL(tracker, t, link);
  275 }
  276 
  277 static int
  278 reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk)
  279 {
  280         struct proc *reap, *p2;
  281         ksiginfo_t ksi;
  282         struct reap_kill_tracker_head tracker;
  283         struct reap_kill_tracker *t;
  284         int error;
  285 
  286         sx_assert(&proctree_lock, SX_LOCKED);
  287         if (IN_CAPABILITY_MODE(td))
  288                 return (ECAPMODE);
  289         if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG ||
  290             (rk->rk_flags & ~(REAPER_KILL_CHILDREN |
  291             REAPER_KILL_SUBTREE)) != 0 || (rk->rk_flags &
  292             (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) ==
  293             (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE))
  294                 return (EINVAL);
  295         PROC_UNLOCK(p);
  296         reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p;
  297         ksiginfo_init(&ksi);
  298         ksi.ksi_signo = rk->rk_sig;
  299         ksi.ksi_code = SI_USER;
  300         ksi.ksi_pid = td->td_proc->p_pid;
  301         ksi.ksi_uid = td->td_ucred->cr_ruid;
  302         error = ESRCH;
  303         rk->rk_killed = 0;
  304         rk->rk_fpid = -1;
  305         if ((rk->rk_flags & REAPER_KILL_CHILDREN) != 0) {
  306                 for (p2 = LIST_FIRST(&reap->p_children); p2 != NULL;
  307                     p2 = LIST_NEXT(p2, p_sibling)) {
  308                         reap_kill_proc(td, p2, &ksi, rk, &error);
  309                         /*
  310                          * Do not end the loop on error, signal
  311                          * everything we can.
  312                          */
  313                 }
  314         } else {
  315                 TAILQ_INIT(&tracker);
  316                 reap_kill_sched(&tracker, reap);
  317                 while ((t = TAILQ_FIRST(&tracker)) != NULL) {
  318                         MPASS((t->parent->p_treeflag & P_TREE_REAPER) != 0);
  319                         TAILQ_REMOVE(&tracker, t, link);
  320                         for (p2 = LIST_FIRST(&t->parent->p_reaplist); p2 != NULL;
  321                             p2 = LIST_NEXT(p2, p_reapsibling)) {
  322                                 if (t->parent == reap &&
  323                                     (rk->rk_flags & REAPER_KILL_SUBTREE) != 0 &&
  324                                     p2->p_reapsubtree != rk->rk_subtree)
  325                                         continue;
  326                                 if ((p2->p_treeflag & P_TREE_REAPER) != 0)
  327                                         reap_kill_sched(&tracker, p2);
  328                                 reap_kill_proc(td, p2, &ksi, rk, &error);
  329                         }
  330                         free(t, M_TEMP);
  331                 }
  332         }
  333         PROC_LOCK(p);
  334         return (error);
  335 }
  336 
  337 static int
  338 trace_ctl(struct thread *td, struct proc *p, int state)
  339 {
  340 
  341         PROC_LOCK_ASSERT(p, MA_OWNED);
  342 
  343         /*
  344          * Ktrace changes p_traceflag from or to zero under the
  345          * process lock, so the test does not need to acquire ktrace
  346          * mutex.
  347          */
  348         if ((p->p_flag & P_TRACED) != 0 || p->p_traceflag != 0)
  349                 return (EBUSY);
  350 
  351         switch (state) {
  352         case PROC_TRACE_CTL_ENABLE:
  353                 if (td->td_proc != p)
  354                         return (EPERM);
  355                 p->p_flag2 &= ~(P2_NOTRACE | P2_NOTRACE_EXEC);
  356                 break;
  357         case PROC_TRACE_CTL_DISABLE_EXEC:
  358                 p->p_flag2 |= P2_NOTRACE_EXEC | P2_NOTRACE;
  359                 break;
  360         case PROC_TRACE_CTL_DISABLE:
  361                 if ((p->p_flag2 & P2_NOTRACE_EXEC) != 0) {
  362                         KASSERT((p->p_flag2 & P2_NOTRACE) != 0,
  363                             ("dandling P2_NOTRACE_EXEC"));
  364                         if (td->td_proc != p)
  365                                 return (EPERM);
  366                         p->p_flag2 &= ~P2_NOTRACE_EXEC;
  367                 } else {
  368                         p->p_flag2 |= P2_NOTRACE;
  369                 }
  370                 break;
  371         default:
  372                 return (EINVAL);
  373         }
  374         return (0);
  375 }
  376 
  377 static int
  378 trace_status(struct thread *td, struct proc *p, int *data)
  379 {
  380 
  381         if ((p->p_flag2 & P2_NOTRACE) != 0) {
  382                 KASSERT((p->p_flag & P_TRACED) == 0,
  383                     ("%d traced but tracing disabled", p->p_pid));
  384                 *data = -1;
  385         } else if ((p->p_flag & P_TRACED) != 0) {
  386                 *data = p->p_pptr->p_pid;
  387         } else {
  388                 *data = 0;
  389         }
  390         return (0);
  391 }
  392 
  393 static int
  394 trapcap_ctl(struct thread *td, struct proc *p, int state)
  395 {
  396 
  397         PROC_LOCK_ASSERT(p, MA_OWNED);
  398 
  399         switch (state) {
  400         case PROC_TRAPCAP_CTL_ENABLE:
  401                 p->p_flag2 |= P2_TRAPCAP;
  402                 break;
  403         case PROC_TRAPCAP_CTL_DISABLE:
  404                 p->p_flag2 &= ~P2_TRAPCAP;
  405                 break;
  406         default:
  407                 return (EINVAL);
  408         }
  409         return (0);
  410 }
  411 
  412 static int
  413 trapcap_status(struct thread *td, struct proc *p, int *data)
  414 {
  415 
  416         *data = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE :
  417             PROC_TRAPCAP_CTL_DISABLE;
  418         return (0);
  419 }
  420 
  421 static int
  422 aslr_ctl(struct thread *td, struct proc *p, int state)
  423 {
  424 
  425         PROC_LOCK_ASSERT(p, MA_OWNED);
  426 
  427         switch (state) {
  428         case PROC_ASLR_FORCE_ENABLE:
  429                 p->p_flag2 &= ~P2_ASLR_DISABLE;
  430                 p->p_flag2 |= P2_ASLR_ENABLE;
  431                 break;
  432         case PROC_ASLR_FORCE_DISABLE:
  433                 p->p_flag2 |= P2_ASLR_DISABLE;
  434                 p->p_flag2 &= ~P2_ASLR_ENABLE;
  435                 break;
  436         case PROC_ASLR_NOFORCE:
  437                 p->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE);
  438                 break;
  439         default:
  440                 return (EINVAL);
  441         }
  442         return (0);
  443 }
  444 
  445 static int
  446 aslr_status(struct thread *td, struct proc *p, int *data)
  447 {
  448         struct vmspace *vm;
  449         int d;
  450 
  451         switch (p->p_flag2 & (P2_ASLR_ENABLE | P2_ASLR_DISABLE)) {
  452         case 0:
  453                 d = PROC_ASLR_NOFORCE;
  454                 break;
  455         case P2_ASLR_ENABLE:
  456                 d = PROC_ASLR_FORCE_ENABLE;
  457                 break;
  458         case P2_ASLR_DISABLE:
  459                 d = PROC_ASLR_FORCE_DISABLE;
  460                 break;
  461         }
  462         if ((p->p_flag & P_WEXIT) == 0) {
  463                 _PHOLD(p);
  464                 PROC_UNLOCK(p);
  465                 vm = vmspace_acquire_ref(p);
  466                 if (vm != NULL) {
  467                         if ((vm->vm_map.flags & MAP_ASLR) != 0)
  468                                 d |= PROC_ASLR_ACTIVE;
  469                         vmspace_free(vm);
  470                 }
  471                 PROC_LOCK(p);
  472                 _PRELE(p);
  473         }
  474         *data = d;
  475         return (0);
  476 }
  477 
  478 static int
  479 stackgap_ctl(struct thread *td, struct proc *p, int state)
  480 {
  481         PROC_LOCK_ASSERT(p, MA_OWNED);
  482 
  483         if ((state & ~(PROC_STACKGAP_ENABLE | PROC_STACKGAP_DISABLE |
  484             PROC_STACKGAP_ENABLE_EXEC | PROC_STACKGAP_DISABLE_EXEC)) != 0)
  485                 return (EINVAL);
  486         switch (state & (PROC_STACKGAP_ENABLE | PROC_STACKGAP_DISABLE)) {
  487         case PROC_STACKGAP_ENABLE:
  488                 if ((p->p_flag2 & P2_STKGAP_DISABLE) != 0)
  489                         return (EINVAL);
  490                 break;
  491         case PROC_STACKGAP_DISABLE:
  492                 p->p_flag2 |= P2_STKGAP_DISABLE;
  493                 break;
  494         case 0:
  495                 break;
  496         default:
  497                 return (EINVAL);
  498         }
  499         switch (state & (PROC_STACKGAP_ENABLE_EXEC |
  500             PROC_STACKGAP_DISABLE_EXEC)) {
  501         case PROC_STACKGAP_ENABLE_EXEC:
  502                 p->p_flag2 &= ~P2_STKGAP_DISABLE_EXEC;
  503                 break;
  504         case PROC_STACKGAP_DISABLE_EXEC:
  505                 p->p_flag2 |= P2_STKGAP_DISABLE_EXEC;
  506                 break;
  507         case 0:
  508                 break;
  509         default:
  510                 return (EINVAL);
  511         }
  512         return (0);
  513 }
  514 
  515 static int
  516 stackgap_status(struct thread *td, struct proc *p, int *data)
  517 {
  518         PROC_LOCK_ASSERT(p, MA_OWNED);
  519 
  520         *data = (p->p_flag2 & P2_STKGAP_DISABLE) != 0 ? PROC_STACKGAP_DISABLE :
  521             PROC_STACKGAP_ENABLE;
  522         *data |= (p->p_flag2 & P2_STKGAP_DISABLE_EXEC) != 0 ?
  523             PROC_STACKGAP_DISABLE_EXEC : PROC_STACKGAP_ENABLE_EXEC;
  524         return (0);
  525 }
  526 
  527 #ifndef _SYS_SYSPROTO_H_
  528 struct procctl_args {
  529         idtype_t idtype;
  530         id_t    id;
  531         int     com;
  532         void    *data;
  533 };
  534 #endif
  535 /* ARGSUSED */
  536 int
  537 sys_procctl(struct thread *td, struct procctl_args *uap)
  538 {
  539         void *data;
  540         union {
  541                 struct procctl_reaper_status rs;
  542                 struct procctl_reaper_pids rp;
  543                 struct procctl_reaper_kill rk;
  544         } x;
  545         int error, error1, flags, signum;
  546 
  547         if (uap->com >= PROC_PROCCTL_MD_MIN)
  548                 return (cpu_procctl(td, uap->idtype, uap->id,
  549                     uap->com, uap->data));
  550 
  551         switch (uap->com) {
  552         case PROC_ASLR_CTL:
  553         case PROC_SPROTECT:
  554         case PROC_STACKGAP_CTL:
  555         case PROC_TRACE_CTL:
  556         case PROC_TRAPCAP_CTL:
  557                 error = copyin(uap->data, &flags, sizeof(flags));
  558                 if (error != 0)
  559                         return (error);
  560                 data = &flags;
  561                 break;
  562         case PROC_REAP_ACQUIRE:
  563         case PROC_REAP_RELEASE:
  564                 if (uap->data != NULL)
  565                         return (EINVAL);
  566                 data = NULL;
  567                 break;
  568         case PROC_REAP_STATUS:
  569                 data = &x.rs;
  570                 break;
  571         case PROC_REAP_GETPIDS:
  572                 error = copyin(uap->data, &x.rp, sizeof(x.rp));
  573                 if (error != 0)
  574                         return (error);
  575                 data = &x.rp;
  576                 break;
  577         case PROC_REAP_KILL:
  578                 error = copyin(uap->data, &x.rk, sizeof(x.rk));
  579                 if (error != 0)
  580                         return (error);
  581                 data = &x.rk;
  582                 break;
  583         case PROC_ASLR_STATUS:
  584         case PROC_STACKGAP_STATUS:
  585         case PROC_TRACE_STATUS:
  586         case PROC_TRAPCAP_STATUS:
  587                 data = &flags;
  588                 break;
  589         case PROC_PDEATHSIG_CTL:
  590                 error = copyin(uap->data, &signum, sizeof(signum));
  591                 if (error != 0)
  592                         return (error);
  593                 data = &signum;
  594                 break;
  595         case PROC_PDEATHSIG_STATUS:
  596                 data = &signum;
  597                 break;
  598         default:
  599                 return (EINVAL);
  600         }
  601         error = kern_procctl(td, uap->idtype, uap->id, uap->com, data);
  602         switch (uap->com) {
  603         case PROC_REAP_STATUS:
  604                 if (error == 0)
  605                         error = copyout(&x.rs, uap->data, sizeof(x.rs));
  606                 break;
  607         case PROC_REAP_KILL:
  608                 error1 = copyout(&x.rk, uap->data, sizeof(x.rk));
  609                 if (error == 0)
  610                         error = error1;
  611                 break;
  612         case PROC_ASLR_STATUS:
  613         case PROC_STACKGAP_STATUS:
  614         case PROC_TRACE_STATUS:
  615         case PROC_TRAPCAP_STATUS:
  616                 if (error == 0)
  617                         error = copyout(&flags, uap->data, sizeof(flags));
  618                 break;
  619         case PROC_PDEATHSIG_STATUS:
  620                 if (error == 0)
  621                         error = copyout(&signum, uap->data, sizeof(signum));
  622                 break;
  623         }
  624         return (error);
  625 }
  626 
  627 static int
  628 kern_procctl_single(struct thread *td, struct proc *p, int com, void *data)
  629 {
  630 
  631         PROC_LOCK_ASSERT(p, MA_OWNED);
  632         switch (com) {
  633         case PROC_ASLR_CTL:
  634                 return (aslr_ctl(td, p, *(int *)data));
  635         case PROC_ASLR_STATUS:
  636                 return (aslr_status(td, p, data));
  637         case PROC_SPROTECT:
  638                 return (protect_set(td, p, *(int *)data));
  639         case PROC_STACKGAP_CTL:
  640                 return (stackgap_ctl(td, p, *(int *)data));
  641         case PROC_STACKGAP_STATUS:
  642                 return (stackgap_status(td, p, data));
  643         case PROC_REAP_ACQUIRE:
  644                 return (reap_acquire(td, p));
  645         case PROC_REAP_RELEASE:
  646                 return (reap_release(td, p));
  647         case PROC_REAP_STATUS:
  648                 return (reap_status(td, p, data));
  649         case PROC_REAP_GETPIDS:
  650                 return (reap_getpids(td, p, data));
  651         case PROC_REAP_KILL:
  652                 return (reap_kill(td, p, data));
  653         case PROC_TRACE_CTL:
  654                 return (trace_ctl(td, p, *(int *)data));
  655         case PROC_TRACE_STATUS:
  656                 return (trace_status(td, p, data));
  657         case PROC_TRAPCAP_CTL:
  658                 return (trapcap_ctl(td, p, *(int *)data));
  659         case PROC_TRAPCAP_STATUS:
  660                 return (trapcap_status(td, p, data));
  661         default:
  662                 return (EINVAL);
  663         }
  664 }
  665 
  666 int
  667 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
  668 {
  669         struct pgrp *pg;
  670         struct proc *p;
  671         int error, first_error, ok;
  672         int signum;
  673         bool tree_locked;
  674 
  675         switch (com) {
  676         case PROC_ASLR_CTL:
  677         case PROC_ASLR_STATUS:
  678         case PROC_REAP_ACQUIRE:
  679         case PROC_REAP_RELEASE:
  680         case PROC_REAP_STATUS:
  681         case PROC_REAP_GETPIDS:
  682         case PROC_REAP_KILL:
  683         case PROC_STACKGAP_CTL:
  684         case PROC_STACKGAP_STATUS:
  685         case PROC_TRACE_STATUS:
  686         case PROC_TRAPCAP_STATUS:
  687         case PROC_PDEATHSIG_CTL:
  688         case PROC_PDEATHSIG_STATUS:
  689                 if (idtype != P_PID)
  690                         return (EINVAL);
  691         }
  692 
  693         switch (com) {
  694         case PROC_PDEATHSIG_CTL:
  695                 signum = *(int *)data;
  696                 p = td->td_proc;
  697                 if ((id != 0 && id != p->p_pid) ||
  698                     (signum != 0 && !_SIG_VALID(signum)))
  699                         return (EINVAL);
  700                 PROC_LOCK(p);
  701                 p->p_pdeathsig = signum;
  702                 PROC_UNLOCK(p);
  703                 return (0);
  704         case PROC_PDEATHSIG_STATUS:
  705                 p = td->td_proc;
  706                 if (id != 0 && id != p->p_pid)
  707                         return (EINVAL);
  708                 PROC_LOCK(p);
  709                 *(int *)data = p->p_pdeathsig;
  710                 PROC_UNLOCK(p);
  711                 return (0);
  712         }
  713 
  714         switch (com) {
  715         case PROC_SPROTECT:
  716         case PROC_REAP_STATUS:
  717         case PROC_REAP_GETPIDS:
  718         case PROC_REAP_KILL:
  719         case PROC_TRACE_CTL:
  720         case PROC_TRAPCAP_CTL:
  721                 sx_slock(&proctree_lock);
  722                 tree_locked = true;
  723                 break;
  724         case PROC_REAP_ACQUIRE:
  725         case PROC_REAP_RELEASE:
  726                 sx_xlock(&proctree_lock);
  727                 tree_locked = true;
  728                 break;
  729         case PROC_ASLR_CTL:
  730         case PROC_ASLR_STATUS:
  731         case PROC_STACKGAP_CTL:
  732         case PROC_STACKGAP_STATUS:
  733         case PROC_TRACE_STATUS:
  734         case PROC_TRAPCAP_STATUS:
  735                 tree_locked = false;
  736                 break;
  737         default:
  738                 return (EINVAL);
  739         }
  740 
  741         switch (idtype) {
  742         case P_PID:
  743                 if (id == 0) {
  744                         p = td->td_proc;
  745                         error = 0;
  746                         PROC_LOCK(p);
  747                 } else {
  748                         p = pfind(id);
  749                         if (p == NULL) {
  750                                 error = ESRCH;
  751                                 break;
  752                         }
  753                         error = p_cansee(td, p);
  754                 }
  755                 if (error == 0)
  756                         error = kern_procctl_single(td, p, com, data);
  757                 PROC_UNLOCK(p);
  758                 break;
  759         case P_PGID:
  760                 /*
  761                  * Attempt to apply the operation to all members of the
  762                  * group.  Ignore processes in the group that can't be
  763                  * seen.  Ignore errors so long as at least one process is
  764                  * able to complete the request successfully.
  765                  */
  766                 pg = pgfind(id);
  767                 if (pg == NULL) {
  768                         error = ESRCH;
  769                         break;
  770                 }
  771                 PGRP_UNLOCK(pg);
  772                 ok = 0;
  773                 first_error = 0;
  774                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  775                         PROC_LOCK(p);
  776                         if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) {
  777                                 PROC_UNLOCK(p);
  778                                 continue;
  779                         }
  780                         error = kern_procctl_single(td, p, com, data);
  781                         PROC_UNLOCK(p);
  782                         if (error == 0)
  783                                 ok = 1;
  784                         else if (first_error == 0)
  785                                 first_error = error;
  786                 }
  787                 if (ok)
  788                         error = 0;
  789                 else if (first_error != 0)
  790                         error = first_error;
  791                 else
  792                         /*
  793                          * Was not able to see any processes in the
  794                          * process group.
  795                          */
  796                         error = ESRCH;
  797                 break;
  798         default:
  799                 error = EINVAL;
  800                 break;
  801         }
  802         if (tree_locked)
  803                 sx_unlock(&proctree_lock);
  804         return (error);
  805 }

Cache object: 0c5f150642d76b84d49c8c2b75c9b61a


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