This source file includes following definitions.
- sys_getpriority
- sys_setpriority
- donice
- sys_setrlimit
- dosetrlimit
- sys_getrlimit
- calcru
- sys_getrusage
- ruadd
- limcopy
- limfree
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/file.h>
44 #include <sys/resourcevar.h>
45 #include <sys/pool.h>
46 #include <sys/proc.h>
47 #include <sys/sched.h>
48
49 #include <sys/mount.h>
50 #include <sys/syscallargs.h>
51
52 #include <uvm/uvm_extern.h>
53
54
55
56
57 rlim_t maxdmap = MAXDSIZ;
58 rlim_t maxsmap = MAXSSIZ;
59
60
61
62
63
64 int
65 sys_getpriority(struct proc *curp, void *v, register_t *retval)
66 {
67 struct sys_getpriority_args
68
69
70 *uap = v;
71 struct proc *p;
72 int low = NZERO + PRIO_MAX + 1;
73
74 switch (SCARG(uap, which)) {
75
76 case PRIO_PROCESS:
77 if (SCARG(uap, who) == 0)
78 p = curp;
79 else
80 p = pfind(SCARG(uap, who));
81 if (p == 0)
82 break;
83 low = p->p_nice;
84 break;
85
86 case PRIO_PGRP: {
87 struct pgrp *pg;
88
89 if (SCARG(uap, who) == 0)
90 pg = curp->p_pgrp;
91 else if ((pg = pgfind(SCARG(uap, who))) == NULL)
92 break;
93 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
94 if (p->p_nice < low)
95 low = p->p_nice;
96 }
97 break;
98 }
99
100 case PRIO_USER:
101 if (SCARG(uap, who) == 0)
102 SCARG(uap, who) = curp->p_ucred->cr_uid;
103 for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list))
104 if (p->p_ucred->cr_uid == SCARG(uap, who) &&
105 p->p_nice < low)
106 low = p->p_nice;
107 break;
108
109 default:
110 return (EINVAL);
111 }
112 if (low == NZERO + PRIO_MAX + 1)
113 return (ESRCH);
114 *retval = low - NZERO;
115 return (0);
116 }
117
118
119 int
120 sys_setpriority(struct proc *curp, void *v, register_t *retval)
121 {
122 struct sys_setpriority_args
123
124
125
126 *uap = v;
127 struct proc *p;
128 int found = 0, error = 0;
129
130 switch (SCARG(uap, which)) {
131
132 case PRIO_PROCESS:
133 if (SCARG(uap, who) == 0)
134 p = curp;
135 else
136 p = pfind(SCARG(uap, who));
137 if (p == 0)
138 break;
139 error = donice(curp, p, SCARG(uap, prio));
140 found++;
141 break;
142
143 case PRIO_PGRP: {
144 struct pgrp *pg;
145
146 if (SCARG(uap, who) == 0)
147 pg = curp->p_pgrp;
148 else if ((pg = pgfind(SCARG(uap, who))) == NULL)
149 break;
150 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
151 error = donice(curp, p, SCARG(uap, prio));
152 found++;
153 }
154 break;
155 }
156
157 case PRIO_USER:
158 if (SCARG(uap, who) == 0)
159 SCARG(uap, who) = curp->p_ucred->cr_uid;
160 for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list))
161 if (p->p_ucred->cr_uid == SCARG(uap, who)) {
162 error = donice(curp, p, SCARG(uap, prio));
163 found++;
164 }
165 break;
166
167 default:
168 return (EINVAL);
169 }
170 if (found == 0)
171 return (ESRCH);
172 return (error);
173 }
174
175 int
176 donice(struct proc *curp, struct proc *chgp, int n)
177 {
178 struct pcred *pcred = curp->p_cred;
179 int s;
180
181 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
182 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
183 pcred->p_ruid != chgp->p_ucred->cr_uid)
184 return (EPERM);
185 if (n > PRIO_MAX)
186 n = PRIO_MAX;
187 if (n < PRIO_MIN)
188 n = PRIO_MIN;
189 n += NZERO;
190 if (n < chgp->p_nice && suser(curp, 0))
191 return (EACCES);
192 chgp->p_nice = n;
193 SCHED_LOCK(s);
194 (void)resetpriority(chgp);
195 SCHED_UNLOCK(s);
196 return (0);
197 }
198
199
200 int
201 sys_setrlimit(struct proc *p, void *v, register_t *retval)
202 {
203 struct sys_setrlimit_args
204
205
206 *uap = v;
207 struct rlimit alim;
208 int error;
209
210 error = copyin((caddr_t)SCARG(uap, rlp), (caddr_t)&alim,
211 sizeof (struct rlimit));
212 if (error)
213 return (error);
214 return (dosetrlimit(p, SCARG(uap, which), &alim));
215 }
216
217 int
218 dosetrlimit(struct proc *p, u_int which, struct rlimit *limp)
219 {
220 struct rlimit *alimp;
221 rlim_t maxlim;
222 int error;
223
224 if (which >= RLIM_NLIMITS)
225 return (EINVAL);
226
227 alimp = &p->p_rlimit[which];
228 if (limp->rlim_cur > alimp->rlim_max ||
229 limp->rlim_max > alimp->rlim_max)
230 if ((error = suser(p, 0)) != 0)
231 return (error);
232 if (p->p_p->ps_limit->p_refcnt > 1 &&
233 (p->p_p->ps_limit->p_lflags & PL_SHAREMOD) == 0) {
234 p->p_p->ps_limit->p_refcnt--;
235 p->p_p->ps_limit = limcopy(p->p_p->ps_limit);
236 alimp = &p->p_rlimit[which];
237 }
238
239 switch (which) {
240 case RLIMIT_DATA:
241 maxlim = maxdmap;
242 break;
243 case RLIMIT_STACK:
244 maxlim = maxsmap;
245 break;
246 case RLIMIT_NOFILE:
247 maxlim = maxfiles;
248 break;
249 case RLIMIT_NPROC:
250 maxlim = maxproc;
251 break;
252 default:
253 maxlim = RLIM_INFINITY;
254 break;
255 }
256
257 if (limp->rlim_max > maxlim)
258 limp->rlim_max = maxlim;
259 if (limp->rlim_cur > limp->rlim_max)
260 limp->rlim_cur = limp->rlim_max;
261
262 if (which == RLIMIT_STACK) {
263
264
265
266
267
268 if (limp->rlim_cur != alimp->rlim_cur) {
269 vaddr_t addr;
270 vsize_t size;
271 vm_prot_t prot;
272
273 if (limp->rlim_cur > alimp->rlim_cur) {
274 prot = VM_PROT_READ|VM_PROT_WRITE;
275 size = limp->rlim_cur - alimp->rlim_cur;
276 #ifdef MACHINE_STACK_GROWS_UP
277 addr = USRSTACK + alimp->rlim_cur;
278 #else
279 addr = USRSTACK - limp->rlim_cur;
280 #endif
281 } else {
282 prot = VM_PROT_NONE;
283 size = alimp->rlim_cur - limp->rlim_cur;
284 #ifdef MACHINE_STACK_GROWS_UP
285 addr = USRSTACK + limp->rlim_cur;
286 #else
287 addr = USRSTACK - alimp->rlim_cur;
288 #endif
289 }
290 addr = trunc_page(addr);
291 size = round_page(size);
292 (void) uvm_map_protect(&p->p_vmspace->vm_map,
293 addr, addr+size, prot, FALSE);
294 }
295 }
296
297 *alimp = *limp;
298 return (0);
299 }
300
301
302 int
303 sys_getrlimit(struct proc *p, void *v, register_t *retval)
304 {
305 struct sys_getrlimit_args
306
307
308 *uap = v;
309
310 if (SCARG(uap, which) < 0 || SCARG(uap, which) >= RLIM_NLIMITS)
311 return (EINVAL);
312 return (copyout((caddr_t)&p->p_rlimit[SCARG(uap, which)],
313 (caddr_t)SCARG(uap, rlp), sizeof (struct rlimit)));
314 }
315
316
317
318
319
320 void
321 calcru(struct proc *p, struct timeval *up, struct timeval *sp,
322 struct timeval *ip)
323 {
324 u_quad_t st, ut, it;
325 int freq;
326 int s;
327
328 s = splstatclock();
329 st = p->p_sticks;
330 ut = p->p_uticks;
331 it = p->p_iticks;
332 splx(s);
333
334 if (st + ut + it == 0) {
335 timerclear(up);
336 timerclear(sp);
337 if (ip != NULL)
338 timerclear(ip);
339 return;
340 }
341
342 freq = stathz ? stathz : hz;
343
344 st = st * 1000000 / freq;
345 sp->tv_sec = st / 1000000;
346 sp->tv_usec = st % 1000000;
347 ut = ut * 1000000 / freq;
348 up->tv_sec = ut / 1000000;
349 up->tv_usec = ut % 1000000;
350 if (ip != NULL) {
351 it = it * 1000000 / freq;
352 ip->tv_sec = it / 1000000;
353 ip->tv_usec = it % 1000000;
354 }
355 }
356
357
358 int
359 sys_getrusage(struct proc *p, void *v, register_t *retval)
360 {
361 struct sys_getrusage_args
362
363
364 *uap = v;
365 struct rusage *rup;
366
367 switch (SCARG(uap, who)) {
368
369 case RUSAGE_SELF:
370 rup = &p->p_stats->p_ru;
371 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
372 break;
373
374 case RUSAGE_CHILDREN:
375 rup = &p->p_stats->p_cru;
376 break;
377
378 default:
379 return (EINVAL);
380 }
381 return (copyout((caddr_t)rup, (caddr_t)SCARG(uap, rusage),
382 sizeof (struct rusage)));
383 }
384
385 void
386 ruadd(struct rusage *ru, struct rusage *ru2)
387 {
388 long *ip, *ip2;
389 int i;
390
391 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
392 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
393 if (ru->ru_maxrss < ru2->ru_maxrss)
394 ru->ru_maxrss = ru2->ru_maxrss;
395 ip = &ru->ru_first; ip2 = &ru2->ru_first;
396 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
397 *ip++ += *ip2++;
398 }
399
400 struct pool plimit_pool;
401
402
403
404
405
406
407 struct plimit *
408 limcopy(struct plimit *lim)
409 {
410 struct plimit *newlim;
411 static int initialized;
412
413 if (!initialized) {
414 pool_init(&plimit_pool, sizeof(struct plimit), 0, 0, 0,
415 "plimitpl", &pool_allocator_nointr);
416 initialized = 1;
417 }
418
419 newlim = pool_get(&plimit_pool, PR_WAITOK);
420 bcopy(lim->pl_rlimit, newlim->pl_rlimit,
421 sizeof(struct rlimit) * RLIM_NLIMITS);
422 newlim->p_lflags = 0;
423 newlim->p_refcnt = 1;
424 return (newlim);
425 }
426
427 void
428 limfree(struct plimit *lim)
429 {
430 if (--lim->p_refcnt > 0)
431 return;
432 pool_put(&plimit_pool, lim);
433 }