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