1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_resource.c 7.10 (Berkeley) 03/17/91 7 */ 8 9 #include "param.h" 10 #include "resourcevar.h" 11 #include "malloc.h" 12 #include "proc.h" 13 14 /* 15 * Resource controls and accounting. 16 */ 17 18 getpriority(curp, uap, retval) 19 struct proc *curp; 20 register struct args { 21 int which; 22 int who; 23 } *uap; 24 int *retval; 25 { 26 register struct proc *p; 27 register int low = PRIO_MAX + 1; 28 29 switch (uap->which) { 30 31 case PRIO_PROCESS: 32 if (uap->who == 0) 33 p = curp; 34 else 35 p = pfind(uap->who); 36 if (p == 0) 37 break; 38 low = p->p_nice; 39 break; 40 41 case PRIO_PGRP: { 42 register struct pgrp *pg; 43 44 if (uap->who == 0) 45 pg = curp->p_pgrp; 46 else if ((pg = pgfind(uap->who)) == NULL) 47 break; 48 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 49 if (p->p_nice < low) 50 low = p->p_nice; 51 } 52 break; 53 } 54 55 case PRIO_USER: 56 if (uap->who == 0) 57 uap->who = curp->p_ucred->cr_uid; 58 for (p = allproc; p != NULL; p = p->p_nxt) { 59 if (p->p_ucred->cr_uid == uap->who && 60 p->p_nice < low) 61 low = p->p_nice; 62 } 63 break; 64 65 default: 66 return (EINVAL); 67 } 68 if (low == PRIO_MAX + 1) 69 return (ESRCH); 70 *retval = low; 71 return (0); 72 } 73 74 /* ARGSUSED */ 75 setpriority(curp, uap, retval) 76 struct proc *curp; 77 register struct args { 78 int which; 79 int who; 80 int prio; 81 } *uap; 82 int *retval; 83 { 84 register struct proc *p; 85 int found = 0, error = 0; 86 87 switch (uap->which) { 88 89 case PRIO_PROCESS: 90 if (uap->who == 0) 91 p = curp; 92 else 93 p = pfind(uap->who); 94 if (p == 0) 95 break; 96 error = donice(curp, p, uap->prio); 97 found++; 98 break; 99 100 case PRIO_PGRP: { 101 register struct pgrp *pg; 102 103 if (uap->who == 0) 104 pg = curp->p_pgrp; 105 else if ((pg = pgfind(uap->who)) == NULL) 106 break; 107 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 108 error = donice(curp, p, uap->prio); 109 found++; 110 } 111 break; 112 } 113 114 case PRIO_USER: 115 if (uap->who == 0) 116 uap->who = curp->p_ucred->cr_uid; 117 for (p = allproc; p != NULL; p = p->p_nxt) 118 if (p->p_ucred->cr_uid == uap->who) { 119 error = donice(curp, p, uap->prio); 120 found++; 121 } 122 break; 123 124 default: 125 return (EINVAL); 126 } 127 if (found == 0) 128 return (ESRCH); 129 return (0); 130 } 131 132 donice(curp, chgp, n) 133 register struct proc *curp, *chgp; 134 register int n; 135 { 136 register struct pcred *pcred = curp->p_cred; 137 138 if (pcred->pc_ucred->cr_uid && pcred->p_ruid && 139 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && 140 pcred->p_ruid != chgp->p_ucred->cr_uid) 141 return (EPERM); 142 if (n > PRIO_MAX) 143 n = PRIO_MAX; 144 if (n < PRIO_MIN) 145 n = PRIO_MIN; 146 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) 147 return (EACCES); 148 chgp->p_nice = n; 149 (void) setpri(chgp); 150 return (0); 151 } 152 153 /* ARGSUSED */ 154 setrlimit(p, uap, retval) 155 struct proc *p; 156 register struct args { 157 u_int which; 158 struct rlimit *lim; 159 } *uap; 160 int *retval; 161 { 162 struct rlimit alim; 163 register struct rlimit *alimp; 164 extern unsigned maxdmap; 165 int error; 166 167 if (uap->which >= RLIM_NLIMITS) 168 return (EINVAL); 169 alimp = &p->p_rlimit[uap->which]; 170 if (error = 171 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 172 return (error); 173 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 174 if (error = suser(p->p_ucred, &p->p_acflag)) 175 return (error); 176 if (p->p_limit->p_refcnt > 1 && 177 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 178 p->p_limit->p_refcnt--; 179 p->p_limit = limcopy(p->p_limit); 180 } 181 182 switch (uap->which) { 183 184 case RLIMIT_DATA: 185 if (alim.rlim_cur > maxdmap) 186 alim.rlim_cur = maxdmap; 187 if (alim.rlim_max > maxdmap) 188 alim.rlim_max = maxdmap; 189 break; 190 191 case RLIMIT_STACK: 192 if (alim.rlim_cur > maxdmap) 193 alim.rlim_cur = maxdmap; 194 if (alim.rlim_max > maxdmap) 195 alim.rlim_max = maxdmap; 196 break; 197 } 198 *alimp = alim; 199 return (0); 200 } 201 202 /* ARGSUSED */ 203 getrlimit(p, uap, retval) 204 struct proc *p; 205 register struct args { 206 u_int which; 207 struct rlimit *rlp; 208 } *uap; 209 int *retval; 210 { 211 212 if (uap->which >= RLIM_NLIMITS) 213 return (EINVAL); 214 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 215 sizeof (struct rlimit))); 216 } 217 218 /* ARGSUSED */ 219 getrusage(p, uap, retval) 220 register struct proc *p; 221 register struct args { 222 int who; 223 struct rusage *rusage; 224 } *uap; 225 int *retval; 226 { 227 register struct rusage *rup; 228 229 switch (uap->who) { 230 231 case RUSAGE_SELF: { 232 int s; 233 234 rup = &p->p_stats->p_ru; 235 s = splclock(); 236 rup->ru_stime = p->p_stime; 237 rup->ru_utime = p->p_utime; 238 splx(s); 239 break; 240 } 241 242 case RUSAGE_CHILDREN: 243 rup = &p->p_stats->p_cru; 244 break; 245 246 default: 247 return (EINVAL); 248 } 249 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 250 sizeof (struct rusage))); 251 } 252 253 ruadd(ru, ru2) 254 register struct rusage *ru, *ru2; 255 { 256 register long *ip, *ip2; 257 register int i; 258 259 timevaladd(&ru->ru_utime, &ru2->ru_utime); 260 timevaladd(&ru->ru_stime, &ru2->ru_stime); 261 if (ru->ru_maxrss < ru2->ru_maxrss) 262 ru->ru_maxrss = ru2->ru_maxrss; 263 ip = &ru->ru_first; ip2 = &ru2->ru_first; 264 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 265 *ip++ += *ip2++; 266 } 267 268 /* 269 * Make a copy of the plimit structure. 270 * We share these structures copy-on-write after fork, 271 * and copy when a limit is changed. 272 */ 273 struct plimit * 274 limcopy(lim) 275 struct plimit *lim; 276 { 277 register struct plimit *copy; 278 279 MALLOC(copy, struct plimit *, sizeof(struct plimit), 280 M_SUBPROC, M_WAITOK); 281 bcopy(lim->pl_rlimit, copy->pl_rlimit, 282 sizeof(struct rlimit) * RLIM_NLIMITS); 283 copy->p_lflags = 0; 284 copy->p_refcnt = 1; 285 return (copy); 286 } 287