Commit | Line | Data |
---|---|---|
f406ae69 KB |
1 | /*- |
2 | * Copyright (c) 1982, 1986, 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
da7c5cc6 | 6 | * |
75e66255 | 7 | * @(#)kern_resource.c 7.14 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
1b64633a | 9 | |
94368568 | 10 | #include "param.h" |
0cee12d3 MK |
11 | #include "resourcevar.h" |
12 | #include "malloc.h" | |
94368568 | 13 | #include "proc.h" |
db1874da | 14 | |
4be63405 MH |
15 | #include "vm/vm.h" |
16 | ||
93cc02ac BJ |
17 | /* |
18 | * Resource controls and accounting. | |
19 | */ | |
20 | ||
8eea23a6 KM |
21 | getpriority(curp, uap, retval) |
22 | struct proc *curp; | |
23 | register struct args { | |
db1874da BJ |
24 | int which; |
25 | int who; | |
8eea23a6 KM |
26 | } *uap; |
27 | int *retval; | |
28 | { | |
db1874da | 29 | register struct proc *p; |
8fe87cbb | 30 | register int low = PRIO_MAX + 1; |
db1874da | 31 | |
db1874da BJ |
32 | switch (uap->which) { |
33 | ||
34 | case PRIO_PROCESS: | |
35 | if (uap->who == 0) | |
8eea23a6 | 36 | p = curp; |
db1874da BJ |
37 | else |
38 | p = pfind(uap->who); | |
39 | if (p == 0) | |
957edfef | 40 | break; |
3fa5efae | 41 | low = p->p_nice; |
db1874da BJ |
42 | break; |
43 | ||
8fe87cbb MT |
44 | case PRIO_PGRP: { |
45 | register struct pgrp *pg; | |
46 | ||
db1874da | 47 | if (uap->who == 0) |
8eea23a6 | 48 | pg = curp->p_pgrp; |
8fe87cbb MT |
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) | |
3fa5efae | 53 | low = p->p_nice; |
93cc02ac BJ |
54 | } |
55 | break; | |
8fe87cbb | 56 | } |
93cc02ac BJ |
57 | |
58 | case PRIO_USER: | |
59 | if (uap->who == 0) | |
0cee12d3 | 60 | uap->who = curp->p_ucred->cr_uid; |
1d348849 | 61 | for (p = allproc; p != NULL; p = p->p_nxt) { |
0cee12d3 | 62 | if (p->p_ucred->cr_uid == uap->who && |
3fa5efae MK |
63 | p->p_nice < low) |
64 | low = p->p_nice; | |
93cc02ac | 65 | } |
db1874da BJ |
66 | break; |
67 | ||
68 | default: | |
d9c2f47f | 69 | return (EINVAL); |
db1874da | 70 | } |
8eea23a6 | 71 | if (low == PRIO_MAX + 1) |
d9c2f47f | 72 | return (ESRCH); |
8eea23a6 | 73 | *retval = low; |
d9c2f47f | 74 | return (0); |
db1874da BJ |
75 | } |
76 | ||
8eea23a6 KM |
77 | /* ARGSUSED */ |
78 | setpriority(curp, uap, retval) | |
79 | struct proc *curp; | |
80 | register struct args { | |
db1874da BJ |
81 | int which; |
82 | int who; | |
83 | int prio; | |
8eea23a6 KM |
84 | } *uap; |
85 | int *retval; | |
86 | { | |
db1874da | 87 | register struct proc *p; |
8eea23a6 | 88 | int found = 0, error = 0; |
db1874da | 89 | |
db1874da BJ |
90 | switch (uap->which) { |
91 | ||
92 | case PRIO_PROCESS: | |
93cc02ac | 93 | if (uap->who == 0) |
8eea23a6 | 94 | p = curp; |
93cc02ac BJ |
95 | else |
96 | p = pfind(uap->who); | |
db1874da | 97 | if (p == 0) |
957edfef | 98 | break; |
8eea23a6 | 99 | error = donice(curp, p, uap->prio); |
3fa5efae | 100 | found++; |
db1874da BJ |
101 | break; |
102 | ||
8fe87cbb MT |
103 | case PRIO_PGRP: { |
104 | register struct pgrp *pg; | |
105 | ||
93cc02ac | 106 | if (uap->who == 0) |
8eea23a6 | 107 | pg = curp->p_pgrp; |
8fe87cbb MT |
108 | else if ((pg = pgfind(uap->who)) == NULL) |
109 | break; | |
110 | for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { | |
8eea23a6 | 111 | error = donice(curp, p, uap->prio); |
8fe87cbb MT |
112 | found++; |
113 | } | |
db1874da | 114 | break; |
8fe87cbb | 115 | } |
db1874da | 116 | |
93cc02ac BJ |
117 | case PRIO_USER: |
118 | if (uap->who == 0) | |
0cee12d3 | 119 | uap->who = curp->p_ucred->cr_uid; |
1d348849 | 120 | for (p = allproc; p != NULL; p = p->p_nxt) |
0cee12d3 | 121 | if (p->p_ucred->cr_uid == uap->who) { |
8eea23a6 | 122 | error = donice(curp, p, uap->prio); |
3fa5efae MK |
123 | found++; |
124 | } | |
93cc02ac BJ |
125 | break; |
126 | ||
db1874da | 127 | default: |
d9c2f47f | 128 | return (EINVAL); |
db1874da | 129 | } |
3fa5efae | 130 | if (found == 0) |
d9c2f47f MK |
131 | return (ESRCH); |
132 | return (0); | |
db1874da BJ |
133 | } |
134 | ||
8eea23a6 KM |
135 | donice(curp, chgp, n) |
136 | register struct proc *curp, *chgp; | |
db1874da BJ |
137 | register int n; |
138 | { | |
0cee12d3 | 139 | register struct pcred *pcred = curp->p_cred; |
db1874da | 140 | |
0cee12d3 MK |
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) | |
8eea23a6 | 144 | return (EPERM); |
3fa5efae MK |
145 | if (n > PRIO_MAX) |
146 | n = PRIO_MAX; | |
147 | if (n < PRIO_MIN) | |
148 | n = PRIO_MIN; | |
0cee12d3 | 149 | if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) |
8eea23a6 KM |
150 | return (EACCES); |
151 | chgp->p_nice = n; | |
152 | (void) setpri(chgp); | |
153 | return (0); | |
db1874da BJ |
154 | } |
155 | ||
8eea23a6 KM |
156 | /* ARGSUSED */ |
157 | setrlimit(p, uap, retval) | |
158 | struct proc *p; | |
159 | register struct args { | |
db1874da BJ |
160 | u_int which; |
161 | struct rlimit *lim; | |
8eea23a6 KM |
162 | } *uap; |
163 | int *retval; | |
164 | { | |
db1874da BJ |
165 | struct rlimit alim; |
166 | register struct rlimit *alimp; | |
63ce5236 | 167 | extern unsigned maxdmap; |
8eea23a6 | 168 | int error; |
db1874da | 169 | |
8eea23a6 | 170 | if (uap->which >= RLIM_NLIMITS) |
d9c2f47f | 171 | return (EINVAL); |
0cee12d3 | 172 | alimp = &p->p_rlimit[uap->which]; |
8eea23a6 KM |
173 | if (error = |
174 | copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) | |
d9c2f47f | 175 | return (error); |
db1874da | 176 | if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) |
0cee12d3 | 177 | if (error = suser(p->p_ucred, &p->p_acflag)) |
d9c2f47f | 178 | return (error); |
0cee12d3 MK |
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); | |
75e66255 | 183 | alimp = &p->p_rlimit[uap->which]; |
0cee12d3 MK |
184 | } |
185 | ||
db1874da BJ |
186 | switch (uap->which) { |
187 | ||
188 | case RLIMIT_DATA: | |
d9937da6 KM |
189 | if (alim.rlim_cur > maxdmap) |
190 | alim.rlim_cur = maxdmap; | |
191 | if (alim.rlim_max > maxdmap) | |
192 | alim.rlim_max = maxdmap; | |
db1874da BJ |
193 | break; |
194 | ||
195 | case RLIMIT_STACK: | |
d9937da6 KM |
196 | if (alim.rlim_cur > maxdmap) |
197 | alim.rlim_cur = maxdmap; | |
198 | if (alim.rlim_max > maxdmap) | |
199 | alim.rlim_max = maxdmap; | |
4be63405 MH |
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 | } | |
db1874da BJ |
224 | break; |
225 | } | |
75e66255 | 226 | *alimp = alim; |
d9c2f47f | 227 | return (0); |
db1874da BJ |
228 | } |
229 | ||
8eea23a6 KM |
230 | /* ARGSUSED */ |
231 | getrlimit(p, uap, retval) | |
232 | struct proc *p; | |
233 | register struct args { | |
db1874da BJ |
234 | u_int which; |
235 | struct rlimit *rlp; | |
8eea23a6 KM |
236 | } *uap; |
237 | int *retval; | |
238 | { | |
db1874da | 239 | |
8eea23a6 | 240 | if (uap->which >= RLIM_NLIMITS) |
d9c2f47f | 241 | return (EINVAL); |
0cee12d3 | 242 | return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, |
8eea23a6 | 243 | sizeof (struct rlimit))); |
db1874da BJ |
244 | } |
245 | ||
8eea23a6 KM |
246 | /* ARGSUSED */ |
247 | getrusage(p, uap, retval) | |
248 | register struct proc *p; | |
249 | register struct args { | |
db1874da BJ |
250 | int who; |
251 | struct rusage *rusage; | |
8eea23a6 KM |
252 | } *uap; |
253 | int *retval; | |
254 | { | |
db1874da BJ |
255 | register struct rusage *rup; |
256 | ||
257 | switch (uap->who) { | |
258 | ||
e9e38d76 MK |
259 | case RUSAGE_SELF: { |
260 | int s; | |
261 | ||
0cee12d3 | 262 | rup = &p->p_stats->p_ru; |
e9e38d76 MK |
263 | s = splclock(); |
264 | rup->ru_stime = p->p_stime; | |
265 | rup->ru_utime = p->p_utime; | |
266 | splx(s); | |
db1874da | 267 | break; |
e9e38d76 | 268 | } |
db1874da BJ |
269 | |
270 | case RUSAGE_CHILDREN: | |
0cee12d3 | 271 | rup = &p->p_stats->p_cru; |
db1874da BJ |
272 | break; |
273 | ||
274 | default: | |
d9c2f47f | 275 | return (EINVAL); |
db1874da | 276 | } |
d9c2f47f | 277 | return (copyout((caddr_t)rup, (caddr_t)uap->rusage, |
8eea23a6 | 278 | sizeof (struct rusage))); |
db1874da BJ |
279 | } |
280 | ||
281 | ruadd(ru, ru2) | |
282 | register struct rusage *ru, *ru2; | |
283 | { | |
3fd23f5c | 284 | register long *ip, *ip2; |
db1874da BJ |
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 | } | |
0cee12d3 MK |
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 | } |