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.15 (Berkeley) 03/15/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 (alim.rlim_cur > alim.rlim_max) 180 alim.rlim_cur = alim.rlim_max; 181 if (p->p_limit->p_refcnt > 1 && 182 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 183 p->p_limit->p_refcnt--; 184 p->p_limit = limcopy(p->p_limit); 185 alimp = &p->p_rlimit[uap->which]; 186 } 187 188 switch (uap->which) { 189 190 case RLIMIT_DATA: 191 if (alim.rlim_cur > maxdmap) 192 alim.rlim_cur = maxdmap; 193 if (alim.rlim_max > maxdmap) 194 alim.rlim_max = maxdmap; 195 break; 196 197 case RLIMIT_STACK: 198 if (alim.rlim_cur > maxdmap) 199 alim.rlim_cur = maxdmap; 200 if (alim.rlim_max > maxdmap) 201 alim.rlim_max = maxdmap; 202 /* 203 * Stack is allocated to the max at exec time with only 204 * "rlim_cur" bytes accessible. If stack limit is going 205 * up make more accessible, if going down make inaccessible. 206 */ 207 if (alim.rlim_cur != alimp->rlim_cur) { 208 vm_offset_t addr; 209 vm_size_t size; 210 vm_prot_t prot; 211 212 if (alim.rlim_cur > alimp->rlim_cur) { 213 prot = VM_PROT_ALL; 214 size = alim.rlim_cur - alimp->rlim_cur; 215 addr = USRSTACK - alim.rlim_cur; 216 } else { 217 prot = VM_PROT_NONE; 218 size = alimp->rlim_cur - alim.rlim_cur; 219 addr = USRSTACK - alimp->rlim_cur; 220 } 221 addr = trunc_page(addr); 222 size = round_page(size); 223 (void) vm_map_protect(&p->p_vmspace->vm_map, 224 addr, addr+size, prot, FALSE); 225 } 226 break; 227 } 228 *alimp = alim; 229 return (0); 230 } 231 232 /* ARGSUSED */ 233 getrlimit(p, uap, retval) 234 struct proc *p; 235 register struct args { 236 u_int which; 237 struct rlimit *rlp; 238 } *uap; 239 int *retval; 240 { 241 242 if (uap->which >= RLIM_NLIMITS) 243 return (EINVAL); 244 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, 245 sizeof (struct rlimit))); 246 } 247 248 /* ARGSUSED */ 249 getrusage(p, uap, retval) 250 register struct proc *p; 251 register struct args { 252 int who; 253 struct rusage *rusage; 254 } *uap; 255 int *retval; 256 { 257 register struct rusage *rup; 258 259 switch (uap->who) { 260 261 case RUSAGE_SELF: { 262 int s; 263 264 rup = &p->p_stats->p_ru; 265 s = splclock(); 266 rup->ru_stime = p->p_stime; 267 rup->ru_utime = p->p_utime; 268 splx(s); 269 break; 270 } 271 272 case RUSAGE_CHILDREN: 273 rup = &p->p_stats->p_cru; 274 break; 275 276 default: 277 return (EINVAL); 278 } 279 return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 280 sizeof (struct rusage))); 281 } 282 283 ruadd(ru, ru2) 284 register struct rusage *ru, *ru2; 285 { 286 register long *ip, *ip2; 287 register int i; 288 289 timevaladd(&ru->ru_utime, &ru2->ru_utime); 290 timevaladd(&ru->ru_stime, &ru2->ru_stime); 291 if (ru->ru_maxrss < ru2->ru_maxrss) 292 ru->ru_maxrss = ru2->ru_maxrss; 293 ip = &ru->ru_first; ip2 = &ru2->ru_first; 294 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 295 *ip++ += *ip2++; 296 } 297 298 /* 299 * Make a copy of the plimit structure. 300 * We share these structures copy-on-write after fork, 301 * and copy when a limit is changed. 302 */ 303 struct plimit * 304 limcopy(lim) 305 struct plimit *lim; 306 { 307 register struct plimit *copy; 308 309 MALLOC(copy, struct plimit *, sizeof(struct plimit), 310 M_SUBPROC, M_WAITOK); 311 bcopy(lim->pl_rlimit, copy->pl_rlimit, 312 sizeof(struct rlimit) * RLIM_NLIMITS); 313 copy->p_lflags = 0; 314 copy->p_refcnt = 1; 315 return (copy); 316 } 317