2 * Copyright (c) 2005, 2010 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * process policy syscall implementation
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/proc_internal.h>
38 #include <sys/kauth.h>
39 #include <sys/unistd.h>
41 #include <sys/ioctl.h>
45 #include <security/audit/audit.h>
47 #include <mach/machine.h>
48 #include <mach/mach_types.h>
49 #include <mach/vm_param.h>
50 #include <kern/task.h>
51 #include <kern/lock.h>
52 #include <kern/kalloc.h>
53 #include <kern/assert.h>
54 #include <vm/vm_kern.h>
55 #include <vm/vm_map.h>
56 #include <mach/host_info.h>
57 #include <mach/task_info.h>
58 #include <mach/thread_info.h>
59 #include <mach/vm_region.h>
61 #include <sys/process_policy.h>
62 #include <sys/proc_info.h>
63 #include <sys/bsdtask_info.h>
64 #include <sys/kdebug.h>
65 #include <sys/sysproto.h>
66 #include <sys/msgbuf.h>
68 #include <machine/machine_routines.h>
70 #include <kern/ipc_misc.h>
71 #include <vm/vm_protos.h>
73 #include <security/mac.h>
74 #include <sys/kern_memorystatus.h>
75 #endif /* CONFIG_EMBEDDED */
77 static int handle_background(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
78 static int handle_hwaccess(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
79 static int handle_lowresrouce(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
80 static int handle_resourceuse(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
81 static int handle_apptype(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
83 extern kern_return_t
task_suspend(task_t
);
84 extern kern_return_t
task_resume(task_t
);
87 static int handle_applifecycle(int scope
, int action
, int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
);
88 #endif /* CONFIG_EMBEDDED */
91 /***************************** process_policy ********************/
94 *int process_policy(int scope, int action, int policy, int policy_subtype,
95 * proc_policy_attribute_t * attrp, pid_t target_pid,
96 * uint64_t target_threadid)
97 *{ int process_policy(int scope, int action, int policy, int policy_subtype,
98 * user_addr_t attrp, pid_t target_pid, uint64_t target_threadid); }
101 /* system call implementaion */
103 process_policy(__unused
struct proc
*p
, struct process_policy_args
* uap
, __unused
int32_t *retval
)
106 int scope
= uap
->scope
;
107 int policy
= uap
->policy
;
108 int action
= uap
->action
;
109 int policy_subtype
= uap
->policy_subtype
;
110 user_addr_t attrp
= uap
->attrp
;
111 pid_t target_pid
= uap
->target_pid
;
112 uint64_t target_threadid
= uap
->target_threadid
;
113 proc_t target_proc
= PROC_NULL
;
114 proc_t curp
= current_proc();
115 kauth_cred_t my_cred
;
117 kauth_cred_t target_cred
;
120 if ((scope
!= PROC_POLICY_SCOPE_PROCESS
) && (scope
!= PROC_POLICY_SCOPE_THREAD
)) {
123 target_proc
= proc_find(target_pid
);
124 if (target_proc
== PROC_NULL
) {
128 my_cred
= kauth_cred_get();
131 target_cred
= kauth_cred_proc_ref(target_proc
);
133 if (!kauth_cred_issuser(my_cred
) && kauth_cred_getruid(my_cred
) &&
134 kauth_cred_getuid(my_cred
) != kauth_cred_getuid(target_cred
) &&
135 kauth_cred_getruid(my_cred
) != kauth_cred_getuid(target_cred
))
138 * Resoure starvation control can be used by unpriv resource owner but priv at the time of ownership claim. This is
139 * checked in low resource handle routine. So bypass the checks here.
141 if ((policy
!= PROC_POLICY_RESOURCE_STARVATION
) &&
142 (policy
!= PROC_POLICY_APPTYPE
) &&
143 (!kauth_cred_issuser(my_cred
) && curp
!= p
))
152 /* Lifecycle management will invoke approp macf checks */
153 if (policy
!= PROC_POLICY_APP_LIFECYCLE
) {
154 #endif /* CONFIG_EMBEDDED */
155 error
= mac_proc_check_sched(curp
, target_proc
);
160 #endif /* CONFIG_EMBEDDED */
161 #endif /* CONFIG_MACF */
165 case PROC_POLICY_BACKGROUND
:
166 error
= handle_background(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
168 case PROC_POLICY_HARDWARE_ACCESS
:
169 error
= handle_hwaccess(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
171 case PROC_POLICY_RESOURCE_STARVATION
:
172 error
= handle_lowresrouce(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
174 case PROC_POLICY_RESOURCE_USAGE
:
175 error
= handle_resourceuse(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
178 case PROC_POLICY_APP_LIFECYCLE
:
179 error
= handle_applifecycle(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
181 #endif /* CONFIG_EMBEDDED */
182 case PROC_POLICY_APPTYPE
:
183 error
= handle_apptype(scope
, action
, policy
, policy_subtype
, attrp
, target_proc
, target_threadid
);
191 proc_rele(target_proc
);
193 kauth_cred_unref(&target_cred
);
199 /* darwin background handling code */
201 handle_background(int scope
, int action
, __unused
int policy
, __unused
int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
)
203 int intval
, error
= 0;
207 case PROC_POLICY_ACTION_GET
:
208 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
209 intval
= proc_get_task_bg_policy(proc
->task
);
212 intval
= proc_get_thread_bg_policy(proc
->task
, target_threadid
);
214 error
= copyout((int *)&intval
, (user_addr_t
)attrp
, sizeof(int));
217 case PROC_POLICY_ACTION_SET
:
218 error
= copyin((user_addr_t
)attrp
, (int *)&intval
, sizeof(int));
221 if (intval
> PROC_POLICY_BG_ALL
) {
225 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
226 error
= proc_set_bgtaskpolicy(proc
->task
, intval
);
229 error
= proc_set_bgthreadpolicy(proc
->task
, target_threadid
, intval
);
233 case PROC_POLICY_ACTION_ADD
:
234 error
= copyin((user_addr_t
)attrp
, (int *)&intval
, sizeof(int));
237 if (intval
> PROC_POLICY_BG_ALL
) {
241 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
242 error
= proc_add_bgtaskpolicy(proc
->task
, intval
);
245 error
= proc_add_bgthreadpolicy(proc
->task
, target_threadid
, intval
);
249 case PROC_POLICY_ACTION_REMOVE
:
250 error
= copyin((user_addr_t
)attrp
, (int *)&intval
, sizeof(int));
253 if (intval
> PROC_POLICY_BG_ALL
) {
257 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
258 error
= proc_remove_bgtaskpolicy(proc
->task
, intval
);
261 error
= proc_remove_bgthreadpolicy(proc
->task
, target_threadid
, intval
);
265 case PROC_POLICY_ACTION_APPLY
:
266 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
267 error
= proc_apply_bgtaskpolicy(proc
->task
);
270 error
= proc_apply_bgthreadpolicy(proc
->task
, target_threadid
);
274 case PROC_POLICY_ACTION_RESTORE
:
275 if (scope
== PROC_POLICY_SCOPE_PROCESS
) {
276 error
= proc_restore_bgtaskpolicy(proc
->task
);
279 error
= proc_restore_bgthreadpolicy(proc
->task
, target_threadid
);
283 case PROC_POLICY_ACTION_DENYINHERIT
:
284 error
= proc_denyinherit_policy(proc
->task
);
287 case PROC_POLICY_ACTION_DENYSELFSET
:
288 error
= proc_denyselfset_policy(proc
->task
);
300 handle_hwaccess(__unused
int scope
, __unused
int action
, __unused
int policy
, int policy_subtype
, __unused user_addr_t attrp
, __unused proc_t proc
, __unused
uint64_t target_threadid
)
302 switch(policy_subtype
) {
303 case PROC_POLICY_HWACCESS_NONE
:
304 case PROC_POLICY_HWACCESS_DISK
:
305 case PROC_POLICY_HWACCESS_GPU
:
306 case PROC_POLICY_HWACCESS_NETWORK
:
307 case PROC_POLICY_HWACCESS_CPU
:
316 handle_lowresrouce(__unused
int scope
, int action
, __unused
int policy
, int policy_subtype
, __unused user_addr_t attrp
, proc_t proc
, __unused
uint64_t target_threadid
)
320 switch(policy_subtype
) {
321 case PROC_POLICY_RS_NONE
:
322 case PROC_POLICY_RS_VIRTUALMEM
:
328 if (action
== PROC_POLICY_ACTION_RESTORE
)
329 error
= proc_resetpcontrol(proc_pid(proc
));
338 handle_resourceuse(__unused
int scope
, __unused
int action
, __unused
int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, __unused
uint64_t target_threadid
)
340 proc_policy_cpuusage_attr_t cpuattr
;
343 switch(policy_subtype
) {
344 case PROC_POLICY_RUSAGE_NONE
:
345 case PROC_POLICY_RUSAGE_WIREDMEM
:
346 case PROC_POLICY_RUSAGE_VIRTMEM
:
347 case PROC_POLICY_RUSAGE_DISK
:
348 case PROC_POLICY_RUSAGE_NETWORK
:
349 case PROC_POLICY_RUSAGE_POWER
:
354 case PROC_POLICY_RUSAGE_CPU
:
359 case PROC_POLICY_ACTION_GET
:
360 error
= proc_get_task_ruse_cpu(proc
->task
, &cpuattr
.ppattr_cpu_attr
,
361 &cpuattr
.ppattr_cpu_percentage
,
362 &cpuattr
.ppattr_cpu_attr_interval
,
363 &cpuattr
.ppattr_cpu_attr_deadline
);
365 error
= copyout((proc_policy_cpuusage_attr_t
*)&cpuattr
, (user_addr_t
)attrp
, sizeof(proc_policy_cpuusage_attr_t
));
368 case PROC_POLICY_ACTION_APPLY
:
369 case PROC_POLICY_ACTION_SET
:
370 error
= copyin((user_addr_t
)attrp
, (proc_policy_cpuusage_attr_t
*)&cpuattr
, sizeof(proc_policy_cpuusage_attr_t
));
373 error
= proc_set_task_ruse_cpu(proc
->task
, cpuattr
.ppattr_cpu_attr
,
374 cpuattr
.ppattr_cpu_percentage
,
375 cpuattr
.ppattr_cpu_attr_interval
,
376 cpuattr
.ppattr_cpu_attr_deadline
);
380 case PROC_POLICY_ACTION_RESTORE
:
381 error
= proc_clear_task_ruse_cpu(proc
->task
);
395 handle_applifecycle(__unused
int scope
, int action
, __unused
int policy
, int policy_subtype
, user_addr_t attrp
, proc_t proc
, uint64_t target_threadid
)
399 int state
= 0, oldstate
= 0;
404 switch(policy_subtype
) {
405 case PROC_POLICY_APPLIFE_NONE
:
409 case PROC_POLICY_APPLIFE_STATE
:
411 error
= mac_proc_check_sched(current_proc(), proc
);
416 case PROC_POLICY_ACTION_GET
:
417 state
= proc_lf_getappstate(proc
->task
);
418 error
= copyout((int *)&state
, (user_addr_t
)attrp
, sizeof(int));
420 case PROC_POLICY_ACTION_APPLY
:
421 case PROC_POLICY_ACTION_SET
:
422 error
= copyin((user_addr_t
)attrp
, (int *)&state
, sizeof(int));
423 if ((error
== 0) && (state
!= TASK_APPSTATE_NONE
)) {
424 oldstate
= proc_lf_getappstate(proc
->task
);
425 error
= proc_lf_setappstate(proc
->task
, state
);
428 case TASK_APPSTATE_ACTIVE
:
429 noteval
= NOTE_APPACTIVE
;
431 case TASK_APPSTATE_BACKGROUND
:
432 noteval
= NOTE_APPBACKGROUND
;
434 case TASK_APPSTATE_NONUI
:
435 noteval
= NOTE_APPNONUI
;
437 case TASK_APPSTATE_INACTIVE
:
438 noteval
= NOTE_APPINACTIVE
;
443 proc_knote(proc
, noteval
);
455 case PROC_POLICY_APPLIFE_DEVSTATUS
:
457 /* ToDo - this should be a generic check, since we could potentially hang other behaviours here. */
458 error
= mac_proc_check_suspend_resume(current_proc(), MAC_PROC_CHECK_HIBERNATE
);
464 if (action
== PROC_POLICY_ACTION_APPLY
) {
465 /* Used as a freeze hint */
466 memorystatus_on_inactivity(-1);
468 /* in future use devicestatus for pid_socketshutdown() */
475 case PROC_POLICY_APPLIFE_PIDBIND
:
477 error
= mac_proc_check_suspend_resume(current_proc(), MAC_PROC_CHECK_PIDBIND
);
483 error
= copyin((user_addr_t
)attrp
, (int *)&state
, sizeof(int));
486 if (action
== PROC_POLICY_ACTION_APPLY
) {
487 /* bind the thread in target_thread in current process to target_proc */
488 error
= proc_lf_pidbind(current_task(), target_threadid
, proc
->task
, state
);
500 #endif /* CONFIG_EMBEDDED */
504 handle_apptype(__unused
int scope
, int action
, __unused
int policy
, int policy_subtype
, __unused user_addr_t attrp
, proc_t target_proc
, __unused
uint64_t target_threadid
)
508 switch(policy_subtype
) {
510 case PROC_POLICY_OSX_APPTYPE_TAL
:
511 /* need to be super user to do this */
512 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
517 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT
:
518 /* no special priv needed */
520 #endif /* !CONFIG_EMBEDDED */
521 case PROC_POLICY_OSX_APPTYPE_NONE
:
523 case PROC_POLICY_IOS_RESV1_APPTYPE
:
524 case PROC_POLICY_IOS_APPLE_DAEMON
:
525 case PROC_POLICY_IOS_APPTYPE
:
526 case PROC_POLICY_IOS_NONUITYPE
:
527 #endif /* CONFIG_EMBEDDED */
535 case PROC_POLICY_ACTION_ENABLE
:
536 /* reapply the app foreground/background policy */
537 error
= proc_enable_task_apptype(target_proc
->task
, policy_subtype
);
539 case PROC_POLICY_ACTION_DISABLE
:
540 /* remove the app foreground/background policy */
541 error
= proc_disable_task_apptype(target_proc
->task
, policy_subtype
);
550 #endif /* !CONFIG_EMBEDDED */
556 proc_apply_resource_actions(void * bsdinfo
, int type
, int action
)
558 proc_t p
= (proc_t
)bsdinfo
;
561 case PROC_POLICY_RSRCACT_THROTTLE
:
562 /* no need to do anything */
565 case PROC_POLICY_RSRCACT_SUSPEND
:
566 task_suspend(p
->task
);
569 case PROC_POLICY_RSRCACT_TERMINATE
:
573 case PROC_POLICY_RSRCACT_NOTIFY_KQ
:
575 proc_knote(p
, NOTE_RESOURCEEND
| (type
& 0xff));
579 case PROC_POLICY_RSRCACT_NOTIFY_EXC
:
580 panic("shouldn't be applying exception notification to process!");
589 proc_restore_resource_actions(void * bsdinfo
, __unused
int type
, int action
)
591 proc_t p
= (proc_t
)bsdinfo
;
594 case PROC_POLICY_RSRCACT_THROTTLE
:
595 case PROC_POLICY_RSRCACT_TERMINATE
:
596 case PROC_POLICY_RSRCACT_NOTIFY_KQ
:
597 case PROC_POLICY_RSRCACT_NOTIFY_EXC
:
598 /* no need to do anything */
601 case PROC_POLICY_RSRCACT_SUSPEND
:
602 task_resume(p
->task
);