Remove confusing and incorrect comment inherited from patchkit days.
[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
4c45483e 34 * $Id: kern_resource.c,v 1.6 1993/10/19 01:02:16 nate Exp $
15637ed4
RG
35 */
36
37#include "param.h"
4c45483e 38#include "systm.h"
15637ed4
RG
39#include "resourcevar.h"
40#include "malloc.h"
41#include "proc.h"
42
43#include "vm/vm.h"
44
45/*
46 * Resource controls and accounting.
47 */
48
3c7eb27c
DG
49struct getpriority_args {
50 int which;
51 int who;
52};
53
4c45483e 54int
15637ed4
RG
55getpriority(curp, uap, retval)
56 struct proc *curp;
3c7eb27c 57 register struct getpriority_args *uap;
15637ed4
RG
58 int *retval;
59{
60 register struct proc *p;
61 register int low = PRIO_MAX + 1;
62
63 switch (uap->which) {
64
65 case PRIO_PROCESS:
66 if (uap->who == 0)
67 p = curp;
68 else
69 p = pfind(uap->who);
70 if (p == 0)
71 break;
72 low = p->p_nice;
73 break;
74
75 case PRIO_PGRP: {
76 register struct pgrp *pg;
77
78 if (uap->who == 0)
79 pg = curp->p_pgrp;
80 else if ((pg = pgfind(uap->who)) == NULL)
81 break;
82 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
83 if (p->p_nice < low)
84 low = p->p_nice;
85 }
86 break;
87 }
88
89 case PRIO_USER:
90 if (uap->who == 0)
91 uap->who = curp->p_ucred->cr_uid;
92 for (p = allproc; p != NULL; p = p->p_nxt) {
93 if (p->p_ucred->cr_uid == uap->who &&
94 p->p_nice < low)
95 low = p->p_nice;
96 }
97 break;
98
99 default:
100 return (EINVAL);
101 }
102 if (low == PRIO_MAX + 1)
103 return (ESRCH);
104 *retval = low;
105 return (0);
106}
107
3c7eb27c
DG
108struct setpriority_args {
109 int which;
110 int who;
111 int prio;
112};
113
15637ed4 114/* ARGSUSED */
4c45483e 115int
15637ed4
RG
116setpriority(curp, uap, retval)
117 struct proc *curp;
3c7eb27c 118 register struct setpriority_args *uap;
15637ed4
RG
119 int *retval;
120{
121 register struct proc *p;
122 int found = 0, error = 0;
123
124 switch (uap->which) {
125
126 case PRIO_PROCESS:
127 if (uap->who == 0)
128 p = curp;
129 else
130 p = pfind(uap->who);
131 if (p == 0)
132 break;
133 error = donice(curp, p, uap->prio);
134 found++;
135 break;
136
137 case PRIO_PGRP: {
138 register struct pgrp *pg;
139
140 if (uap->who == 0)
141 pg = curp->p_pgrp;
142 else if ((pg = pgfind(uap->who)) == NULL)
143 break;
144 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
145 error = donice(curp, p, uap->prio);
146 found++;
147 }
148 break;
149 }
150
151 case PRIO_USER:
152 if (uap->who == 0)
153 uap->who = curp->p_ucred->cr_uid;
154 for (p = allproc; p != NULL; p = p->p_nxt)
155 if (p->p_ucred->cr_uid == uap->who) {
156 error = donice(curp, p, uap->prio);
157 found++;
158 }
159 break;
160
161 default:
162 return (EINVAL);
163 }
164 if (found == 0)
165 return (ESRCH);
166 return (0);
167}
168
4c45483e 169int
15637ed4
RG
170donice(curp, chgp, n)
171 register struct proc *curp, *chgp;
172 register int n;
173{
174 register struct pcred *pcred = curp->p_cred;
175
176 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
177 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
178 pcred->p_ruid != chgp->p_ucred->cr_uid)
179 return (EPERM);
180 if (n > PRIO_MAX)
181 n = PRIO_MAX;
182 if (n < PRIO_MIN)
183 n = PRIO_MIN;
184 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
185 return (EACCES);
186 chgp->p_nice = n;
187 (void) setpri(chgp);
188 return (0);
189}
190
3c7eb27c
DG
191struct setrlimit_args {
192 u_int which;
193 struct rlimit *lim;
194};
195
15637ed4 196/* ARGSUSED */
4c45483e 197int
15637ed4
RG
198setrlimit(p, uap, retval)
199 struct proc *p;
3c7eb27c 200 register struct setrlimit_args *uap;
15637ed4
RG
201 int *retval;
202{
203 struct rlimit alim;
204 register struct rlimit *alimp;
d7f27d01 205 extern int maxfdescs;
15637ed4
RG
206 int error;
207
208 if (uap->which >= RLIM_NLIMITS)
209 return (EINVAL);
210 alimp = &p->p_rlimit[uap->which];
211 if (error =
212 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
213 return (error);
214 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
215 if (error = suser(p->p_ucred, &p->p_acflag))
216 return (error);
217 if (p->p_limit->p_refcnt > 1 &&
218 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
219 p->p_limit->p_refcnt--;
220 p->p_limit = limcopy(p->p_limit);
221 }
222
223 switch (uap->which) {
224
225 case RLIMIT_DATA:
eb71de0b
RG
226 if (alim.rlim_cur > MAXDSIZ)
227 alim.rlim_cur = MAXDSIZ;
228 if (alim.rlim_max > MAXDSIZ)
229 alim.rlim_max = MAXDSIZ;
15637ed4
RG
230 break;
231
d7f27d01
NW
232 case RLIMIT_OFILE:
233 if (alim.rlim_cur > maxfdescs)
234 alim.rlim_cur = maxfdescs;
235 if (alim.rlim_max > maxfdescs)
236 alim.rlim_max = maxfdescs;
237 break;
15637ed4 238 case RLIMIT_STACK:
eb71de0b
RG
239 if (alim.rlim_cur > MAXSSIZ)
240 alim.rlim_cur = MAXSSIZ;
241 if (alim.rlim_max > MAXSSIZ)
242 alim.rlim_max = MAXSSIZ;
15637ed4
RG
243 /*
244 * Stack is allocated to the max at exec time with only
245 * "rlim_cur" bytes accessible. If stack limit is going
246 * up make more accessible, if going down make inaccessible.
247 */
248 if (alim.rlim_cur != alimp->rlim_cur) {
249 vm_offset_t addr;
250 vm_size_t size;
251 vm_prot_t prot;
252 struct vmspace *vm = p->p_vmspace;
253
254 addr = (unsigned) vm->vm_maxsaddr + MAXSSIZ;
255 if (alim.rlim_cur > alimp->rlim_cur) {
256 prot = VM_PROT_ALL;
257 size = alim.rlim_cur - alimp->rlim_cur;
258 addr -= alim.rlim_cur;
259 } else {
260 prot = VM_PROT_NONE;
261 size = alimp->rlim_cur - alim.rlim_cur;
262 addr -= alimp->rlim_cur;
263 }
264 addr = trunc_page(addr);
265 size = round_page(size);
266 (void) vm_map_protect(&p->p_vmspace->vm_map,
267 addr, addr+size, prot, FALSE);
268 }
269 break;
270 }
271 p->p_rlimit[uap->which] = alim;
272 return (0);
273}
274
3c7eb27c
DG
275struct getrlimit_args {
276 u_int which;
277 struct rlimit *rlp;
278};
279
15637ed4 280/* ARGSUSED */
4c45483e 281int
15637ed4
RG
282getrlimit(p, uap, retval)
283 struct proc *p;
3c7eb27c 284 register struct getrlimit_args *uap;
15637ed4
RG
285 int *retval;
286{
287
288 if (uap->which >= RLIM_NLIMITS)
289 return (EINVAL);
290 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
291 sizeof (struct rlimit)));
292}
293
3c7eb27c
DG
294struct getrusage_args {
295 int who;
296 struct rusage *rusage;
297};
298
15637ed4 299/* ARGSUSED */
4c45483e 300int
15637ed4
RG
301getrusage(p, uap, retval)
302 register struct proc *p;
3c7eb27c 303 register struct getrusage_args *uap;
15637ed4
RG
304 int *retval;
305{
306 register struct rusage *rup;
307
308 switch (uap->who) {
309
310 case RUSAGE_SELF: {
311 int s;
312
313 rup = &p->p_stats->p_ru;
314 s = splclock();
315 rup->ru_stime = p->p_stime;
316 rup->ru_utime = p->p_utime;
317 splx(s);
318 break;
319 }
320
321 case RUSAGE_CHILDREN:
322 rup = &p->p_stats->p_cru;
323 break;
324
325 default:
326 return (EINVAL);
327 }
328 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
329 sizeof (struct rusage)));
330}
331
4c45483e 332void
15637ed4
RG
333ruadd(ru, ru2)
334 register struct rusage *ru, *ru2;
335{
336 register long *ip, *ip2;
337 register int i;
338
339 timevaladd(&ru->ru_utime, &ru2->ru_utime);
340 timevaladd(&ru->ru_stime, &ru2->ru_stime);
341 if (ru->ru_maxrss < ru2->ru_maxrss)
342 ru->ru_maxrss = ru2->ru_maxrss;
343 ip = &ru->ru_first; ip2 = &ru2->ru_first;
06cb0d70 344 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--) /* Yuval fix */
15637ed4
RG
345 *ip++ += *ip2++;
346}
347
348/*
349 * Make a copy of the plimit structure.
350 * We share these structures copy-on-write after fork,
351 * and copy when a limit is changed.
352 */
353struct plimit *
354limcopy(lim)
355 struct plimit *lim;
356{
357 register struct plimit *copy;
358
359 MALLOC(copy, struct plimit *, sizeof(struct plimit),
360 M_SUBPROC, M_WAITOK);
361 bcopy(lim->pl_rlimit, copy->pl_rlimit,
362 sizeof(struct rlimit) * RLIM_NLIMITS);
363 copy->p_lflags = 0;
364 copy->p_refcnt = 1;
365 return (copy);
366}