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_resource.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kern_resource.c,v 1.164 2011/05/14 17:57:05 rmind Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1982, 1986, 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)kern_resource.c     8.8 (Berkeley) 2/14/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.164 2011/05/14 17:57:05 rmind Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/file.h>
   46 #include <sys/resourcevar.h>
   47 #include <sys/kmem.h>
   48 #include <sys/namei.h>
   49 #include <sys/pool.h>
   50 #include <sys/proc.h>
   51 #include <sys/sysctl.h>
   52 #include <sys/timevar.h>
   53 #include <sys/kauth.h>
   54 #include <sys/atomic.h>
   55 #include <sys/mount.h>
   56 #include <sys/syscallargs.h>
   57 #include <sys/atomic.h>
   58 
   59 #include <uvm/uvm_extern.h>
   60 
   61 /*
   62  * Maximum process data and stack limits.
   63  * They are variables so they are patchable.
   64  */
   65 const rlim_t            maxdmap = MAXDSIZ;
   66 const rlim_t            maxsmap = MAXSSIZ;
   67 
   68 static pool_cache_t     plimit_cache    __read_mostly;
   69 static pool_cache_t     pstats_cache    __read_mostly;
   70 
   71 static kauth_listener_t resource_listener;
   72 static struct sysctllog *proc_sysctllog;
   73 
   74 static int      donice(struct lwp *, struct proc *, int);
   75 static void     sysctl_proc_setup(void);
   76 
   77 static int
   78 resource_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
   79     void *arg0, void *arg1, void *arg2, void *arg3)
   80 {
   81         struct proc *p;
   82         int result;
   83 
   84         result = KAUTH_RESULT_DEFER;
   85         p = arg0;
   86 
   87         switch (action) {
   88         case KAUTH_PROCESS_NICE:
   89                 if (kauth_cred_geteuid(cred) != kauth_cred_geteuid(p->p_cred) &&
   90                     kauth_cred_getuid(cred) != kauth_cred_geteuid(p->p_cred)) {
   91                         break;
   92                 }
   93 
   94                 if ((u_long)arg1 >= p->p_nice)
   95                         result = KAUTH_RESULT_ALLOW;
   96 
   97                 break;
   98 
   99         case KAUTH_PROCESS_RLIMIT: {
  100                 enum kauth_process_req req;
  101 
  102                 req = (enum kauth_process_req)(unsigned long)arg1;
  103 
  104                 switch (req) {
  105                 case KAUTH_REQ_PROCESS_RLIMIT_GET:
  106                         result = KAUTH_RESULT_ALLOW;
  107                         break;
  108 
  109                 case KAUTH_REQ_PROCESS_RLIMIT_SET: {
  110                         struct rlimit *new_rlimit;
  111                         u_long which;
  112 
  113                         if ((p != curlwp->l_proc) &&
  114                             (proc_uidmatch(cred, p->p_cred) != 0))
  115                                 break;
  116 
  117                         new_rlimit = arg2;
  118                         which = (u_long)arg3;
  119 
  120                         if (new_rlimit->rlim_max <= p->p_rlimit[which].rlim_max)
  121                                 result = KAUTH_RESULT_ALLOW;
  122 
  123                         break;
  124                         }
  125 
  126                 default:
  127                         break;
  128                 }
  129 
  130                 break;
  131         }
  132 
  133         default:
  134                 break;
  135         }
  136 
  137         return result;
  138 }
  139 
  140 void
  141 resource_init(void)
  142 {
  143 
  144         plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0,
  145             "plimitpl", NULL, IPL_NONE, NULL, NULL, NULL);
  146         pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0,
  147             "pstatspl", NULL, IPL_NONE, NULL, NULL, NULL);
  148 
  149         resource_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
  150             resource_listener_cb, NULL);
  151 
  152         sysctl_proc_setup();
  153 }
  154 
  155 /*
  156  * Resource controls and accounting.
  157  */
  158 
  159 int
  160 sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap,
  161     register_t *retval)
  162 {
  163         /* {
  164                 syscallarg(int) which;
  165                 syscallarg(id_t) who;
  166         } */
  167         struct proc *curp = l->l_proc, *p;
  168         id_t who = SCARG(uap, who);
  169         int low = NZERO + PRIO_MAX + 1;
  170 
  171         mutex_enter(proc_lock);
  172         switch (SCARG(uap, which)) {
  173         case PRIO_PROCESS:
  174                 p = who ? proc_find(who) : curp;;
  175                 if (p != NULL)
  176                         low = p->p_nice;
  177                 break;
  178 
  179         case PRIO_PGRP: {
  180                 struct pgrp *pg;
  181 
  182                 if (who == 0)
  183                         pg = curp->p_pgrp;
  184                 else if ((pg = pgrp_find(who)) == NULL)
  185                         break;
  186                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  187                         if (p->p_nice < low)
  188                                 low = p->p_nice;
  189                 }
  190                 break;
  191         }
  192 
  193         case PRIO_USER:
  194                 if (who == 0)
  195                         who = (int)kauth_cred_geteuid(l->l_cred);
  196                 PROCLIST_FOREACH(p, &allproc) {
  197                         mutex_enter(p->p_lock);
  198                         if (kauth_cred_geteuid(p->p_cred) ==
  199                             (uid_t)who && p->p_nice < low)
  200                                 low = p->p_nice;
  201                         mutex_exit(p->p_lock);
  202                 }
  203                 break;
  204 
  205         default:
  206                 mutex_exit(proc_lock);
  207                 return EINVAL;
  208         }
  209         mutex_exit(proc_lock);
  210 
  211         if (low == NZERO + PRIO_MAX + 1) {
  212                 return ESRCH;
  213         }
  214         *retval = low - NZERO;
  215         return 0;
  216 }
  217 
  218 int
  219 sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap,
  220     register_t *retval)
  221 {
  222         /* {
  223                 syscallarg(int) which;
  224                 syscallarg(id_t) who;
  225                 syscallarg(int) prio;
  226         } */
  227         struct proc *curp = l->l_proc, *p;
  228         id_t who = SCARG(uap, who);
  229         int found = 0, error = 0;
  230 
  231         mutex_enter(proc_lock);
  232         switch (SCARG(uap, which)) {
  233         case PRIO_PROCESS:
  234                 p = who ? proc_find(who) : curp;
  235                 if (p != NULL) {
  236                         mutex_enter(p->p_lock);
  237                         found++;
  238                         error = donice(l, p, SCARG(uap, prio));
  239                         mutex_exit(p->p_lock);
  240                 }
  241                 break;
  242 
  243         case PRIO_PGRP: {
  244                 struct pgrp *pg;
  245 
  246                 if (who == 0)
  247                         pg = curp->p_pgrp;
  248                 else if ((pg = pgrp_find(who)) == NULL)
  249                         break;
  250                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  251                         mutex_enter(p->p_lock);
  252                         found++;
  253                         error = donice(l, p, SCARG(uap, prio));
  254                         mutex_exit(p->p_lock);
  255                         if (error)
  256                                 break;
  257                 }
  258                 break;
  259         }
  260 
  261         case PRIO_USER:
  262                 if (who == 0)
  263                         who = (int)kauth_cred_geteuid(l->l_cred);
  264                 PROCLIST_FOREACH(p, &allproc) {
  265                         mutex_enter(p->p_lock);
  266                         if (kauth_cred_geteuid(p->p_cred) ==
  267                             (uid_t)SCARG(uap, who)) {
  268                                 found++;
  269                                 error = donice(l, p, SCARG(uap, prio));
  270                         }
  271                         mutex_exit(p->p_lock);
  272                         if (error)
  273                                 break;
  274                 }
  275                 break;
  276 
  277         default:
  278                 mutex_exit(proc_lock);
  279                 return EINVAL;
  280         }
  281         mutex_exit(proc_lock);
  282 
  283         return (found == 0) ? ESRCH : error;
  284 }
  285 
  286 /*
  287  * Renice a process.
  288  *
  289  * Call with the target process' credentials locked.
  290  */
  291 static int
  292 donice(struct lwp *l, struct proc *chgp, int n)
  293 {
  294         kauth_cred_t cred = l->l_cred;
  295 
  296         KASSERT(mutex_owned(chgp->p_lock));
  297 
  298         if (kauth_cred_geteuid(cred) && kauth_cred_getuid(cred) &&
  299             kauth_cred_geteuid(cred) != kauth_cred_geteuid(chgp->p_cred) &&
  300             kauth_cred_getuid(cred) != kauth_cred_geteuid(chgp->p_cred))
  301                 return EPERM;
  302 
  303         if (n > PRIO_MAX) {
  304                 n = PRIO_MAX;
  305         }
  306         if (n < PRIO_MIN) {
  307                 n = PRIO_MIN;
  308         }
  309         n += NZERO;
  310 
  311         if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp,
  312             KAUTH_ARG(n), NULL, NULL)) {
  313                 return EACCES;
  314         }
  315 
  316         sched_nice(chgp, n);
  317         return 0;
  318 }
  319 
  320 int
  321 sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap,
  322     register_t *retval)
  323 {
  324         /* {
  325                 syscallarg(int) which;
  326                 syscallarg(const struct rlimit *) rlp;
  327         } */
  328         int error, which = SCARG(uap, which);
  329         struct rlimit alim;
  330 
  331         error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
  332         if (error) {
  333                 return error;
  334         }
  335         return dosetrlimit(l, l->l_proc, which, &alim);
  336 }
  337 
  338 int
  339 dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
  340 {
  341         struct rlimit *alimp;
  342         int error;
  343 
  344         if ((u_int)which >= RLIM_NLIMITS)
  345                 return EINVAL;
  346 
  347         if (limp->rlim_cur > limp->rlim_max) {
  348                 /*
  349                  * This is programming error. According to SUSv2, we should
  350                  * return error in this case.
  351                  */
  352                 return EINVAL;
  353         }
  354 
  355         alimp = &p->p_rlimit[which];
  356         /* if we don't change the value, no need to limcopy() */
  357         if (limp->rlim_cur == alimp->rlim_cur &&
  358             limp->rlim_max == alimp->rlim_max)
  359                 return 0;
  360 
  361         error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
  362             p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which));
  363         if (error)
  364                 return error;
  365 
  366         lim_privatise(p);
  367         /* p->p_limit is now unchangeable */
  368         alimp = &p->p_rlimit[which];
  369 
  370         switch (which) {
  371 
  372         case RLIMIT_DATA:
  373                 if (limp->rlim_cur > maxdmap)
  374                         limp->rlim_cur = maxdmap;
  375                 if (limp->rlim_max > maxdmap)
  376                         limp->rlim_max = maxdmap;
  377                 break;
  378 
  379         case RLIMIT_STACK:
  380                 if (limp->rlim_cur > maxsmap)
  381                         limp->rlim_cur = maxsmap;
  382                 if (limp->rlim_max > maxsmap)
  383                         limp->rlim_max = maxsmap;
  384 
  385                 /*
  386                  * Return EINVAL if the new stack size limit is lower than
  387                  * current usage. Otherwise, the process would get SIGSEGV the
  388                  * moment it would try to access anything on it's current stack.
  389                  * This conforms to SUSv2.
  390                  */
  391                 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE ||
  392                     limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) {
  393                         return EINVAL;
  394                 }
  395 
  396                 /*
  397                  * Stack is allocated to the max at exec time with
  398                  * only "rlim_cur" bytes accessible (In other words,
  399                  * allocates stack dividing two contiguous regions at
  400                  * "rlim_cur" bytes boundary).
  401                  *
  402                  * Since allocation is done in terms of page, roundup
  403                  * "rlim_cur" (otherwise, contiguous regions
  404                  * overlap).  If stack limit is going up make more
  405                  * accessible, if going down make inaccessible.
  406                  */
  407                 limp->rlim_cur = round_page(limp->rlim_cur);
  408                 if (limp->rlim_cur != alimp->rlim_cur) {
  409                         vaddr_t addr;
  410                         vsize_t size;
  411                         vm_prot_t prot;
  412 
  413                         if (limp->rlim_cur > alimp->rlim_cur) {
  414                                 prot = VM_PROT_READ | VM_PROT_WRITE;
  415                                 size = limp->rlim_cur - alimp->rlim_cur;
  416                                 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
  417                                     limp->rlim_cur;
  418                         } else {
  419                                 prot = VM_PROT_NONE;
  420                                 size = alimp->rlim_cur - limp->rlim_cur;
  421                                 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
  422                                      alimp->rlim_cur;
  423                         }
  424                         (void) uvm_map_protect(&p->p_vmspace->vm_map,
  425                             addr, addr+size, prot, false);
  426                 }
  427                 break;
  428 
  429         case RLIMIT_NOFILE:
  430                 if (limp->rlim_cur > maxfiles)
  431                         limp->rlim_cur = maxfiles;
  432                 if (limp->rlim_max > maxfiles)
  433                         limp->rlim_max = maxfiles;
  434                 break;
  435 
  436         case RLIMIT_NPROC:
  437                 if (limp->rlim_cur > maxproc)
  438                         limp->rlim_cur = maxproc;
  439                 if (limp->rlim_max > maxproc)
  440                         limp->rlim_max = maxproc;
  441                 break;
  442         }
  443 
  444         mutex_enter(&p->p_limit->pl_lock);
  445         *alimp = *limp;
  446         mutex_exit(&p->p_limit->pl_lock);
  447         return 0;
  448 }
  449 
  450 int
  451 sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap,
  452     register_t *retval)
  453 {
  454         /* {
  455                 syscallarg(int) which;
  456                 syscallarg(struct rlimit *) rlp;
  457         } */
  458         struct proc *p = l->l_proc;
  459         int which = SCARG(uap, which);
  460         struct rlimit rl;
  461 
  462         if ((u_int)which >= RLIM_NLIMITS)
  463                 return EINVAL;
  464 
  465         mutex_enter(p->p_lock);
  466         memcpy(&rl, &p->p_rlimit[which], sizeof(rl));
  467         mutex_exit(p->p_lock);
  468 
  469         return copyout(&rl, SCARG(uap, rlp), sizeof(rl));
  470 }
  471 
  472 /*
  473  * Transform the running time and tick information in proc p into user,
  474  * system, and interrupt time usage.
  475  *
  476  * Should be called with p->p_lock held unless called from exit1().
  477  */
  478 void
  479 calcru(struct proc *p, struct timeval *up, struct timeval *sp,
  480     struct timeval *ip, struct timeval *rp)
  481 {
  482         uint64_t u, st, ut, it, tot;
  483         struct lwp *l;
  484         struct bintime tm;
  485         struct timeval tv;
  486 
  487         mutex_spin_enter(&p->p_stmutex);
  488         st = p->p_sticks;
  489         ut = p->p_uticks;
  490         it = p->p_iticks;
  491         mutex_spin_exit(&p->p_stmutex);
  492 
  493         tm = p->p_rtime;
  494 
  495         LIST_FOREACH(l, &p->p_lwps, l_sibling) {
  496                 lwp_lock(l);
  497                 bintime_add(&tm, &l->l_rtime);
  498                 if ((l->l_pflag & LP_RUNNING) != 0) {
  499                         struct bintime diff;
  500                         /*
  501                          * Adjust for the current time slice.  This is
  502                          * actually fairly important since the error
  503                          * here is on the order of a time quantum,
  504                          * which is much greater than the sampling
  505                          * error.
  506                          */
  507                         binuptime(&diff);
  508                         bintime_sub(&diff, &l->l_stime);
  509                         bintime_add(&tm, &diff);
  510                 }
  511                 lwp_unlock(l);
  512         }
  513 
  514         tot = st + ut + it;
  515         bintime2timeval(&tm, &tv);
  516         u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec;
  517 
  518         if (tot == 0) {
  519                 /* No ticks, so can't use to share time out, split 50-50 */
  520                 st = ut = u / 2;
  521         } else {
  522                 st = (u * st) / tot;
  523                 ut = (u * ut) / tot;
  524         }
  525         if (sp != NULL) {
  526                 sp->tv_sec = st / 1000000;
  527                 sp->tv_usec = st % 1000000;
  528         }
  529         if (up != NULL) {
  530                 up->tv_sec = ut / 1000000;
  531                 up->tv_usec = ut % 1000000;
  532         }
  533         if (ip != NULL) {
  534                 if (it != 0)
  535                         it = (u * it) / tot;
  536                 ip->tv_sec = it / 1000000;
  537                 ip->tv_usec = it % 1000000;
  538         }
  539         if (rp != NULL) {
  540                 *rp = tv;
  541         }
  542 }
  543 
  544 int
  545 sys___getrusage50(struct lwp *l, const struct sys___getrusage50_args *uap,
  546     register_t *retval)
  547 {
  548         /* {
  549                 syscallarg(int) who;
  550                 syscallarg(struct rusage *) rusage;
  551         } */
  552         struct rusage ru;
  553         struct proc *p = l->l_proc;
  554 
  555         switch (SCARG(uap, who)) {
  556         case RUSAGE_SELF:
  557                 mutex_enter(p->p_lock);
  558                 memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
  559                 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
  560                 rulwps(p, &ru);
  561                 mutex_exit(p->p_lock);
  562                 break;
  563 
  564         case RUSAGE_CHILDREN:
  565                 mutex_enter(p->p_lock);
  566                 memcpy(&ru, &p->p_stats->p_cru, sizeof(ru));
  567                 mutex_exit(p->p_lock);
  568                 break;
  569 
  570         default:
  571                 return EINVAL;
  572         }
  573 
  574         return copyout(&ru, SCARG(uap, rusage), sizeof(ru));
  575 }
  576 
  577 void
  578 ruadd(struct rusage *ru, struct rusage *ru2)
  579 {
  580         long *ip, *ip2;
  581         int i;
  582 
  583         timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
  584         timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
  585         if (ru->ru_maxrss < ru2->ru_maxrss)
  586                 ru->ru_maxrss = ru2->ru_maxrss;
  587         ip = &ru->ru_first; ip2 = &ru2->ru_first;
  588         for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
  589                 *ip++ += *ip2++;
  590 }
  591 
  592 void
  593 rulwps(proc_t *p, struct rusage *ru)
  594 {
  595         lwp_t *l;
  596 
  597         KASSERT(mutex_owned(p->p_lock));
  598 
  599         LIST_FOREACH(l, &p->p_lwps, l_sibling) {
  600                 ruadd(ru, &l->l_ru);
  601                 ru->ru_nvcsw += (l->l_ncsw - l->l_nivcsw);
  602                 ru->ru_nivcsw += l->l_nivcsw;
  603         }
  604 }
  605 
  606 /*
  607  * lim_copy: make a copy of the plimit structure.
  608  *
  609  * We use copy-on-write after fork, and copy when a limit is changed.
  610  */
  611 struct plimit *
  612 lim_copy(struct plimit *lim)
  613 {
  614         struct plimit *newlim;
  615         char *corename;
  616         size_t alen, len;
  617 
  618         newlim = pool_cache_get(plimit_cache, PR_WAITOK);
  619         mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
  620         newlim->pl_writeable = false;
  621         newlim->pl_refcnt = 1;
  622         newlim->pl_sv_limit = NULL;
  623 
  624         mutex_enter(&lim->pl_lock);
  625         memcpy(newlim->pl_rlimit, lim->pl_rlimit,
  626             sizeof(struct rlimit) * RLIM_NLIMITS);
  627 
  628         /*
  629          * Note: the common case is a use of default core name.
  630          */
  631         alen = 0;
  632         corename = NULL;
  633         for (;;) {
  634                 if (lim->pl_corename == defcorename) {
  635                         newlim->pl_corename = defcorename;
  636                         newlim->pl_cnlen = 0;
  637                         break;
  638                 }
  639                 len = lim->pl_cnlen;
  640                 if (len == alen) {
  641                         newlim->pl_corename = corename;
  642                         newlim->pl_cnlen = len;
  643                         memcpy(corename, lim->pl_corename, len);
  644                         corename = NULL;
  645                         break;
  646                 }
  647                 mutex_exit(&lim->pl_lock);
  648                 if (corename) {
  649                         kmem_free(corename, alen);
  650                 }
  651                 alen = len;
  652                 corename = kmem_alloc(alen, KM_SLEEP);
  653                 mutex_enter(&lim->pl_lock);
  654         }
  655         mutex_exit(&lim->pl_lock);
  656 
  657         if (corename) {
  658                 kmem_free(corename, alen);
  659         }
  660         return newlim;
  661 }
  662 
  663 void
  664 lim_addref(struct plimit *lim)
  665 {
  666         atomic_inc_uint(&lim->pl_refcnt);
  667 }
  668 
  669 /*
  670  * lim_privatise: give a process its own private plimit structure.
  671  */
  672 void
  673 lim_privatise(proc_t *p)
  674 {
  675         struct plimit *lim = p->p_limit, *newlim;
  676 
  677         if (lim->pl_writeable) {
  678                 return;
  679         }
  680 
  681         newlim = lim_copy(lim);
  682 
  683         mutex_enter(p->p_lock);
  684         if (p->p_limit->pl_writeable) {
  685                 /* Other thread won the race. */
  686                 mutex_exit(p->p_lock);
  687                 lim_free(newlim);
  688                 return;
  689         }
  690 
  691         /*
  692          * Since p->p_limit can be accessed without locked held,
  693          * old limit structure must not be deleted yet.
  694          */
  695         newlim->pl_sv_limit = p->p_limit;
  696         newlim->pl_writeable = true;
  697         p->p_limit = newlim;
  698         mutex_exit(p->p_lock);
  699 }
  700 
  701 void
  702 lim_setcorename(proc_t *p, char *name, size_t len)
  703 {
  704         struct plimit *lim;
  705         char *oname;
  706         size_t olen;
  707 
  708         lim_privatise(p);
  709         lim = p->p_limit;
  710 
  711         mutex_enter(&lim->pl_lock);
  712         oname = lim->pl_corename;
  713         olen = lim->pl_cnlen;
  714         lim->pl_corename = name;
  715         lim->pl_cnlen = len;
  716         mutex_exit(&lim->pl_lock);
  717 
  718         if (oname != defcorename) {
  719                 kmem_free(oname, olen);
  720         }
  721 }
  722 
  723 void
  724 lim_free(struct plimit *lim)
  725 {
  726         struct plimit *sv_lim;
  727 
  728         do {
  729                 if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0) {
  730                         return;
  731                 }
  732                 if (lim->pl_corename != defcorename) {
  733                         kmem_free(lim->pl_corename, lim->pl_cnlen);
  734                 }
  735                 sv_lim = lim->pl_sv_limit;
  736                 mutex_destroy(&lim->pl_lock);
  737                 pool_cache_put(plimit_cache, lim);
  738         } while ((lim = sv_lim) != NULL);
  739 }
  740 
  741 struct pstats *
  742 pstatscopy(struct pstats *ps)
  743 {
  744         struct pstats *nps;
  745         size_t len;
  746 
  747         nps = pool_cache_get(pstats_cache, PR_WAITOK);
  748 
  749         len = (char *)&nps->pstat_endzero - (char *)&nps->pstat_startzero;
  750         memset(&nps->pstat_startzero, 0, len);
  751 
  752         len = (char *)&nps->pstat_endcopy - (char *)&nps->pstat_startcopy;
  753         memcpy(&nps->pstat_startcopy, &ps->pstat_startcopy, len);
  754 
  755         return nps;
  756 }
  757 
  758 void
  759 pstatsfree(struct pstats *ps)
  760 {
  761 
  762         pool_cache_put(pstats_cache, ps);
  763 }
  764 
  765 /*
  766  * sysctl_proc_findproc: a routine for sysctl proc subtree helpers that
  767  * need to pick a valid process by PID.
  768  *
  769  * => Hold a reference on the process, on success.
  770  */
  771 static int
  772 sysctl_proc_findproc(lwp_t *l, pid_t pid, proc_t **p2)
  773 {
  774         proc_t *p;
  775         int error;
  776 
  777         if (pid == PROC_CURPROC) {
  778                 p = l->l_proc;
  779         } else {
  780                 mutex_enter(proc_lock);
  781                 p = proc_find(pid);
  782                 if (p == NULL) {
  783                         mutex_exit(proc_lock);
  784                         return ESRCH;
  785                 }
  786         }
  787         error = rw_tryenter(&p->p_reflock, RW_READER) ? 0 : EBUSY;
  788         if (pid != PROC_CURPROC) {
  789                 mutex_exit(proc_lock);
  790         }
  791         *p2 = p;
  792         return error;
  793 }
  794 
  795 /*
  796  * sysctl_proc_corename: helper routine to get or set the core file name
  797  * for a process specified by PID.
  798  */
  799 static int
  800 sysctl_proc_corename(SYSCTLFN_ARGS)
  801 {
  802         struct proc *p;
  803         struct plimit *lim;
  804         char *cnbuf, *cname;
  805         struct sysctlnode node;
  806         size_t len;
  807         int error;
  808 
  809         /* First, validate the request. */
  810         if (namelen != 0 || name[-1] != PROC_PID_CORENAME)
  811                 return EINVAL;
  812 
  813         /* Find the process.  Hold a reference (p_reflock), if found. */
  814         error = sysctl_proc_findproc(l, (pid_t)name[-2], &p);
  815         if (error)
  816                 return error;
  817 
  818         /* XXX-elad */
  819         error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
  820             KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
  821         if (error) {
  822                 rw_exit(&p->p_reflock);
  823                 return error;
  824         }
  825 
  826         cnbuf = PNBUF_GET();
  827 
  828         if (newp == NULL) {
  829                 /* Get case: copy the core name into the buffer. */
  830                 error = kauth_authorize_process(l->l_cred,
  831                     KAUTH_PROCESS_CORENAME, p,
  832                     KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL);
  833                 if (error) {
  834                         goto done;
  835                 }
  836                 lim = p->p_limit;
  837                 mutex_enter(&lim->pl_lock);
  838                 strlcpy(cnbuf, lim->pl_corename, MAXPATHLEN);
  839                 mutex_exit(&lim->pl_lock);
  840         } else {
  841                 /* Set case: just use the temporary buffer. */
  842                 error = kauth_authorize_process(l->l_cred,
  843                     KAUTH_PROCESS_CORENAME, p,
  844                     KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cnbuf, NULL);
  845                 if (error) {
  846                         goto done;
  847                 }
  848         }
  849 
  850         node = *rnode;
  851         node.sysctl_data = cnbuf;
  852         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  853 
  854         /* Return if error, or if caller is only getting the core name. */
  855         if (error || newp == NULL) {
  856                 goto done;
  857         }
  858 
  859         /*
  860          * Validate new core name.  It must be either "core", "/core",
  861          * or end in ".core".
  862          */
  863         len = strlen(cnbuf);
  864         if ((len < 4 || strcmp(cnbuf + len - 4, "core") != 0) ||
  865             (len > 4 && cnbuf[len - 5] != '/' && cnbuf[len - 5] != '.')) {
  866                 error = EINVAL;
  867                 goto done;
  868         }
  869 
  870         /* Allocate, copy and set the new core name for plimit structure. */
  871         cname = kmem_alloc(++len, KM_NOSLEEP);
  872         if (cname == NULL) {
  873                 error = ENOMEM;
  874                 goto done;
  875         }
  876         memcpy(cname, cnbuf, len);
  877         lim_setcorename(p, cname, len);
  878 done:
  879         rw_exit(&p->p_reflock);
  880         PNBUF_PUT(cnbuf);
  881         return error;
  882 }
  883 
  884 /*
  885  * sysctl_proc_stop: helper routine for checking/setting the stop flags.
  886  */
  887 static int
  888 sysctl_proc_stop(SYSCTLFN_ARGS)
  889 {
  890         struct proc *p;
  891         int isset, flag, error = 0;
  892         struct sysctlnode node;
  893 
  894         if (namelen != 0)
  895                 return EINVAL;
  896 
  897         /* Find the process.  Hold a reference (p_reflock), if found. */
  898         error = sysctl_proc_findproc(l, (pid_t)name[-2], &p);
  899         if (error)
  900                 return error;
  901 
  902         /* XXX-elad */
  903         error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
  904             KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
  905         if (error) {
  906                 goto out;
  907         }
  908 
  909         /* Determine the flag. */
  910         switch (rnode->sysctl_num) {
  911         case PROC_PID_STOPFORK:
  912                 flag = PS_STOPFORK;
  913                 break;
  914         case PROC_PID_STOPEXEC:
  915                 flag = PS_STOPEXEC;
  916                 break;
  917         case PROC_PID_STOPEXIT:
  918                 flag = PS_STOPEXIT;
  919                 break;
  920         default:
  921                 error = EINVAL;
  922                 goto out;
  923         }
  924         isset = (p->p_flag & flag) ? 1 : 0;
  925         node = *rnode;
  926         node.sysctl_data = &isset;
  927         error = sysctl_lookup(SYSCTLFN_CALL(&node));
  928 
  929         /* Return if error, or if callers is only getting the flag. */
  930         if (error || newp == NULL) {
  931                 goto out;
  932         }
  933 
  934         /* Check if caller can set the flags. */
  935         error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG,
  936             p, KAUTH_ARG(flag), NULL, NULL);
  937         if (error) {
  938                 goto out;
  939         }
  940         mutex_enter(p->p_lock);
  941         if (isset) {
  942                 p->p_sflag |= flag;
  943         } else {
  944                 p->p_sflag &= ~flag;
  945         }
  946         mutex_exit(p->p_lock);
  947 out:
  948         rw_exit(&p->p_reflock);
  949         return error;
  950 }
  951 
  952 /*
  953  * sysctl_proc_plimit: helper routine to get/set rlimits of a process.
  954  */
  955 static int
  956 sysctl_proc_plimit(SYSCTLFN_ARGS)
  957 {
  958         struct proc *p;
  959         u_int limitno;
  960         int which, error = 0;
  961         struct rlimit alim;
  962         struct sysctlnode node;
  963 
  964         if (namelen != 0)
  965                 return EINVAL;
  966 
  967         which = name[-1];
  968         if (which != PROC_PID_LIMIT_TYPE_SOFT &&
  969             which != PROC_PID_LIMIT_TYPE_HARD)
  970                 return EINVAL;
  971 
  972         limitno = name[-2] - 1;
  973         if (limitno >= RLIM_NLIMITS)
  974                 return EINVAL;
  975 
  976         if (name[-3] != PROC_PID_LIMIT)
  977                 return EINVAL;
  978 
  979         /* Find the process.  Hold a reference (p_reflock), if found. */
  980         error = sysctl_proc_findproc(l, (pid_t)name[-4], &p);
  981         if (error)
  982                 return error;
  983 
  984         /* XXX-elad */
  985         error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
  986             KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
  987         if (error)
  988                 goto out;
  989 
  990         /* Check if caller can retrieve the limits. */
  991         if (newp == NULL) {
  992                 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
  993                     p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim,
  994                     KAUTH_ARG(which));
  995                 if (error)
  996                         goto out;
  997         }
  998 
  999         /* Retrieve the limits. */
 1000         node = *rnode;
 1001         memcpy(&alim, &p->p_rlimit[limitno], sizeof(alim));
 1002         if (which == PROC_PID_LIMIT_TYPE_HARD) {
 1003                 node.sysctl_data = &alim.rlim_max;
 1004         } else {
 1005                 node.sysctl_data = &alim.rlim_cur;
 1006         }
 1007         error = sysctl_lookup(SYSCTLFN_CALL(&node));
 1008 
 1009         /* Return if error, or if we are only retrieving the limits. */
 1010         if (error || newp == NULL) {
 1011                 goto out;
 1012         }
 1013         error = dosetrlimit(l, p, limitno, &alim);
 1014 out:
 1015         rw_exit(&p->p_reflock);
 1016         return error;
 1017 }
 1018 
 1019 /*
 1020  * Setup sysctl nodes.
 1021  */
 1022 static void
 1023 sysctl_proc_setup(void)
 1024 {
 1025 
 1026         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1027                        CTLFLAG_PERMANENT,
 1028                        CTLTYPE_NODE, "proc", NULL,
 1029                        NULL, 0, NULL, 0,
 1030                        CTL_PROC, CTL_EOL);
 1031         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1032                        CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
 1033                        CTLTYPE_NODE, "curproc",
 1034                        SYSCTL_DESCR("Per-process settings"),
 1035                        NULL, 0, NULL, 0,
 1036                        CTL_PROC, PROC_CURPROC, CTL_EOL);
 1037 
 1038         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1039                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
 1040                        CTLTYPE_STRING, "corename",
 1041                        SYSCTL_DESCR("Core file name"),
 1042                        sysctl_proc_corename, 0, NULL, MAXPATHLEN,
 1043                        CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
 1044         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1045                        CTLFLAG_PERMANENT,
 1046                        CTLTYPE_NODE, "rlimit",
 1047                        SYSCTL_DESCR("Process limits"),
 1048                        NULL, 0, NULL, 0,
 1049                        CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
 1050 
 1051 #define create_proc_plimit(s, n) do {                                   \
 1052         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,                  \
 1053                        CTLFLAG_PERMANENT,                               \
 1054                        CTLTYPE_NODE, s,                                 \
 1055                        SYSCTL_DESCR("Process " s " limits"),            \
 1056                        NULL, 0, NULL, 0,                                \
 1057                        CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
 1058                        CTL_EOL);                                        \
 1059         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,                  \
 1060                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
 1061                        CTLTYPE_QUAD, "soft",                            \
 1062                        SYSCTL_DESCR("Process soft " s " limit"),        \
 1063                        sysctl_proc_plimit, 0, NULL, 0,                  \
 1064                        CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
 1065                        PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL);              \
 1066         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,                  \
 1067                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
 1068                        CTLTYPE_QUAD, "hard",                            \
 1069                        SYSCTL_DESCR("Process hard " s " limit"),        \
 1070                        sysctl_proc_plimit, 0, NULL, 0,                  \
 1071                        CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
 1072                        PROC_PID_LIMIT_TYPE_HARD, CTL_EOL);              \
 1073         } while (0/*CONSTCOND*/)
 1074 
 1075         create_proc_plimit("cputime",           PROC_PID_LIMIT_CPU);
 1076         create_proc_plimit("filesize",          PROC_PID_LIMIT_FSIZE);
 1077         create_proc_plimit("datasize",          PROC_PID_LIMIT_DATA);
 1078         create_proc_plimit("stacksize",         PROC_PID_LIMIT_STACK);
 1079         create_proc_plimit("coredumpsize",      PROC_PID_LIMIT_CORE);
 1080         create_proc_plimit("memoryuse",         PROC_PID_LIMIT_RSS);
 1081         create_proc_plimit("memorylocked",      PROC_PID_LIMIT_MEMLOCK);
 1082         create_proc_plimit("maxproc",           PROC_PID_LIMIT_NPROC);
 1083         create_proc_plimit("descriptors",       PROC_PID_LIMIT_NOFILE);
 1084         create_proc_plimit("sbsize",            PROC_PID_LIMIT_SBSIZE);
 1085         create_proc_plimit("vmemoryuse",        PROC_PID_LIMIT_AS);
 1086 
 1087 #undef create_proc_plimit
 1088 
 1089         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1090                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
 1091                        CTLTYPE_INT, "stopfork",
 1092                        SYSCTL_DESCR("Stop process at fork(2)"),
 1093                        sysctl_proc_stop, 0, NULL, 0,
 1094                        CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
 1095         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1096                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
 1097                        CTLTYPE_INT, "stopexec",
 1098                        SYSCTL_DESCR("Stop process at execve(2)"),
 1099                        sysctl_proc_stop, 0, NULL, 0,
 1100                        CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
 1101         sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
 1102                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
 1103                        CTLTYPE_INT, "stopexit",
 1104                        SYSCTL_DESCR("Stop process before completing exit"),
 1105                        sysctl_proc_stop, 0, NULL, 0,
 1106                        CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
 1107 }

Cache object: bf391cec60dad6899c6ee4cb9f0861d0


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