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