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