Fix from Yuval Yurom:
[unix-history] / sys / kern / kern_resource.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
600f7f07 33 * from: @(#)kern_resource.c 7.13 (Berkeley) 5/9/91
06cb0d70 34 * $Id: kern_resource.c,v 1.5 1993/10/16 15:24:26 rgrimes Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "resourcevar.h"
39#include "malloc.h"
40#include "proc.h"
41
42#include "vm/vm.h"
43
44/*
45 * Resource controls and accounting.
46 */
47
3c7eb27c
DG
48struct getpriority_args {
49 int which;
50 int who;
51};
52
15637ed4
RG
53getpriority(curp, uap, retval)
54 struct proc *curp;
3c7eb27c 55 register struct getpriority_args *uap;
15637ed4
RG
56 int *retval;
57{
58 register struct proc *p;
59 register int low = PRIO_MAX + 1;
60
61 switch (uap->which) {
62
63 case PRIO_PROCESS:
64 if (uap->who == 0)
65 p = curp;
66 else
67 p = pfind(uap->who);
68 if (p == 0)
69 break;
70 low = p->p_nice;
71 break;
72
73 case PRIO_PGRP: {
74 register struct pgrp *pg;
75
76 if (uap->who == 0)
77 pg = curp->p_pgrp;
78 else if ((pg = pgfind(uap->who)) == NULL)
79 break;
80 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
81 if (p->p_nice < low)
82 low = p->p_nice;
83 }
84 break;
85 }
86
87 case PRIO_USER:
88 if (uap->who == 0)
89 uap->who = curp->p_ucred->cr_uid;
90 for (p = allproc; p != NULL; p = p->p_nxt) {
91 if (p->p_ucred->cr_uid == uap->who &&
92 p->p_nice < low)
93 low = p->p_nice;
94 }
95 break;
96
97 default:
98 return (EINVAL);
99 }
100 if (low == PRIO_MAX + 1)
101 return (ESRCH);
102 *retval = low;
103 return (0);
104}
105
3c7eb27c
DG
106struct setpriority_args {
107 int which;
108 int who;
109 int prio;
110};
111
15637ed4
RG
112/* ARGSUSED */
113setpriority(curp, uap, retval)
114 struct proc *curp;
3c7eb27c 115 register struct setpriority_args *uap;
15637ed4
RG
116 int *retval;
117{
118 register struct proc *p;
119 int found = 0, error = 0;
120
121 switch (uap->which) {
122
123 case PRIO_PROCESS:
124 if (uap->who == 0)
125 p = curp;
126 else
127 p = pfind(uap->who);
128 if (p == 0)
129 break;
130 error = donice(curp, p, uap->prio);
131 found++;
132 break;
133
134 case PRIO_PGRP: {
135 register struct pgrp *pg;
136
137 if (uap->who == 0)
138 pg = curp->p_pgrp;
139 else if ((pg = pgfind(uap->who)) == NULL)
140 break;
141 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
142 error = donice(curp, p, uap->prio);
143 found++;
144 }
145 break;
146 }
147
148 case PRIO_USER:
149 if (uap->who == 0)
150 uap->who = curp->p_ucred->cr_uid;
151 for (p = allproc; p != NULL; p = p->p_nxt)
152 if (p->p_ucred->cr_uid == uap->who) {
153 error = donice(curp, p, uap->prio);
154 found++;
155 }
156 break;
157
158 default:
159 return (EINVAL);
160 }
161 if (found == 0)
162 return (ESRCH);
163 return (0);
164}
165
166donice(curp, chgp, n)
167 register struct proc *curp, *chgp;
168 register int n;
169{
170 register struct pcred *pcred = curp->p_cred;
171
172 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
173 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
174 pcred->p_ruid != chgp->p_ucred->cr_uid)
175 return (EPERM);
176 if (n > PRIO_MAX)
177 n = PRIO_MAX;
178 if (n < PRIO_MIN)
179 n = PRIO_MIN;
180 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
181 return (EACCES);
182 chgp->p_nice = n;
183 (void) setpri(chgp);
184 return (0);
185}
186
3c7eb27c
DG
187struct setrlimit_args {
188 u_int which;
189 struct rlimit *lim;
190};
191
15637ed4
RG
192/* ARGSUSED */
193setrlimit(p, uap, retval)
194 struct proc *p;
3c7eb27c 195 register struct setrlimit_args *uap;
15637ed4
RG
196 int *retval;
197{
198 struct rlimit alim;
199 register struct rlimit *alimp;
d7f27d01 200 extern int maxfdescs;
15637ed4
RG
201 int error;
202
203 if (uap->which >= RLIM_NLIMITS)
204 return (EINVAL);
205 alimp = &p->p_rlimit[uap->which];
206 if (error =
207 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
208 return (error);
209 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
210 if (error = suser(p->p_ucred, &p->p_acflag))
211 return (error);
212 if (p->p_limit->p_refcnt > 1 &&
213 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
214 p->p_limit->p_refcnt--;
215 p->p_limit = limcopy(p->p_limit);
216 }
217
218 switch (uap->which) {
219
220 case RLIMIT_DATA:
eb71de0b
RG
221 if (alim.rlim_cur > MAXDSIZ)
222 alim.rlim_cur = MAXDSIZ;
223 if (alim.rlim_max > MAXDSIZ)
224 alim.rlim_max = MAXDSIZ;
15637ed4
RG
225 break;
226
d7f27d01
NW
227 case RLIMIT_OFILE:
228 if (alim.rlim_cur > maxfdescs)
229 alim.rlim_cur = maxfdescs;
230 if (alim.rlim_max > maxfdescs)
231 alim.rlim_max = maxfdescs;
232 break;
15637ed4 233 case RLIMIT_STACK:
eb71de0b
RG
234 if (alim.rlim_cur > MAXSSIZ)
235 alim.rlim_cur = MAXSSIZ;
236 if (alim.rlim_max > MAXSSIZ)
237 alim.rlim_max = MAXSSIZ;
15637ed4
RG
238 /*
239 * Stack is allocated to the max at exec time with only
240 * "rlim_cur" bytes accessible. If stack limit is going
241 * up make more accessible, if going down make inaccessible.
242 */
243 if (alim.rlim_cur != alimp->rlim_cur) {
244 vm_offset_t addr;
245 vm_size_t size;
246 vm_prot_t prot;
247 struct vmspace *vm = p->p_vmspace;
248
249 addr = (unsigned) vm->vm_maxsaddr + MAXSSIZ;
250 if (alim.rlim_cur > alimp->rlim_cur) {
251 prot = VM_PROT_ALL;
252 size = alim.rlim_cur - alimp->rlim_cur;
253 addr -= alim.rlim_cur;
254 } else {
255 prot = VM_PROT_NONE;
256 size = alimp->rlim_cur - alim.rlim_cur;
257 addr -= alimp->rlim_cur;
258 }
259 addr = trunc_page(addr);
260 size = round_page(size);
261 (void) vm_map_protect(&p->p_vmspace->vm_map,
262 addr, addr+size, prot, FALSE);
263 }
264 break;
265 }
266 p->p_rlimit[uap->which] = alim;
267 return (0);
268}
269
3c7eb27c
DG
270struct getrlimit_args {
271 u_int which;
272 struct rlimit *rlp;
273};
274
15637ed4
RG
275/* ARGSUSED */
276getrlimit(p, uap, retval)
277 struct proc *p;
3c7eb27c 278 register struct getrlimit_args *uap;
15637ed4
RG
279 int *retval;
280{
281
282 if (uap->which >= RLIM_NLIMITS)
283 return (EINVAL);
284 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
285 sizeof (struct rlimit)));
286}
287
3c7eb27c
DG
288struct getrusage_args {
289 int who;
290 struct rusage *rusage;
291};
292
15637ed4
RG
293/* ARGSUSED */
294getrusage(p, uap, retval)
295 register struct proc *p;
3c7eb27c 296 register struct getrusage_args *uap;
15637ed4
RG
297 int *retval;
298{
299 register struct rusage *rup;
300
301 switch (uap->who) {
302
303 case RUSAGE_SELF: {
304 int s;
305
306 rup = &p->p_stats->p_ru;
307 s = splclock();
308 rup->ru_stime = p->p_stime;
309 rup->ru_utime = p->p_utime;
310 splx(s);
311 break;
312 }
313
314 case RUSAGE_CHILDREN:
315 rup = &p->p_stats->p_cru;
316 break;
317
318 default:
319 return (EINVAL);
320 }
321 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
322 sizeof (struct rusage)));
323}
324
325ruadd(ru, ru2)
326 register struct rusage *ru, *ru2;
327{
328 register long *ip, *ip2;
329 register int i;
330
331 timevaladd(&ru->ru_utime, &ru2->ru_utime);
332 timevaladd(&ru->ru_stime, &ru2->ru_stime);
333 if (ru->ru_maxrss < ru2->ru_maxrss)
334 ru->ru_maxrss = ru2->ru_maxrss;
335 ip = &ru->ru_first; ip2 = &ru2->ru_first;
06cb0d70 336 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) /* Yuval fix */
15637ed4
RG
337 *ip++ += *ip2++;
338}
339
340/*
341 * Make a copy of the plimit structure.
342 * We share these structures copy-on-write after fork,
343 * and copy when a limit is changed.
344 */
345struct plimit *
346limcopy(lim)
347 struct plimit *lim;
348{
349 register struct plimit *copy;
350
351 MALLOC(copy, struct plimit *, sizeof(struct plimit),
352 M_SUBPROC, M_WAITOK);
353 bcopy(lim->pl_rlimit, copy->pl_rlimit,
354 sizeof(struct rlimit) * RLIM_NLIMITS);
355 copy->p_lflags = 0;
356 copy->p_refcnt = 1;
357 return (copy);
358}