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