]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/process_policy.c
xnu-1699.24.8.tar.gz
[apple/xnu.git] / bsd / kern / process_policy.c
CommitLineData
6d2010ae
A
1/*
2 * Copyright (c) 2005, 2010 Apple Computer, 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
29/*
30 * process policy syscall implementation
31 */
32
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>
40#include <sys/buf.h>
41#include <sys/ioctl.h>
42#include <sys/vm.h>
43#include <sys/user.h>
44
45#include <security/audit/audit.h>
46
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>
60
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>
67
68#include <machine/machine_routines.h>
69
70#include <kern/ipc_misc.h>
71#include <vm/vm_protos.h>
72
73static int handle_background(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
74static int handle_hwaccess(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
75static int handle_lowresrouce(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
76static int handle_resourceuse(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
77static int handle_apptype(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
78
79extern kern_return_t task_suspend(task_t);
80extern kern_return_t task_resume(task_t);
81
82/***************************** process_policy ********************/
83
84/*
85 *int process_policy(int scope, int action, int policy, int policy_subtype,
86 * proc_policy_attribute_t * attrp, pid_t target_pid,
87 * uint64_t target_threadid)
88 *{ int process_policy(int scope, int action, int policy, int policy_subtype,
89 * user_addr_t attrp, pid_t target_pid, uint64_t target_threadid); }
90 */
91
92/* system call implementaion */
93int
94process_policy(struct proc *p, struct process_policy_args * uap, __unused int32_t *retval)
95{
96 int error = 0;
97 int scope = uap->scope;
98 int policy = uap->policy;
99 int action = uap->action;
100 int policy_subtype = uap->policy_subtype;
101 user_addr_t attrp = uap->attrp;
102 pid_t target_pid = uap->target_pid;
103 uint64_t target_threadid = uap->target_threadid;
104 proc_t proc = PROC_NULL;
105 proc_t curp = current_proc();
106 kauth_cred_t my_cred;
107#if CONFIG_EMBEDDED
108 kauth_cred_t target_cred;
109#endif
110
111 if ((scope != PROC_POLICY_SCOPE_PROCESS) && (scope != PROC_POLICY_SCOPE_THREAD)) {
112 return(EINVAL);
113 }
114 proc = proc_find(target_pid);
115 if (proc == PROC_NULL) {
116 return(EINVAL);
117 }
118
119 my_cred = kauth_cred_proc_ref(curp);
120
121#if CONFIG_EMBEDDED
122 target_cred = kauth_cred_proc_ref(proc);
123
124 if (suser(my_cred, NULL) && kauth_cred_getruid(my_cred) &&
125 kauth_cred_getuid(my_cred) != kauth_cred_getuid(target_cred) &&
126 kauth_cred_getruid(my_cred) != kauth_cred_getuid(target_cred))
127#else
128 /*
129 * Resoure starvation control can be used by unpriv resource owner but priv at the time of ownership claim. This is
130 * checked in low resource handle routine. So bypass the checks here.
131 */
132 if ((policy != PROC_POLICY_RESOURCE_STARVATION) &&
133 (policy != PROC_POLICY_APPTYPE) &&
134 (suser(my_cred, NULL) && curp != p))
135#endif
136 {
137 error = EPERM;
138 goto out;
139 }
140
141#if CONFIG_MACF
142 error = mac_proc_check_sched(curp, p);
143 if (error)
144 goto out;
145#endif
146
147
148 switch(policy) {
149 case PROC_POLICY_BACKGROUND:
150 error = handle_background(scope, action, policy, policy_subtype, attrp, proc, target_threadid);
151 break;
152 case PROC_POLICY_HARDWARE_ACCESS:
153 error = handle_hwaccess(scope, action, policy, policy_subtype, attrp, proc, target_threadid);
154 break;
155 case PROC_POLICY_RESOURCE_STARVATION:
156 error = handle_lowresrouce(scope, action, policy, policy_subtype, attrp, proc, target_threadid);
157 break;
158 case PROC_POLICY_RESOURCE_USAGE:
159 error = handle_resourceuse(scope, action, policy, policy_subtype, attrp, proc, target_threadid);
160 break;
161 case PROC_POLICY_APPTYPE:
162 error = handle_apptype(scope, action, policy, policy_subtype, attrp, proc, target_threadid);
163 break;
164 default:
165 error = EINVAL;
166 break;
167 }
168
169out:
170 proc_rele(proc);
171 kauth_cred_unref(&my_cred);
172#if CONFIG_EMBEDDED
173 kauth_cred_unref(&target_cred);
174#endif
175 return(error);
176}
177
178
179/* darwin background handling code */
180static int
181handle_background(int scope, int action, __unused int policy, __unused int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid)
182{
183 int intval, error = 0;
184
185
186 switch (action) {
187 case PROC_POLICY_ACTION_GET:
188 if (scope == PROC_POLICY_SCOPE_PROCESS) {
189 intval = proc_get_task_bg_policy(proc->task);
190 } else {
191 /* thread scope */
192 intval = proc_get_thread_bg_policy(proc->task, target_threadid);
193 }
194 error = copyout((int *)&intval, (user_addr_t)attrp, sizeof(int));
195 break;
196
197 case PROC_POLICY_ACTION_SET:
198 error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int));
199 if (error != 0)
200 goto out;
201 if (intval > PROC_POLICY_BG_ALL) {
202 error = EINVAL;
203 goto out;
204 }
205 if (scope == PROC_POLICY_SCOPE_PROCESS) {
206 error = proc_set_bgtaskpolicy(proc->task, intval);
207 } else {
208 /* thread scope */
209 error = proc_set_bgthreadpolicy(proc->task, target_threadid, intval);
210 }
211 break;
212
213 case PROC_POLICY_ACTION_ADD:
214 error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int));
215 if (error != 0)
216 goto out;
217 if (intval > PROC_POLICY_BG_ALL) {
218 error = EINVAL;
219 goto out;
220 }
221 if (scope == PROC_POLICY_SCOPE_PROCESS) {
222 error = proc_add_bgtaskpolicy(proc->task, intval);
223 } else {
224 /* thread scope */
225 error = proc_add_bgthreadpolicy(proc->task, target_threadid, intval);
226 }
227 break;
228
229 case PROC_POLICY_ACTION_REMOVE:
230 error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int));
231 if (error != 0)
232 goto out;
233 if (intval > PROC_POLICY_BG_ALL) {
234 error = EINVAL;
235 goto out;
236 }
237 if (scope == PROC_POLICY_SCOPE_PROCESS) {
238 error = proc_remove_bgtaskpolicy(proc->task, intval);
239 } else {
240 /* thread scope */
241 error = proc_remove_bgthreadpolicy(proc->task, target_threadid, intval);
242 }
243 break;
244
245 case PROC_POLICY_ACTION_APPLY:
246 if (scope == PROC_POLICY_SCOPE_PROCESS) {
247 error = proc_apply_bgtaskpolicy(proc->task);
248 } else {
249 /* thread scope */
250 error = proc_apply_bgthreadpolicy(proc->task, target_threadid);
251 }
252 break;
253
254 case PROC_POLICY_ACTION_RESTORE:
255 if (scope == PROC_POLICY_SCOPE_PROCESS) {
256 error = proc_restore_bgtaskpolicy(proc->task);
257 } else {
258 /* thread scope */
259 error = proc_restore_bgthreadpolicy(proc->task, target_threadid);
260 }
261 break;
262
263 case PROC_POLICY_ACTION_DENYINHERIT:
264 error = proc_denyinherit_policy(proc->task);
265 break;
266
267 case PROC_POLICY_ACTION_DENYSELFSET:
268 error = proc_denyselfset_policy(proc->task);
269 break;
270
271 default:
272 return(EINVAL);
273 }
274
275out:
276 return(error);
277}
278
279static int
280handle_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)
281{
282 switch(policy_subtype) {
283 case PROC_POLICY_HWACCESS_NONE:
284 case PROC_POLICY_HWACCESS_DISK:
285 case PROC_POLICY_HWACCESS_GPU:
286 case PROC_POLICY_HWACCESS_NETWORK:
287 case PROC_POLICY_HWACCESS_CPU:
288 break;
289 default:
290 return(EINVAL);
291 }
292 return(0);
293}
294
295static int
296handle_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)
297{
298 int error = 0;
299
300 switch(policy_subtype) {
301 case PROC_POLICY_RS_NONE:
302 case PROC_POLICY_RS_VIRTUALMEM:
303 break;
304 default:
305 return(EINVAL);
306 }
307
308 if (action == PROC_POLICY_ACTION_RESTORE)
309 error = proc_resetpcontrol(proc_pid(proc));
310 else
311 error = EINVAL;
312
313 return(error);
314}
315
316
317static int
318handle_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)
319{
320 proc_policy_cpuusage_attr_t cpuattr;
321 int error = 0;
322
323 switch(policy_subtype) {
324 case PROC_POLICY_RUSAGE_NONE:
325 case PROC_POLICY_RUSAGE_WIREDMEM:
326 case PROC_POLICY_RUSAGE_VIRTMEM:
327 case PROC_POLICY_RUSAGE_DISK:
328 case PROC_POLICY_RUSAGE_NETWORK:
329 case PROC_POLICY_RUSAGE_POWER:
330 return(ENOTSUP);
331 break;
332 default:
333 return(EINVAL);
334 case PROC_POLICY_RUSAGE_CPU:
335 break;
336 }
337
338 switch (action) {
339 case PROC_POLICY_ACTION_GET:
340 error = proc_get_task_ruse_cpu(proc->task, &cpuattr.ppattr_cpu_attr,
341 &cpuattr.ppattr_cpu_percentage,
342 &cpuattr.ppattr_cpu_attr_interval,
343 &cpuattr.ppattr_cpu_attr_deadline);
344 if (error == 0)
345 error = copyout((proc_policy_cpuusage_attr_t *)&cpuattr, (user_addr_t)attrp, sizeof(proc_policy_cpuusage_attr_t));
346 break;
347
348 case PROC_POLICY_ACTION_APPLY:
349 case PROC_POLICY_ACTION_SET:
350 error = copyin((user_addr_t)attrp, (proc_policy_cpuusage_attr_t *)&cpuattr, sizeof(proc_policy_cpuusage_attr_t));
351
352 if (error == 0) {
353 error = proc_set_task_ruse_cpu(proc->task, cpuattr.ppattr_cpu_attr,
354 cpuattr.ppattr_cpu_percentage,
355 cpuattr.ppattr_cpu_attr_interval,
356 cpuattr.ppattr_cpu_attr_deadline);
357 }
358 default:
359 error = EINVAL;
360 break;
361
362 }
363
364 return(error);
365}
366
367
368static int
369handle_apptype(__unused int scope, int action, __unused int policy, int policy_subtype, __unused user_addr_t attrp, proc_t proc, __unused uint64_t target_threadid)
370{
371 int error = 0;
372
373 switch(policy_subtype) {
374 case PROC_POLICY_OSX_APPTYPE_TAL:
375 /* need to be super user to do this */
376 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
377 error = EPERM;
378 goto out;
379 }
380 break;
381 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
382 /* no special priv needed */
383 break;
384 case PROC_POLICY_OSX_APPTYPE_NONE:
385 case PROC_POLICY_IOS_APPTYPE:
386 case PROC_POLICY_IOS_NONUITYPE:
387 return(ENOTSUP);
388 break;
389 default:
390 return(EINVAL);
391 }
392
393 switch (action) {
394 case PROC_POLICY_ACTION_ENABLE:
395 /* reapply the app foreground/background policy */
396 error = proc_enable_task_apptype(proc->task, policy_subtype);
397 break;
398 case PROC_POLICY_ACTION_DISABLE:
399 /* remove the app foreground/background policy */
400 error = proc_disable_task_apptype(proc->task, policy_subtype);
401 break;
402 default:
403 error = EINVAL;
404 break;
405 }
406
407out:
408 return(error);
409}
410
411int
412proc_apply_resource_actions(void * bsdinfo, int type, int action)
413{
414 proc_t p = (proc_t)bsdinfo;
415
416 switch(action) {
417 case PROC_POLICY_RSRCACT_THROTTLE:
418 /* no need to do anything */
419 break;
420
421 case PROC_POLICY_RSRCACT_SUSPEND:
422 task_suspend(p->task);
423 break;
424
425 case PROC_POLICY_RSRCACT_TERMINATE:
426 psignal(p, SIGKILL);
427 break;
428
429 case PROC_POLICY_RSRCACT_NOTIFY:
430 proc_lock(p);
431 proc_knote(p, NOTE_RESOURCEEND | (type & 0xff));
432 proc_unlock(p);
433 break;
434 }
435
436 return(0);
437}
438
439
440int
441proc_restore_resource_actions(void * bsdinfo, __unused int type, int action)
442{
443 proc_t p = (proc_t)bsdinfo;
444
445 switch(action) {
446 case PROC_POLICY_RSRCACT_THROTTLE:
447 case PROC_POLICY_RSRCACT_TERMINATE:
448 case PROC_POLICY_RSRCACT_NOTIFY:
449 /* no need to do anything */
450 break;
451
452 case PROC_POLICY_RSRCACT_SUSPEND:
453 task_resume(p->task);
454 break;
455
456 }
457
458 return(0);
459}
460