]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_resource.c
xnu-2782.10.72.tar.gz
[apple/xnu.git] / bsd / kern / kern_resource.c
1 /*
2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
29 /*-
30 * Copyright (c) 1982, 1986, 1991, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94
67 */
68 /*
69 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
70 * support for mandatory and extensible security protections. This notice
71 * is included in support of clause 2.2 (b) of the Apple Public License,
72 * Version 2.0.
73 */
74
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/sysctl.h>
78 #include <sys/kernel.h>
79 #include <sys/file_internal.h>
80 #include <sys/resourcevar.h>
81 #include <sys/malloc.h>
82 #include <sys/proc_internal.h>
83 #include <sys/kauth.h>
84 #include <machine/spl.h>
85
86 #include <sys/mount_internal.h>
87 #include <sys/sysproto.h>
88
89 #include <security/audit/audit.h>
90
91 #include <machine/vmparam.h>
92
93 #include <mach/mach_types.h>
94 #include <mach/time_value.h>
95 #include <mach/task.h>
96 #include <mach/task_info.h>
97 #include <mach/vm_map.h>
98 #include <mach/mach_vm.h>
99 #include <mach/thread_act.h> /* for thread_policy_set( ) */
100 #include <kern/thread.h>
101
102 #include <kern/task.h>
103 #include <kern/clock.h> /* for absolutetime_to_microtime() */
104 #include <netinet/in.h> /* for TRAFFIC_MGT_SO_* */
105 #include <sys/socketvar.h> /* for struct socket */
106
107 #include <vm/vm_map.h>
108
109 #include <kern/assert.h>
110 #include <sys/resource.h>
111
112 int donice(struct proc *curp, struct proc *chgp, int n);
113 int dosetrlimit(struct proc *p, u_int which, struct rlimit *limp);
114 int uthread_get_background_state(uthread_t);
115 static void do_background_socket(struct proc *p, thread_t thread);
116 static int do_background_thread(struct proc *curp, thread_t thread, int priority);
117 static int do_background_proc(struct proc *curp, struct proc *targetp, int priority);
118 static int set_gpudeny_proc(struct proc *curp, struct proc *targetp, int priority);
119 static int proc_set_darwin_role(proc_t curp, proc_t targetp, int priority);
120 static int proc_get_darwin_role(proc_t curp, proc_t targetp, int *priority);
121 static int get_background_proc(struct proc *curp, struct proc *targetp, int *priority);
122 void proc_apply_task_networkbg_internal(proc_t, thread_t);
123 void proc_restore_task_networkbg_internal(proc_t, thread_t);
124 int proc_pid_rusage(int pid, int flavor, user_addr_t buf, int32_t *retval);
125 void gather_rusage_info(proc_t p, rusage_info_current *ru, int flavor);
126 int fill_task_rusage(task_t task, rusage_info_current *ri);
127 void fill_task_billed_usage(task_t task, rusage_info_current *ri);
128 int fill_task_io_rusage(task_t task, rusage_info_current *ri);
129 int fill_task_qos_rusage(task_t task, rusage_info_current *ri);
130 static void rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor);
131
132 int proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie);
133
134 rlim_t maxdmap = MAXDSIZ; /* XXX */
135 rlim_t maxsmap = MAXSSIZ - PAGE_MAX_SIZE; /* XXX */
136
137 /*
138 * Limits on the number of open files per process, and the number
139 * of child processes per process.
140 *
141 * Note: would be in kern/subr_param.c in FreeBSD.
142 */
143 __private_extern__ int maxfilesperproc = OPEN_MAX; /* per-proc open files limit */
144
145 SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW | CTLFLAG_LOCKED,
146 &maxprocperuid, 0, "Maximum processes allowed per userid" );
147
148 SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW | CTLFLAG_LOCKED,
149 &maxfilesperproc, 0, "Maximum files allowed open per process" );
150
151 /* Args and fn for proc_iteration callback used in setpriority */
152 struct puser_nice_args {
153 proc_t curp;
154 int prio;
155 id_t who;
156 int * foundp;
157 int * errorp;
158 };
159 static int puser_donice_callback(proc_t p, void * arg);
160
161
162 /* Args and fn for proc_iteration callback used in setpriority */
163 struct ppgrp_nice_args {
164 proc_t curp;
165 int prio;
166 int * foundp;
167 int * errorp;
168 };
169 static int ppgrp_donice_callback(proc_t p, void * arg);
170
171 /*
172 * Resource controls and accounting.
173 */
174 int
175 getpriority(struct proc *curp, struct getpriority_args *uap, int32_t *retval)
176 {
177 struct proc *p;
178 int low = PRIO_MAX + 1;
179 kauth_cred_t my_cred;
180 int refheld = 0;
181 int error = 0;
182
183 /* would also test (uap->who < 0), but id_t is unsigned */
184 if (uap->who > 0x7fffffff)
185 return (EINVAL);
186
187 switch (uap->which) {
188
189 case PRIO_PROCESS:
190 if (uap->who == 0) {
191 p = curp;
192 low = p->p_nice;
193 } else {
194 p = proc_find(uap->who);
195 if (p == 0)
196 break;
197 low = p->p_nice;
198 proc_rele(p);
199
200 }
201 break;
202
203 case PRIO_PGRP: {
204 struct pgrp *pg = PGRP_NULL;
205
206 if (uap->who == 0) {
207 /* returns the pgrp to ref */
208 pg = proc_pgrp(curp);
209 } else if ((pg = pgfind(uap->who)) == PGRP_NULL) {
210 break;
211 }
212 /* No need for iteration as it is a simple scan */
213 pgrp_lock(pg);
214 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
215 if (p->p_nice < low)
216 low = p->p_nice;
217 }
218 pgrp_unlock(pg);
219 pg_rele(pg);
220 break;
221 }
222
223 case PRIO_USER:
224 if (uap->who == 0)
225 uap->who = kauth_cred_getuid(kauth_cred_get());
226
227 proc_list_lock();
228
229 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
230 my_cred = kauth_cred_proc_ref(p);
231 if (kauth_cred_getuid(my_cred) == uap->who &&
232 p->p_nice < low)
233 low = p->p_nice;
234 kauth_cred_unref(&my_cred);
235 }
236
237 proc_list_unlock();
238
239 break;
240
241 case PRIO_DARWIN_THREAD:
242 /* we currently only support the current thread */
243 if (uap->who != 0)
244 return (EINVAL);
245
246 low = proc_get_task_policy(current_task(), current_thread(), TASK_POLICY_INTERNAL, TASK_POLICY_DARWIN_BG);
247
248 break;
249
250 case PRIO_DARWIN_PROCESS:
251 if (uap->who == 0) {
252 p = curp;
253 } else {
254 p = proc_find(uap->who);
255 if (p == PROC_NULL)
256 break;
257 refheld = 1;
258 }
259
260 error = get_background_proc(curp, p, &low);
261
262 if (refheld)
263 proc_rele(p);
264 if (error)
265 return (error);
266 break;
267
268 case PRIO_DARWIN_ROLE:
269 if (uap->who == 0) {
270 p = curp;
271 } else {
272 p = proc_find(uap->who);
273 if (p == PROC_NULL)
274 break;
275 refheld = 1;
276 }
277
278 error = proc_get_darwin_role(curp, p, &low);
279
280 if (refheld)
281 proc_rele(p);
282 if (error)
283 return (error);
284 break;
285
286 default:
287 return (EINVAL);
288 }
289 if (low == PRIO_MAX + 1)
290 return (ESRCH);
291 *retval = low;
292 return (0);
293 }
294
295 /* call back function used for proc iteration in PRIO_USER */
296 static int
297 puser_donice_callback(proc_t p, void * arg)
298 {
299 int error, n;
300 struct puser_nice_args * pun = (struct puser_nice_args *)arg;
301 kauth_cred_t my_cred;
302
303 my_cred = kauth_cred_proc_ref(p);
304 if (kauth_cred_getuid(my_cred) == pun->who) {
305 error = donice(pun->curp, p, pun->prio);
306 if (pun->errorp != NULL)
307 *pun->errorp = error;
308 if (pun->foundp != NULL) {
309 n = *pun->foundp;
310 *pun->foundp = n+1;
311 }
312 }
313 kauth_cred_unref(&my_cred);
314
315 return(PROC_RETURNED);
316 }
317
318 /* call back function used for proc iteration in PRIO_PGRP */
319 static int
320 ppgrp_donice_callback(proc_t p, void * arg)
321 {
322 int error;
323 struct ppgrp_nice_args * pun = (struct ppgrp_nice_args *)arg;
324 int n;
325
326 error = donice(pun->curp, p, pun->prio);
327 if (pun->errorp != NULL)
328 *pun->errorp = error;
329 if (pun->foundp!= NULL) {
330 n = *pun->foundp;
331 *pun->foundp = n+1;
332 }
333
334 return(PROC_RETURNED);
335 }
336
337 /*
338 * Returns: 0 Success
339 * EINVAL
340 * ESRCH
341 * donice:EPERM
342 * donice:EACCES
343 */
344 /* ARGSUSED */
345 int
346 setpriority(struct proc *curp, struct setpriority_args *uap, int32_t *retval)
347 {
348 struct proc *p;
349 int found = 0, error = 0;
350 int refheld = 0;
351
352 AUDIT_ARG(cmd, uap->which);
353 AUDIT_ARG(owner, uap->who, 0);
354 AUDIT_ARG(value32, uap->prio);
355
356 /* would also test (uap->who < 0), but id_t is unsigned */
357 if (uap->who > 0x7fffffff)
358 return (EINVAL);
359
360 switch (uap->which) {
361
362 case PRIO_PROCESS:
363 if (uap->who == 0)
364 p = curp;
365 else {
366 p = proc_find(uap->who);
367 if (p == 0)
368 break;
369 refheld = 1;
370 }
371 error = donice(curp, p, uap->prio);
372 found++;
373 if (refheld != 0)
374 proc_rele(p);
375 break;
376
377 case PRIO_PGRP: {
378 struct pgrp *pg = PGRP_NULL;
379 struct ppgrp_nice_args ppgrp;
380
381 if (uap->who == 0) {
382 pg = proc_pgrp(curp);
383 } else if ((pg = pgfind(uap->who)) == PGRP_NULL)
384 break;
385
386 ppgrp.curp = curp;
387 ppgrp.prio = uap->prio;
388 ppgrp.foundp = &found;
389 ppgrp.errorp = &error;
390
391 /* PGRP_DROPREF drops the reference on process group */
392 pgrp_iterate(pg, PGRP_DROPREF, ppgrp_donice_callback, (void *)&ppgrp, NULL, NULL);
393
394 break;
395 }
396
397 case PRIO_USER: {
398 struct puser_nice_args punice;
399
400 if (uap->who == 0)
401 uap->who = kauth_cred_getuid(kauth_cred_get());
402
403 punice.curp = curp;
404 punice.prio = uap->prio;
405 punice.who = uap->who;
406 punice.foundp = &found;
407 error = 0;
408 punice.errorp = &error;
409 proc_iterate(PROC_ALLPROCLIST, puser_donice_callback, (void *)&punice, NULL, NULL);
410
411 break;
412 }
413
414 case PRIO_DARWIN_THREAD: {
415 /* we currently only support the current thread */
416 if (uap->who != 0)
417 return (EINVAL);
418
419 error = do_background_thread(curp, current_thread(), uap->prio);
420 found++;
421 break;
422 }
423
424 case PRIO_DARWIN_PROCESS: {
425 if (uap->who == 0)
426 p = curp;
427 else {
428 p = proc_find(uap->who);
429 if (p == 0)
430 break;
431 refheld = 1;
432 }
433
434 error = do_background_proc(curp, p, uap->prio);
435
436 found++;
437 if (refheld != 0)
438 proc_rele(p);
439 break;
440 }
441
442 case PRIO_DARWIN_GPU: {
443 if (uap->who == 0)
444 return (EINVAL);
445
446 p = proc_find(uap->who);
447 if (p == PROC_NULL)
448 break;
449
450 error = set_gpudeny_proc(curp, p, uap->prio);
451
452 found++;
453 proc_rele(p);
454 break;
455 }
456
457 case PRIO_DARWIN_ROLE: {
458 if (uap->who == 0) {
459 p = curp;
460 } else {
461 p = proc_find(uap->who);
462 if (p == PROC_NULL)
463 break;
464 refheld = 1;
465 }
466
467 error = proc_set_darwin_role(curp, p, uap->prio);
468
469 found++;
470 if (refheld != 0)
471 proc_rele(p);
472 break;
473 }
474
475 default:
476 return (EINVAL);
477 }
478 if (found == 0)
479 return (ESRCH);
480 if (error == EIDRM) {
481 *retval = -2;
482 error = 0;
483 }
484 return (error);
485 }
486
487
488 /*
489 * Returns: 0 Success
490 * EPERM
491 * EACCES
492 * mac_check_proc_sched:???
493 */
494 int
495 donice(struct proc *curp, struct proc *chgp, int n)
496 {
497 int error = 0;
498 kauth_cred_t ucred;
499 kauth_cred_t my_cred;
500
501 ucred = kauth_cred_proc_ref(curp);
502 my_cred = kauth_cred_proc_ref(chgp);
503
504 if (suser(ucred, NULL) && kauth_cred_getruid(ucred) &&
505 kauth_cred_getuid(ucred) != kauth_cred_getuid(my_cred) &&
506 kauth_cred_getruid(ucred) != kauth_cred_getuid(my_cred)) {
507 error = EPERM;
508 goto out;
509 }
510 if (n > PRIO_MAX)
511 n = PRIO_MAX;
512 if (n < PRIO_MIN)
513 n = PRIO_MIN;
514 if (n < chgp->p_nice && suser(ucred, &curp->p_acflag)) {
515 error = EACCES;
516 goto out;
517 }
518 #if CONFIG_MACF
519 error = mac_proc_check_sched(curp, chgp);
520 if (error)
521 goto out;
522 #endif
523 proc_lock(chgp);
524 chgp->p_nice = n;
525 proc_unlock(chgp);
526 (void)resetpriority(chgp);
527 out:
528 kauth_cred_unref(&ucred);
529 kauth_cred_unref(&my_cred);
530 return (error);
531 }
532
533 static int
534 set_gpudeny_proc(struct proc *curp, struct proc *targetp, int priority)
535 {
536 int error = 0;
537 kauth_cred_t ucred;
538 kauth_cred_t target_cred;
539
540 ucred = kauth_cred_get();
541 target_cred = kauth_cred_proc_ref(targetp);
542
543 /* TODO: Entitlement instead of uid check */
544
545 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
546 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
547 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
548 error = EPERM;
549 goto out;
550 }
551
552 if (curp == targetp) {
553 error = EPERM;
554 goto out;
555 }
556
557 #if CONFIG_MACF
558 error = mac_proc_check_sched(curp, targetp);
559 if (error)
560 goto out;
561 #endif
562
563 switch (priority) {
564 case PRIO_DARWIN_GPU_DENY:
565 task_set_gpu_denied(proc_task(targetp), TRUE);
566 break;
567 case PRIO_DARWIN_GPU_ALLOW:
568 task_set_gpu_denied(proc_task(targetp), FALSE);
569 break;
570 default:
571 error = EINVAL;
572 goto out;
573 }
574
575 out:
576 kauth_cred_unref(&target_cred);
577 return (error);
578
579 }
580
581 static int
582 proc_set_darwin_role(proc_t curp, proc_t targetp, int priority)
583 {
584 int error = 0;
585 uint32_t flagsp;
586
587 kauth_cred_t ucred, target_cred;
588
589 ucred = kauth_cred_get();
590 target_cred = kauth_cred_proc_ref(targetp);
591
592 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
593 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
594 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
595 error = EPERM;
596 goto out;
597 }
598
599 if (curp != targetp) {
600 #if CONFIG_MACF
601 if ((error = mac_proc_check_sched(curp, targetp)))
602 goto out;
603 #endif
604 }
605
606 proc_get_darwinbgstate(proc_task(targetp), &flagsp);
607 if ((flagsp & PROC_FLAG_APPLICATION) != PROC_FLAG_APPLICATION) {
608 error = ENOTSUP;
609 goto out;
610 }
611
612 integer_t role = 0;
613
614 switch (priority) {
615 case PRIO_DARWIN_ROLE_DEFAULT:
616 role = TASK_UNSPECIFIED;
617 break;
618 case PRIO_DARWIN_ROLE_UI_FOCAL:
619 role = TASK_FOREGROUND_APPLICATION;
620 break;
621 case PRIO_DARWIN_ROLE_UI:
622 role = TASK_BACKGROUND_APPLICATION;
623 break;
624 case PRIO_DARWIN_ROLE_NON_UI:
625 role = TASK_NONUI_APPLICATION;
626 break;
627 default:
628 error = EINVAL;
629 goto out;
630 }
631
632 proc_set_task_policy(proc_task(targetp), THREAD_NULL,
633 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE, role);
634
635 out:
636 kauth_cred_unref(&target_cred);
637 return (error);
638 }
639
640 static int
641 proc_get_darwin_role(proc_t curp, proc_t targetp, int *priority)
642 {
643 int error = 0;
644 int role = 0;
645
646 kauth_cred_t ucred, target_cred;
647
648 ucred = kauth_cred_get();
649 target_cred = kauth_cred_proc_ref(targetp);
650
651 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
652 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
653 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
654 error = EPERM;
655 goto out;
656 }
657
658 if (curp != targetp) {
659 #if CONFIG_MACF
660 if ((error = mac_proc_check_sched(curp, targetp)))
661 goto out;
662 #endif
663 }
664
665 role = proc_get_task_policy(proc_task(targetp), THREAD_NULL,
666 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE);
667
668 switch (role) {
669 case TASK_FOREGROUND_APPLICATION:
670 *priority = PRIO_DARWIN_ROLE_UI_FOCAL;
671 break;
672 case TASK_BACKGROUND_APPLICATION:
673 *priority = PRIO_DARWIN_ROLE_UI;
674 break;
675 case TASK_NONUI_APPLICATION:
676 *priority = PRIO_DARWIN_ROLE_NON_UI;
677 break;
678 case TASK_UNSPECIFIED:
679 default:
680 *priority = PRIO_DARWIN_ROLE_DEFAULT;
681 break;
682 }
683
684 out:
685 kauth_cred_unref(&target_cred);
686 return (error);
687 }
688
689
690 static int
691 get_background_proc(struct proc *curp, struct proc *targetp, int *priority)
692 {
693 int external = 0;
694 int error = 0;
695 kauth_cred_t ucred, target_cred;
696
697 ucred = kauth_cred_get();
698 target_cred = kauth_cred_proc_ref(targetp);
699
700 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
701 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
702 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
703 error = EPERM;
704 goto out;
705 }
706
707 external = (curp == targetp) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL;
708
709 *priority = proc_get_task_policy(current_task(), THREAD_NULL, external, TASK_POLICY_DARWIN_BG);
710
711 out:
712 kauth_cred_unref(&target_cred);
713 return (error);
714 }
715
716 static int
717 do_background_proc(struct proc *curp, struct proc *targetp, int priority)
718 {
719 #if !CONFIG_MACF
720 #pragma unused(curp)
721 #endif
722 int error = 0;
723 kauth_cred_t ucred;
724 kauth_cred_t target_cred;
725 int external;
726 int enable;
727
728 ucred = kauth_cred_get();
729 target_cred = kauth_cred_proc_ref(targetp);
730
731 if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
732 kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
733 kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred))
734 {
735 error = EPERM;
736 goto out;
737 }
738
739 #if CONFIG_MACF
740 error = mac_proc_check_sched(curp, targetp);
741 if (error)
742 goto out;
743 #endif
744
745 external = (curp == targetp) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL;
746
747 switch (priority) {
748 case PRIO_DARWIN_BG:
749 enable = TASK_POLICY_ENABLE;
750 break;
751 case PRIO_DARWIN_NONUI:
752 /* ignored for compatibility */
753 goto out;
754 default:
755 /* TODO: EINVAL if priority != 0 */
756 enable = TASK_POLICY_DISABLE;
757 break;
758 }
759
760 proc_set_task_policy(proc_task(targetp), THREAD_NULL, external, TASK_POLICY_DARWIN_BG, enable);
761
762 out:
763 kauth_cred_unref(&target_cred);
764 return (error);
765 }
766
767 static void
768 do_background_socket(struct proc *p, thread_t thread)
769 {
770 #if SOCKETS
771 struct filedesc *fdp;
772 struct fileproc *fp;
773 int i, background;
774
775 proc_fdlock(p);
776
777 if (thread != THREAD_NULL)
778 background = proc_get_effective_thread_policy(thread, TASK_POLICY_ALL_SOCKETS_BG);
779 else
780 background = proc_get_effective_task_policy(proc_task(p), TASK_POLICY_ALL_SOCKETS_BG);
781
782 if (background) {
783 /*
784 * For PRIO_DARWIN_PROCESS (thread is NULL), simply mark
785 * the sockets with the background flag. There's nothing
786 * to do here for the PRIO_DARWIN_THREAD case.
787 */
788 if (thread == THREAD_NULL) {
789 fdp = p->p_fd;
790
791 for (i = 0; i < fdp->fd_nfiles; i++) {
792 struct socket *sockp;
793
794 fp = fdp->fd_ofiles[i];
795 if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0 ||
796 FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET) {
797 continue;
798 }
799 sockp = (struct socket *)fp->f_fglob->fg_data;
800 socket_set_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
801 sockp->so_background_thread = NULL;
802 }
803 }
804 } else {
805 /* disable networking IO throttle.
806 * NOTE - It is a known limitation of the current design that we
807 * could potentially clear TRAFFIC_MGT_SO_BACKGROUND bit for
808 * sockets created by other threads within this process.
809 */
810 fdp = p->p_fd;
811 for ( i = 0; i < fdp->fd_nfiles; i++ ) {
812 struct socket *sockp;
813
814 fp = fdp->fd_ofiles[ i ];
815 if ( fp == NULL || (fdp->fd_ofileflags[ i ] & UF_RESERVED) != 0 ||
816 FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET ) {
817 continue;
818 }
819 sockp = (struct socket *)fp->f_fglob->fg_data;
820 /* skip if only clearing this thread's sockets */
821 if ((thread) && (sockp->so_background_thread != thread)) {
822 continue;
823 }
824 socket_clear_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
825 sockp->so_background_thread = NULL;
826 }
827 }
828
829 proc_fdunlock(p);
830 #else
831 #pragma unused(p, thread)
832 #endif
833 }
834
835
836 /*
837 * do_background_thread
838 * Returns: 0 Success
839 * EPERM Tried to background while in vfork
840 * XXX - todo - does this need a MACF hook?
841 */
842 static int
843 do_background_thread(struct proc *curp, thread_t thread, int priority)
844 {
845 struct uthread *ut;
846 int enable, external;
847 int rv = 0;
848
849 ut = get_bsdthread_info(thread);
850
851 /* Backgrounding is unsupported for threads in vfork */
852 if ((ut->uu_flag & UT_VFORK) != 0)
853 return(EPERM);
854
855 if (thread_is_static_param(thread)) {
856 return(EPERM);
857 }
858
859 /* Not allowed to combine QoS and DARWIN_BG, doing so strips the QoS */
860 if (thread_has_qos_policy(thread)) {
861 thread_remove_qos_policy(thread);
862 rv = EIDRM;
863 }
864
865 /* TODO: Fail if someone passes something besides 0 or PRIO_DARWIN_BG */
866 enable = (priority == PRIO_DARWIN_BG) ? TASK_POLICY_ENABLE : TASK_POLICY_DISABLE;
867 external = (current_thread() == thread) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL;
868
869 proc_set_task_policy_thread(curp->task, thread_tid(thread), external,
870 TASK_POLICY_DARWIN_BG, enable);
871
872 return rv;
873 }
874
875
876 /*
877 * Returns: 0 Success
878 * copyin:EFAULT
879 * dosetrlimit:
880 */
881 /* ARGSUSED */
882 int
883 setrlimit(struct proc *p, struct setrlimit_args *uap, __unused int32_t *retval)
884 {
885 struct rlimit alim;
886 int error;
887
888 if ((error = copyin(uap->rlp, (caddr_t)&alim,
889 sizeof (struct rlimit))))
890 return (error);
891
892 return (dosetrlimit(p, uap->which, &alim));
893 }
894
895 /*
896 * Returns: 0 Success
897 * EINVAL
898 * ENOMEM Cannot copy limit structure
899 * suser:EPERM
900 *
901 * Notes: EINVAL is returned both for invalid arguments, and in the
902 * case that the current usage (e.g. RLIMIT_STACK) is already
903 * in excess of the requested limit.
904 */
905 int
906 dosetrlimit(struct proc *p, u_int which, struct rlimit *limp)
907 {
908 struct rlimit *alimp;
909 int error;
910 kern_return_t kr;
911 int posix = (which & _RLIMIT_POSIX_FLAG) ? 1 : 0;
912
913 /* Mask out POSIX flag, saved above */
914 which &= ~_RLIMIT_POSIX_FLAG;
915
916 if (which >= RLIM_NLIMITS)
917 return (EINVAL);
918
919 alimp = &p->p_rlimit[which];
920 if (limp->rlim_cur > limp->rlim_max)
921 return EINVAL;
922
923 if (limp->rlim_cur > alimp->rlim_max ||
924 limp->rlim_max > alimp->rlim_max)
925 if ((error = suser(kauth_cred_get(), &p->p_acflag))) {
926 return (error);
927 }
928
929 proc_limitblock(p);
930
931 if ((error = proc_limitreplace(p)) != 0) {
932 proc_limitunblock(p);
933 return(error);
934 }
935
936 alimp = &p->p_rlimit[which];
937
938 switch (which) {
939
940 case RLIMIT_CPU:
941 if (limp->rlim_cur == RLIM_INFINITY) {
942 task_vtimer_clear(p->task, TASK_VTIMER_RLIM);
943 timerclear(&p->p_rlim_cpu);
944 }
945 else {
946 task_absolutetime_info_data_t tinfo;
947 mach_msg_type_number_t count;
948 struct timeval ttv, tv;
949 clock_sec_t tv_sec;
950 clock_usec_t tv_usec;
951
952 count = TASK_ABSOLUTETIME_INFO_COUNT;
953 task_info(p->task, TASK_ABSOLUTETIME_INFO,
954 (task_info_t)&tinfo, &count);
955 absolutetime_to_microtime(tinfo.total_user + tinfo.total_system,
956 &tv_sec, &tv_usec);
957 ttv.tv_sec = tv_sec;
958 ttv.tv_usec = tv_usec;
959
960 tv.tv_sec = (limp->rlim_cur > __INT_MAX__ ? __INT_MAX__ : limp->rlim_cur);
961 tv.tv_usec = 0;
962 timersub(&tv, &ttv, &p->p_rlim_cpu);
963
964 timerclear(&tv);
965 if (timercmp(&p->p_rlim_cpu, &tv, >))
966 task_vtimer_set(p->task, TASK_VTIMER_RLIM);
967 else {
968 task_vtimer_clear(p->task, TASK_VTIMER_RLIM);
969
970 timerclear(&p->p_rlim_cpu);
971
972 psignal(p, SIGXCPU);
973 }
974 }
975 break;
976
977 case RLIMIT_DATA:
978 if (limp->rlim_cur > maxdmap)
979 limp->rlim_cur = maxdmap;
980 if (limp->rlim_max > maxdmap)
981 limp->rlim_max = maxdmap;
982 break;
983
984 case RLIMIT_STACK:
985 /* Disallow illegal stack size instead of clipping */
986 if (limp->rlim_cur > maxsmap ||
987 limp->rlim_max > maxsmap) {
988 if (posix) {
989 error = EINVAL;
990 goto out;
991 }
992 else {
993 /*
994 * 4797860 - workaround poorly written installers by
995 * doing previous implementation (< 10.5) when caller
996 * is non-POSIX conforming.
997 */
998 if (limp->rlim_cur > maxsmap)
999 limp->rlim_cur = maxsmap;
1000 if (limp->rlim_max > maxsmap)
1001 limp->rlim_max = maxsmap;
1002 }
1003 }
1004
1005 /*
1006 * Stack is allocated to the max at exec time with only
1007 * "rlim_cur" bytes accessible. If stack limit is going
1008 * up make more accessible, if going down make inaccessible.
1009 */
1010 if (limp->rlim_cur > alimp->rlim_cur) {
1011 user_addr_t addr;
1012 user_size_t size;
1013
1014 /* grow stack */
1015 size = round_page_64(limp->rlim_cur);
1016 size -= round_page_64(alimp->rlim_cur);
1017
1018 addr = p->user_stack - round_page_64(limp->rlim_cur);
1019 kr = mach_vm_protect(current_map(),
1020 addr, size,
1021 FALSE, VM_PROT_DEFAULT);
1022 if (kr != KERN_SUCCESS) {
1023 error = EINVAL;
1024 goto out;
1025 }
1026 } else if (limp->rlim_cur < alimp->rlim_cur) {
1027 user_addr_t addr;
1028 user_size_t size;
1029 user_addr_t cur_sp;
1030
1031 /* shrink stack */
1032
1033 /*
1034 * First check if new stack limit would agree
1035 * with current stack usage.
1036 * Get the current thread's stack pointer...
1037 */
1038 cur_sp = thread_adjuserstack(current_thread(),
1039 0);
1040 if (cur_sp <= p->user_stack &&
1041 cur_sp > (p->user_stack -
1042 round_page_64(alimp->rlim_cur))) {
1043 /* stack pointer is in main stack */
1044 if (cur_sp <= (p->user_stack -
1045 round_page_64(limp->rlim_cur))) {
1046 /*
1047 * New limit would cause
1048 * current usage to be invalid:
1049 * reject new limit.
1050 */
1051 error = EINVAL;
1052 goto out;
1053 }
1054 } else {
1055 /* not on the main stack: reject */
1056 error = EINVAL;
1057 goto out;
1058 }
1059
1060 size = round_page_64(alimp->rlim_cur);
1061 size -= round_page_64(limp->rlim_cur);
1062
1063 addr = p->user_stack - round_page_64(alimp->rlim_cur);
1064
1065 kr = mach_vm_protect(current_map(),
1066 addr, size,
1067 FALSE, VM_PROT_NONE);
1068 if (kr != KERN_SUCCESS) {
1069 error = EINVAL;
1070 goto out;
1071 }
1072 } else {
1073 /* no change ... */
1074 }
1075 break;
1076
1077 case RLIMIT_NOFILE:
1078 /*
1079 * Only root can set the maxfiles limits, as it is
1080 * systemwide resource. If we are expecting POSIX behavior,
1081 * instead of clamping the value, return EINVAL. We do this
1082 * because historically, people have been able to attempt to
1083 * set RLIM_INFINITY to get "whatever the maximum is".
1084 */
1085 if ( kauth_cred_issuser(kauth_cred_get()) ) {
1086 if (limp->rlim_cur != alimp->rlim_cur &&
1087 limp->rlim_cur > (rlim_t)maxfiles) {
1088 if (posix) {
1089 error = EINVAL;
1090 goto out;
1091 }
1092 limp->rlim_cur = maxfiles;
1093 }
1094 if (limp->rlim_max != alimp->rlim_max &&
1095 limp->rlim_max > (rlim_t)maxfiles)
1096 limp->rlim_max = maxfiles;
1097 }
1098 else {
1099 if (limp->rlim_cur != alimp->rlim_cur &&
1100 limp->rlim_cur > (rlim_t)maxfilesperproc) {
1101 if (posix) {
1102 error = EINVAL;
1103 goto out;
1104 }
1105 limp->rlim_cur = maxfilesperproc;
1106 }
1107 if (limp->rlim_max != alimp->rlim_max &&
1108 limp->rlim_max > (rlim_t)maxfilesperproc)
1109 limp->rlim_max = maxfilesperproc;
1110 }
1111 break;
1112
1113 case RLIMIT_NPROC:
1114 /*
1115 * Only root can set to the maxproc limits, as it is
1116 * systemwide resource; all others are limited to
1117 * maxprocperuid (presumably less than maxproc).
1118 */
1119 if ( kauth_cred_issuser(kauth_cred_get()) ) {
1120 if (limp->rlim_cur > (rlim_t)maxproc)
1121 limp->rlim_cur = maxproc;
1122 if (limp->rlim_max > (rlim_t)maxproc)
1123 limp->rlim_max = maxproc;
1124 }
1125 else {
1126 if (limp->rlim_cur > (rlim_t)maxprocperuid)
1127 limp->rlim_cur = maxprocperuid;
1128 if (limp->rlim_max > (rlim_t)maxprocperuid)
1129 limp->rlim_max = maxprocperuid;
1130 }
1131 break;
1132
1133 case RLIMIT_MEMLOCK:
1134 /*
1135 * Tell the Mach VM layer about the new limit value.
1136 */
1137
1138 vm_map_set_user_wire_limit(current_map(), limp->rlim_cur);
1139 break;
1140
1141 } /* switch... */
1142 proc_lock(p);
1143 *alimp = *limp;
1144 proc_unlock(p);
1145 error = 0;
1146 out:
1147 proc_limitunblock(p);
1148 return (error);
1149 }
1150
1151 /* ARGSUSED */
1152 int
1153 getrlimit(struct proc *p, struct getrlimit_args *uap, __unused int32_t *retval)
1154 {
1155 struct rlimit lim;
1156
1157 /*
1158 * Take out flag now in case we need to use it to trigger variant
1159 * behaviour later.
1160 */
1161 uap->which &= ~_RLIMIT_POSIX_FLAG;
1162
1163 if (uap->which >= RLIM_NLIMITS)
1164 return (EINVAL);
1165 proc_limitget(p, uap->which, &lim);
1166 return (copyout((caddr_t)&lim,
1167 uap->rlp, sizeof (struct rlimit)));
1168 }
1169
1170 /*
1171 * Transform the running time and tick information in proc p into user,
1172 * system, and interrupt time usage.
1173 */
1174 /* No lock on proc is held for this.. */
1175 void
1176 calcru(struct proc *p, struct timeval *up, struct timeval *sp, struct timeval *ip)
1177 {
1178 task_t task;
1179
1180 timerclear(up);
1181 timerclear(sp);
1182 if (ip != NULL)
1183 timerclear(ip);
1184
1185 task = p->task;
1186 if (task) {
1187 mach_task_basic_info_data_t tinfo;
1188 task_thread_times_info_data_t ttimesinfo;
1189 task_events_info_data_t teventsinfo;
1190 mach_msg_type_number_t task_info_count, task_ttimes_count;
1191 mach_msg_type_number_t task_events_count;
1192 struct timeval ut,st;
1193
1194 task_info_count = MACH_TASK_BASIC_INFO_COUNT;
1195 task_info(task, MACH_TASK_BASIC_INFO,
1196 (task_info_t)&tinfo, &task_info_count);
1197 ut.tv_sec = tinfo.user_time.seconds;
1198 ut.tv_usec = tinfo.user_time.microseconds;
1199 st.tv_sec = tinfo.system_time.seconds;
1200 st.tv_usec = tinfo.system_time.microseconds;
1201 timeradd(&ut, up, up);
1202 timeradd(&st, sp, sp);
1203
1204 task_ttimes_count = TASK_THREAD_TIMES_INFO_COUNT;
1205 task_info(task, TASK_THREAD_TIMES_INFO,
1206 (task_info_t)&ttimesinfo, &task_ttimes_count);
1207
1208 ut.tv_sec = ttimesinfo.user_time.seconds;
1209 ut.tv_usec = ttimesinfo.user_time.microseconds;
1210 st.tv_sec = ttimesinfo.system_time.seconds;
1211 st.tv_usec = ttimesinfo.system_time.microseconds;
1212 timeradd(&ut, up, up);
1213 timeradd(&st, sp, sp);
1214
1215 task_events_count = TASK_EVENTS_INFO_COUNT;
1216 task_info(task, TASK_EVENTS_INFO,
1217 (task_info_t)&teventsinfo, &task_events_count);
1218
1219 /*
1220 * No need to lock "p": this does not need to be
1221 * completely consistent, right ?
1222 */
1223 p->p_stats->p_ru.ru_minflt = (teventsinfo.faults -
1224 teventsinfo.pageins);
1225 p->p_stats->p_ru.ru_majflt = teventsinfo.pageins;
1226 p->p_stats->p_ru.ru_nivcsw = (teventsinfo.csw -
1227 p->p_stats->p_ru.ru_nvcsw);
1228 if (p->p_stats->p_ru.ru_nivcsw < 0)
1229 p->p_stats->p_ru.ru_nivcsw = 0;
1230
1231 p->p_stats->p_ru.ru_maxrss = tinfo.resident_size_max;
1232 }
1233 }
1234
1235 __private_extern__ void munge_user64_rusage(struct rusage *a_rusage_p, struct user64_rusage *a_user_rusage_p);
1236 __private_extern__ void munge_user32_rusage(struct rusage *a_rusage_p, struct user32_rusage *a_user_rusage_p);
1237
1238 /* ARGSUSED */
1239 int
1240 getrusage(struct proc *p, struct getrusage_args *uap, __unused int32_t *retval)
1241 {
1242 struct rusage *rup, rubuf;
1243 struct user64_rusage rubuf64;
1244 struct user32_rusage rubuf32;
1245 size_t retsize = sizeof(rubuf); /* default: 32 bits */
1246 caddr_t retbuf = (caddr_t)&rubuf; /* default: 32 bits */
1247 struct timeval utime;
1248 struct timeval stime;
1249
1250
1251 switch (uap->who) {
1252 case RUSAGE_SELF:
1253 calcru(p, &utime, &stime, NULL);
1254 proc_lock(p);
1255 rup = &p->p_stats->p_ru;
1256 rup->ru_utime = utime;
1257 rup->ru_stime = stime;
1258
1259 rubuf = *rup;
1260 proc_unlock(p);
1261
1262 break;
1263
1264 case RUSAGE_CHILDREN:
1265 proc_lock(p);
1266 rup = &p->p_stats->p_cru;
1267 rubuf = *rup;
1268 proc_unlock(p);
1269 break;
1270
1271 default:
1272 return (EINVAL);
1273 }
1274 if (IS_64BIT_PROCESS(p)) {
1275 retsize = sizeof(rubuf64);
1276 retbuf = (caddr_t)&rubuf64;
1277 munge_user64_rusage(&rubuf, &rubuf64);
1278 } else {
1279 retsize = sizeof(rubuf32);
1280 retbuf = (caddr_t)&rubuf32;
1281 munge_user32_rusage(&rubuf, &rubuf32);
1282 }
1283
1284 return (copyout(retbuf, uap->rusage, retsize));
1285 }
1286
1287 void
1288 ruadd(struct rusage *ru, struct rusage *ru2)
1289 {
1290 long *ip, *ip2;
1291 long i;
1292
1293 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
1294 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
1295 if (ru->ru_maxrss < ru2->ru_maxrss)
1296 ru->ru_maxrss = ru2->ru_maxrss;
1297 ip = &ru->ru_first; ip2 = &ru2->ru_first;
1298 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
1299 *ip++ += *ip2++;
1300 }
1301
1302 /*
1303 * Add the rusage stats of child in parent.
1304 *
1305 * It adds rusage statistics of child process and statistics of all its
1306 * children to its parent.
1307 *
1308 * Note: proc lock of parent should be held while calling this function.
1309 */
1310 void
1311 update_rusage_info_child(struct rusage_info_child *ri, rusage_info_current *ri_current)
1312 {
1313 ri->ri_child_user_time += (ri_current->ri_user_time +
1314 ri_current->ri_child_user_time);
1315 ri->ri_child_system_time += (ri_current->ri_system_time +
1316 ri_current->ri_child_system_time);
1317 ri->ri_child_pkg_idle_wkups += (ri_current->ri_pkg_idle_wkups +
1318 ri_current->ri_child_pkg_idle_wkups);
1319 ri->ri_child_interrupt_wkups += (ri_current->ri_interrupt_wkups +
1320 ri_current->ri_child_interrupt_wkups);
1321 ri->ri_child_pageins += (ri_current->ri_pageins +
1322 ri_current->ri_child_pageins);
1323 ri->ri_child_elapsed_abstime += ((ri_current->ri_proc_exit_abstime -
1324 ri_current->ri_proc_start_abstime) + ri_current->ri_child_elapsed_abstime);
1325 }
1326
1327 void
1328 proc_limitget(proc_t p, int which, struct rlimit * limp)
1329 {
1330 proc_list_lock();
1331 limp->rlim_cur = p->p_rlimit[which].rlim_cur;
1332 limp->rlim_max = p->p_rlimit[which].rlim_max;
1333 proc_list_unlock();
1334 }
1335
1336
1337 void
1338 proc_limitdrop(proc_t p, int exiting)
1339 {
1340 struct plimit * freelim = NULL;
1341 struct plimit * freeoldlim = NULL;
1342
1343 proc_list_lock();
1344
1345 if (--p->p_limit->pl_refcnt == 0) {
1346 freelim = p->p_limit;
1347 p->p_limit = NULL;
1348 }
1349 if ((exiting != 0) && (p->p_olimit != NULL) && (--p->p_olimit->pl_refcnt == 0)) {
1350 freeoldlim = p->p_olimit;
1351 p->p_olimit = NULL;
1352 }
1353
1354 proc_list_unlock();
1355 if (freelim != NULL)
1356 FREE_ZONE(freelim, sizeof *p->p_limit, M_PLIMIT);
1357 if (freeoldlim != NULL)
1358 FREE_ZONE(freeoldlim, sizeof *p->p_olimit, M_PLIMIT);
1359 }
1360
1361
1362 void
1363 proc_limitfork(proc_t parent, proc_t child)
1364 {
1365 proc_list_lock();
1366 child->p_limit = parent->p_limit;
1367 child->p_limit->pl_refcnt++;
1368 child->p_olimit = NULL;
1369 proc_list_unlock();
1370 }
1371
1372 void
1373 proc_limitblock(proc_t p)
1374 {
1375 proc_lock(p);
1376 while (p->p_lflag & P_LLIMCHANGE) {
1377 p->p_lflag |= P_LLIMWAIT;
1378 msleep(&p->p_olimit, &p->p_mlock, 0, "proc_limitblock", NULL);
1379 }
1380 p->p_lflag |= P_LLIMCHANGE;
1381 proc_unlock(p);
1382
1383 }
1384
1385
1386 void
1387 proc_limitunblock(proc_t p)
1388 {
1389 proc_lock(p);
1390 p->p_lflag &= ~P_LLIMCHANGE;
1391 if (p->p_lflag & P_LLIMWAIT) {
1392 p->p_lflag &= ~P_LLIMWAIT;
1393 wakeup(&p->p_olimit);
1394 }
1395 proc_unlock(p);
1396 }
1397
1398 /* This is called behind serialization provided by proc_limitblock/unlbock */
1399 int
1400 proc_limitreplace(proc_t p)
1401 {
1402 struct plimit *copy;
1403
1404
1405 proc_list_lock();
1406
1407 if (p->p_limit->pl_refcnt == 1) {
1408 proc_list_unlock();
1409 return(0);
1410 }
1411
1412 proc_list_unlock();
1413
1414 MALLOC_ZONE(copy, struct plimit *,
1415 sizeof(struct plimit), M_PLIMIT, M_WAITOK);
1416 if (copy == NULL) {
1417 return(ENOMEM);
1418 }
1419
1420 proc_list_lock();
1421 bcopy(p->p_limit->pl_rlimit, copy->pl_rlimit,
1422 sizeof(struct rlimit) * RLIM_NLIMITS);
1423 copy->pl_refcnt = 1;
1424 /* hang on to reference to old till process exits */
1425 p->p_olimit = p->p_limit;
1426 p->p_limit = copy;
1427 proc_list_unlock();
1428
1429 return(0);
1430 }
1431
1432 /*
1433 * iopolicysys
1434 *
1435 * Description: System call MUX for use in manipulating I/O policy attributes of the current process or thread
1436 *
1437 * Parameters: cmd Policy command
1438 * arg Pointer to policy arguments
1439 *
1440 * Returns: 0 Success
1441 * EINVAL Invalid command or invalid policy arguments
1442 *
1443 */
1444
1445 static int
1446 iopolicysys_disk(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param);
1447 static int
1448 iopolicysys_vfs(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param);
1449
1450 int
1451 iopolicysys(struct proc *p, struct iopolicysys_args *uap, int32_t *retval)
1452 {
1453 int error = 0;
1454 struct _iopol_param_t iop_param;
1455
1456 if ((error = copyin(uap->arg, &iop_param, sizeof(iop_param))) != 0)
1457 goto out;
1458
1459 switch (iop_param.iop_iotype) {
1460 case IOPOL_TYPE_DISK:
1461 error = iopolicysys_disk(p, uap->cmd, iop_param.iop_scope, iop_param.iop_policy, &iop_param);
1462 if (error == EIDRM) {
1463 *retval = -2;
1464 error = 0;
1465 }
1466 if (error)
1467 goto out;
1468 break;
1469 case IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY:
1470 error = iopolicysys_vfs(p, uap->cmd, iop_param.iop_scope, iop_param.iop_policy, &iop_param);
1471 if (error)
1472 goto out;
1473 break;
1474 default:
1475 error = EINVAL;
1476 goto out;
1477 }
1478
1479 /* Individual iotype handlers are expected to update iop_param, if requested with a GET command */
1480 if (uap->cmd == IOPOL_CMD_GET) {
1481 error = copyout((caddr_t)&iop_param, uap->arg, sizeof(iop_param));
1482 if (error)
1483 goto out;
1484 }
1485
1486 out:
1487 return (error);
1488 }
1489
1490 static int
1491 iopolicysys_disk(struct proc *p __unused, int cmd, int scope, int policy, struct _iopol_param_t *iop_param)
1492 {
1493 int error = 0;
1494 thread_t thread;
1495 int policy_flavor;
1496
1497 /* Validate scope */
1498 switch (scope) {
1499 case IOPOL_SCOPE_PROCESS:
1500 thread = THREAD_NULL;
1501 policy_flavor = TASK_POLICY_IOPOL;
1502 break;
1503
1504 case IOPOL_SCOPE_THREAD:
1505 thread = current_thread();
1506 policy_flavor = TASK_POLICY_IOPOL;
1507
1508 /* Not allowed to combine QoS and (non-PASSIVE) IO policy, doing so strips the QoS */
1509 if (cmd == IOPOL_CMD_SET && thread_has_qos_policy(thread)) {
1510 switch (policy) {
1511 case IOPOL_DEFAULT:
1512 case IOPOL_PASSIVE:
1513 break;
1514 case IOPOL_UTILITY:
1515 case IOPOL_THROTTLE:
1516 case IOPOL_IMPORTANT:
1517 case IOPOL_STANDARD:
1518 if (!thread_is_static_param(thread)) {
1519 thread_remove_qos_policy(thread);
1520 /*
1521 * This is not an error case, this is to return a marker to user-space that
1522 * we stripped the thread of its QoS class.
1523 */
1524 error = EIDRM;
1525 break;
1526 }
1527 /* otherwise, fall through to the error case. */
1528 default:
1529 error = EINVAL;
1530 goto out;
1531 }
1532 }
1533 break;
1534
1535 case IOPOL_SCOPE_DARWIN_BG:
1536 thread = THREAD_NULL;
1537 policy_flavor = TASK_POLICY_DARWIN_BG_IOPOL;
1538 break;
1539
1540 default:
1541 error = EINVAL;
1542 goto out;
1543 }
1544
1545 /* Validate policy */
1546 if (cmd == IOPOL_CMD_SET) {
1547 switch (policy) {
1548 case IOPOL_DEFAULT:
1549 if (scope == IOPOL_SCOPE_DARWIN_BG) {
1550 /* the current default BG throttle level is UTILITY */
1551 policy = IOPOL_UTILITY;
1552 } else {
1553 policy = IOPOL_IMPORTANT;
1554 }
1555 break;
1556 case IOPOL_UTILITY:
1557 /* fall-through */
1558 case IOPOL_THROTTLE:
1559 /* These levels are OK */
1560 break;
1561 case IOPOL_IMPORTANT:
1562 /* fall-through */
1563 case IOPOL_STANDARD:
1564 /* fall-through */
1565 case IOPOL_PASSIVE:
1566 if (scope == IOPOL_SCOPE_DARWIN_BG) {
1567 /* These levels are invalid for BG */
1568 error = EINVAL;
1569 goto out;
1570 } else {
1571 /* OK for other scopes */
1572 }
1573 break;
1574 default:
1575 error = EINVAL;
1576 goto out;
1577 }
1578 }
1579
1580 /* Perform command */
1581 switch(cmd) {
1582 case IOPOL_CMD_SET:
1583 proc_set_task_policy(current_task(), thread,
1584 TASK_POLICY_INTERNAL, policy_flavor,
1585 policy);
1586 break;
1587 case IOPOL_CMD_GET:
1588 policy = proc_get_task_policy(current_task(), thread,
1589 TASK_POLICY_INTERNAL, policy_flavor);
1590
1591 iop_param->iop_policy = policy;
1592 break;
1593 default:
1594 error = EINVAL; /* unknown command */
1595 break;
1596 }
1597
1598 out:
1599 return (error);
1600 }
1601
1602 static int
1603 iopolicysys_vfs(struct proc *p, int cmd, int scope, int policy, struct _iopol_param_t *iop_param)
1604 {
1605 int error = 0;
1606
1607 /* Validate scope */
1608 switch (scope) {
1609 case IOPOL_SCOPE_PROCESS:
1610 /* Only process OK */
1611 break;
1612 default:
1613 error = EINVAL;
1614 goto out;
1615 }
1616
1617 /* Validate policy */
1618 if (cmd == IOPOL_CMD_SET) {
1619 switch (policy) {
1620 case IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT:
1621 /* fall-through */
1622 case IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE:
1623 /* These policies are OK */
1624 break;
1625 default:
1626 error = EINVAL;
1627 goto out;
1628 }
1629 }
1630
1631 /* Perform command */
1632 switch(cmd) {
1633 case IOPOL_CMD_SET:
1634 if (0 == kauth_cred_issuser(kauth_cred_get())) {
1635 error = EPERM;
1636 goto out;
1637 }
1638
1639 switch (policy) {
1640 case IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT:
1641 OSBitAndAtomic16(~((uint32_t)P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY), &p->p_vfs_iopolicy);
1642 break;
1643 case IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE:
1644 OSBitOrAtomic16((uint32_t)P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY, &p->p_vfs_iopolicy);
1645 break;
1646 default:
1647 error = EINVAL;
1648 goto out;
1649 }
1650
1651 break;
1652 case IOPOL_CMD_GET:
1653 iop_param->iop_policy = (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY)
1654 ? IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE
1655 : IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT;
1656 break;
1657 default:
1658 error = EINVAL; /* unknown command */
1659 break;
1660 }
1661
1662 out:
1663 return (error);
1664 }
1665
1666 /* BSD call back function for task_policy */
1667 void proc_apply_task_networkbg(void * bsd_info, thread_t thread);
1668
1669 void
1670 proc_apply_task_networkbg(void * bsd_info, thread_t thread)
1671 {
1672 assert(bsd_info != PROC_NULL);
1673
1674 pid_t pid = proc_pid((proc_t)bsd_info);
1675
1676 proc_t p = proc_find(pid);
1677
1678 if (p != PROC_NULL) {
1679 assert(p == (proc_t)bsd_info);
1680
1681 do_background_socket(p, thread);
1682 proc_rele(p);
1683 }
1684 }
1685
1686 void
1687 gather_rusage_info(proc_t p, rusage_info_current *ru, int flavor)
1688 {
1689 struct rusage_info_child *ri_child;
1690
1691 assert(p->p_stats != NULL);
1692 switch(flavor) {
1693
1694 case RUSAGE_INFO_V3:
1695 fill_task_qos_rusage(p->task, ru);
1696 fill_task_billed_usage(p->task, ru);
1697 /* fall through */
1698
1699 case RUSAGE_INFO_V2:
1700 fill_task_io_rusage(p->task, ru);
1701 /* fall through */
1702
1703 case RUSAGE_INFO_V1:
1704 /*
1705 * p->p_stats->ri_child statistics are protected under proc lock.
1706 */
1707 proc_lock(p);
1708
1709 ri_child = &(p->p_stats->ri_child);
1710 ru->ri_child_user_time = ri_child->ri_child_user_time;
1711 ru->ri_child_system_time = ri_child->ri_child_system_time;
1712 ru->ri_child_pkg_idle_wkups = ri_child->ri_child_pkg_idle_wkups;
1713 ru->ri_child_interrupt_wkups = ri_child->ri_child_interrupt_wkups;
1714 ru->ri_child_pageins = ri_child->ri_child_pageins;
1715 ru->ri_child_elapsed_abstime = ri_child->ri_child_elapsed_abstime;
1716
1717 proc_unlock(p);
1718 /* fall through */
1719
1720 case RUSAGE_INFO_V0:
1721 proc_getexecutableuuid(p, (unsigned char *)&ru->ri_uuid, sizeof (ru->ri_uuid));
1722 fill_task_rusage(p->task, ru);
1723 ru->ri_proc_start_abstime = p->p_stats->ps_start;
1724 }
1725 }
1726
1727 static void
1728 rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor)
1729 {
1730 struct rusage_info_v0 *ri_v0;
1731 struct rusage_info_v1 *ri_v1;
1732 struct rusage_info_v2 *ri_v2;
1733
1734 switch (flavor) {
1735
1736 case RUSAGE_INFO_V2:
1737 ri_v2 = (struct rusage_info_v2 *)ri_info;
1738 ri_v2->ri_diskio_bytesread = ri_current->ri_diskio_bytesread;
1739 ri_v2->ri_diskio_byteswritten = ri_current->ri_diskio_byteswritten;
1740 /* fall through */
1741
1742 case RUSAGE_INFO_V1:
1743 ri_v1 = (struct rusage_info_v1 *)ri_info;
1744 ri_v1->ri_child_user_time = ri_current->ri_child_user_time;
1745 ri_v1->ri_child_system_time = ri_current->ri_child_system_time;
1746 ri_v1->ri_child_pkg_idle_wkups = ri_current->ri_child_pkg_idle_wkups;
1747 ri_v1->ri_child_interrupt_wkups = ri_current->ri_child_interrupt_wkups;
1748 ri_v1->ri_child_pageins = ri_current->ri_child_pageins;
1749 ri_v1->ri_child_elapsed_abstime = ri_current->ri_child_elapsed_abstime;
1750 /* fall through */
1751
1752 case RUSAGE_INFO_V0:
1753 ri_v0 = (struct rusage_info_v0 *)ri_info;
1754 memcpy(&ri_v0->ri_uuid[0], &ri_current->ri_uuid[0], sizeof(ri_v0->ri_uuid));
1755 ri_v0->ri_user_time = ri_current->ri_user_time;
1756 ri_v0->ri_system_time = ri_current->ri_system_time;
1757 ri_v0->ri_pkg_idle_wkups = ri_current->ri_pkg_idle_wkups;
1758 ri_v0->ri_interrupt_wkups = ri_current->ri_interrupt_wkups;
1759 ri_v0->ri_pageins = ri_current->ri_pageins;
1760 ri_v0->ri_wired_size = ri_current->ri_wired_size;
1761 ri_v0->ri_resident_size = ri_current->ri_resident_size;
1762 ri_v0->ri_phys_footprint = ri_current->ri_phys_footprint;
1763 ri_v0->ri_proc_start_abstime = ri_current->ri_proc_start_abstime;
1764 ri_v0->ri_proc_exit_abstime = ri_current->ri_proc_exit_abstime;
1765
1766 break;
1767
1768 default:
1769 break;
1770 }
1771 }
1772
1773
1774 int
1775 proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie)
1776 {
1777 struct rusage_info_v0 ri_v0;
1778 struct rusage_info_v1 ri_v1;
1779 struct rusage_info_v2 ri_v2;
1780 struct rusage_info_v3 ri_v3;
1781
1782 rusage_info_current ri_current;
1783
1784 int error = 0;
1785
1786 switch (flavor) {
1787 case RUSAGE_INFO_V0:
1788 /*
1789 * If task is still alive, collect info from the live task itself.
1790 * Otherwise, look to the cached info in the zombie proc.
1791 */
1792 if (p->p_ru == NULL) {
1793 gather_rusage_info(p, &ri_current, flavor);
1794 ri_current.ri_proc_exit_abstime = 0;
1795 rusage_info_conversion(&ri_v0, &ri_current, flavor);
1796 } else {
1797 rusage_info_conversion(&ri_v0, &p->p_ru->ri, flavor);
1798 }
1799 error = copyout(&ri_v0, buffer, sizeof (ri_v0));
1800 break;
1801
1802 case RUSAGE_INFO_V1:
1803 /*
1804 * If task is still alive, collect info from the live task itself.
1805 * Otherwise, look to the cached info in the zombie proc.
1806 */
1807 if (p->p_ru == NULL) {
1808 gather_rusage_info(p, &ri_current, flavor);
1809 ri_current.ri_proc_exit_abstime = 0;
1810 rusage_info_conversion(&ri_v1, &ri_current, flavor);
1811 } else {
1812 rusage_info_conversion(&ri_v1, &p->p_ru->ri, flavor);
1813 }
1814 error = copyout(&ri_v1, buffer, sizeof (ri_v1));
1815 break;
1816
1817 case RUSAGE_INFO_V2:
1818 /*
1819 * If task is still alive, collect info from the live task itself.
1820 * Otherwise, look to the cached info in the zombie proc.
1821 */
1822 if (p->p_ru == NULL) {
1823 gather_rusage_info(p, &ri_current, flavor);
1824 ri_current.ri_proc_exit_abstime = 0;
1825 rusage_info_conversion(&ri_v2, &ri_current, flavor);
1826 } else {
1827 rusage_info_conversion(&ri_v2, &p->p_ru->ri, flavor);
1828 }
1829 error = copyout(&ri_v2, buffer, sizeof (ri_v2));
1830 break;
1831
1832 case RUSAGE_INFO_V3:
1833 /*
1834 * If task is still alive, collect info from the live task itself.
1835 * Otherwise, look to the cached info in the zombie proc.
1836 */
1837 if (p->p_ru == NULL) {
1838 gather_rusage_info(p, &ri_v3, flavor);
1839 ri_v3.ri_proc_exit_abstime = 0;
1840 } else {
1841 ri_v3 = p->p_ru->ri;
1842 }
1843 error = copyout(&ri_v3, buffer, sizeof (ri_v3));
1844 break;
1845
1846 default:
1847 error = EINVAL;
1848 break;
1849 }
1850
1851 return (error);
1852 }
1853
1854 static int
1855 mach_to_bsd_rv(int mach_rv)
1856 {
1857 int bsd_rv = 0;
1858
1859 switch (mach_rv) {
1860 case KERN_SUCCESS:
1861 bsd_rv = 0;
1862 break;
1863 case KERN_INVALID_ARGUMENT:
1864 bsd_rv = EINVAL;
1865 break;
1866 default:
1867 panic("unknown error %#x", mach_rv);
1868 }
1869
1870 return bsd_rv;
1871 }
1872
1873 /*
1874 * Resource limit controls
1875 *
1876 * uap->flavor available flavors:
1877 *
1878 * RLIMIT_WAKEUPS_MONITOR
1879 */
1880 int
1881 proc_rlimit_control(__unused struct proc *p, struct proc_rlimit_control_args *uap, __unused int32_t *retval)
1882 {
1883 proc_t targetp;
1884 int error = 0;
1885 struct proc_rlimit_control_wakeupmon wakeupmon_args;
1886 uint32_t cpumon_flags;
1887 uint32_t cpulimits_flags;
1888 kauth_cred_t my_cred, target_cred;
1889
1890 /* -1 implicitly means our own process (perhaps even the current thread for per-thread attributes) */
1891 if (uap->pid == -1) {
1892 targetp = proc_self();
1893 } else {
1894 targetp = proc_find(uap->pid);
1895 }
1896
1897 /* proc_self() can return NULL for an exiting process */
1898 if (targetp == PROC_NULL) {
1899 return (ESRCH);
1900 }
1901
1902 my_cred = kauth_cred_get();
1903 target_cred = kauth_cred_proc_ref(targetp);
1904
1905 if (!kauth_cred_issuser(my_cred) && kauth_cred_getruid(my_cred) &&
1906 kauth_cred_getuid(my_cred) != kauth_cred_getuid(target_cred) &&
1907 kauth_cred_getruid(my_cred) != kauth_cred_getuid(target_cred)) {
1908 proc_rele(targetp);
1909 kauth_cred_unref(&target_cred);
1910 return (EACCES);
1911 }
1912
1913 switch (uap->flavor) {
1914 case RLIMIT_WAKEUPS_MONITOR:
1915 if ((error = copyin(uap->arg, &wakeupmon_args, sizeof (wakeupmon_args))) != 0) {
1916 break;
1917 }
1918 if ((error = mach_to_bsd_rv(task_wakeups_monitor_ctl(targetp->task, &wakeupmon_args.wm_flags,
1919 &wakeupmon_args.wm_rate))) != 0) {
1920 break;
1921 }
1922 error = copyout(&wakeupmon_args, uap->arg, sizeof (wakeupmon_args));
1923 break;
1924 case RLIMIT_CPU_USAGE_MONITOR:
1925 cpumon_flags = uap->arg; // XXX temporarily stashing flags in argp (12592127)
1926 error = mach_to_bsd_rv(task_cpu_usage_monitor_ctl(targetp->task, &cpumon_flags));
1927 break;
1928 case RLIMIT_THREAD_CPULIMITS:
1929 cpulimits_flags = (uint32_t)uap->arg; // only need a limited set of bits, pass in void * argument
1930
1931 if (uap->pid != -1) {
1932 error = EINVAL;
1933 break;
1934 }
1935
1936 uint8_t percent = 0;
1937 uint32_t ms_refill = 0;
1938 uint64_t ns_refill;
1939
1940 percent = (uint8_t)(cpulimits_flags & 0xffU); /* low 8 bits for percent */
1941 ms_refill = (cpulimits_flags >> 8) & 0xffffff; /* next 24 bits represent ms refill value */
1942 if (percent >= 100) {
1943 error = EINVAL;
1944 break;
1945 }
1946
1947 ns_refill = ((uint64_t)ms_refill) * NSEC_PER_MSEC;
1948
1949 error = mach_to_bsd_rv(thread_set_cpulimit(THREAD_CPULIMIT_BLOCK, percent, ns_refill));
1950 break;
1951 default:
1952 error = EINVAL;
1953 break;
1954 }
1955
1956 proc_rele(targetp);
1957 kauth_cred_unref(&target_cred);
1958
1959 /*
1960 * Return value from this function becomes errno to userland caller.
1961 */
1962 return (error);
1963 }
1964
1965 /*
1966 * Return the current amount of CPU consumed by this thread (in either user or kernel mode)
1967 */
1968 int thread_selfusage(struct proc *p __unused, struct thread_selfusage_args *uap __unused, uint64_t *retval)
1969 {
1970 uint64_t runtime;
1971
1972 runtime = thread_get_runtime_self();
1973 *retval = runtime;
1974
1975 return (0);
1976 }