]>
Commit | Line | Data |
---|---|---|
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> | |
316670eb A |
72 | #if CONFIG_EMBEDDED |
73 | #include <security/mac.h> | |
74 | #include <sys/kern_memorystatus.h> | |
75 | #endif /* CONFIG_EMBEDDED */ | |
6d2010ae A |
76 | |
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); | |
82 | ||
83 | extern kern_return_t task_suspend(task_t); | |
84 | extern kern_return_t task_resume(task_t); | |
85 | ||
316670eb A |
86 | #if CONFIG_EMBEDDED |
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 */ | |
89 | ||
90 | ||
6d2010ae A |
91 | /***************************** process_policy ********************/ |
92 | ||
93 | /* | |
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); } | |
99 | */ | |
100 | ||
101 | /* system call implementaion */ | |
102 | int | |
316670eb | 103 | process_policy(__unused struct proc *p, struct process_policy_args * uap, __unused int32_t *retval) |
6d2010ae A |
104 | { |
105 | int error = 0; | |
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; | |
316670eb | 113 | proc_t target_proc = PROC_NULL; |
6d2010ae A |
114 | proc_t curp = current_proc(); |
115 | kauth_cred_t my_cred; | |
116 | #if CONFIG_EMBEDDED | |
117 | kauth_cred_t target_cred; | |
118 | #endif | |
119 | ||
120 | if ((scope != PROC_POLICY_SCOPE_PROCESS) && (scope != PROC_POLICY_SCOPE_THREAD)) { | |
121 | return(EINVAL); | |
122 | } | |
316670eb A |
123 | target_proc = proc_find(target_pid); |
124 | if (target_proc == PROC_NULL) { | |
125 | return(ESRCH); | |
6d2010ae A |
126 | } |
127 | ||
316670eb | 128 | my_cred = kauth_cred_get(); |
6d2010ae A |
129 | |
130 | #if CONFIG_EMBEDDED | |
316670eb | 131 | target_cred = kauth_cred_proc_ref(target_proc); |
6d2010ae | 132 | |
316670eb | 133 | if (!kauth_cred_issuser(my_cred) && kauth_cred_getruid(my_cred) && |
6d2010ae A |
134 | kauth_cred_getuid(my_cred) != kauth_cred_getuid(target_cred) && |
135 | kauth_cred_getruid(my_cred) != kauth_cred_getuid(target_cred)) | |
136 | #else | |
137 | /* | |
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. | |
140 | */ | |
141 | if ((policy != PROC_POLICY_RESOURCE_STARVATION) && | |
142 | (policy != PROC_POLICY_APPTYPE) && | |
316670eb | 143 | (!kauth_cred_issuser(my_cred) && curp != p)) |
6d2010ae A |
144 | #endif |
145 | { | |
146 | error = EPERM; | |
147 | goto out; | |
148 | } | |
149 | ||
150 | #if CONFIG_MACF | |
316670eb A |
151 | #if CONFIG_EMBEDDED |
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); | |
156 | if (error) | |
157 | goto out; | |
158 | #if CONFIG_EMBEDDED | |
159 | } | |
160 | #endif /* CONFIG_EMBEDDED */ | |
161 | #endif /* CONFIG_MACF */ | |
6d2010ae A |
162 | |
163 | ||
164 | switch(policy) { | |
165 | case PROC_POLICY_BACKGROUND: | |
316670eb | 166 | error = handle_background(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); |
6d2010ae A |
167 | break; |
168 | case PROC_POLICY_HARDWARE_ACCESS: | |
316670eb | 169 | error = handle_hwaccess(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); |
6d2010ae A |
170 | break; |
171 | case PROC_POLICY_RESOURCE_STARVATION: | |
316670eb | 172 | error = handle_lowresrouce(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); |
6d2010ae A |
173 | break; |
174 | case PROC_POLICY_RESOURCE_USAGE: | |
316670eb A |
175 | error = handle_resourceuse(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); |
176 | break; | |
177 | #if CONFIG_EMBEDDED | |
178 | case PROC_POLICY_APP_LIFECYCLE: | |
179 | error = handle_applifecycle(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); | |
6d2010ae | 180 | break; |
316670eb | 181 | #endif /* CONFIG_EMBEDDED */ |
6d2010ae | 182 | case PROC_POLICY_APPTYPE: |
316670eb | 183 | error = handle_apptype(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid); |
6d2010ae A |
184 | break; |
185 | default: | |
186 | error = EINVAL; | |
187 | break; | |
188 | } | |
189 | ||
190 | out: | |
316670eb | 191 | proc_rele(target_proc); |
6d2010ae A |
192 | #if CONFIG_EMBEDDED |
193 | kauth_cred_unref(&target_cred); | |
194 | #endif | |
195 | return(error); | |
196 | } | |
197 | ||
198 | ||
199 | /* darwin background handling code */ | |
200 | static int | |
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) | |
202 | { | |
203 | int intval, error = 0; | |
204 | ||
205 | ||
206 | switch (action) { | |
207 | case PROC_POLICY_ACTION_GET: | |
208 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
209 | intval = proc_get_task_bg_policy(proc->task); | |
210 | } else { | |
211 | /* thread scope */ | |
212 | intval = proc_get_thread_bg_policy(proc->task, target_threadid); | |
213 | } | |
214 | error = copyout((int *)&intval, (user_addr_t)attrp, sizeof(int)); | |
215 | break; | |
216 | ||
217 | case PROC_POLICY_ACTION_SET: | |
218 | error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int)); | |
219 | if (error != 0) | |
220 | goto out; | |
221 | if (intval > PROC_POLICY_BG_ALL) { | |
222 | error = EINVAL; | |
223 | goto out; | |
224 | } | |
225 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
226 | error = proc_set_bgtaskpolicy(proc->task, intval); | |
227 | } else { | |
228 | /* thread scope */ | |
229 | error = proc_set_bgthreadpolicy(proc->task, target_threadid, intval); | |
230 | } | |
231 | break; | |
232 | ||
233 | case PROC_POLICY_ACTION_ADD: | |
234 | error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int)); | |
235 | if (error != 0) | |
236 | goto out; | |
237 | if (intval > PROC_POLICY_BG_ALL) { | |
238 | error = EINVAL; | |
239 | goto out; | |
240 | } | |
241 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
242 | error = proc_add_bgtaskpolicy(proc->task, intval); | |
243 | } else { | |
244 | /* thread scope */ | |
245 | error = proc_add_bgthreadpolicy(proc->task, target_threadid, intval); | |
246 | } | |
247 | break; | |
248 | ||
249 | case PROC_POLICY_ACTION_REMOVE: | |
250 | error = copyin((user_addr_t)attrp, (int *)&intval, sizeof(int)); | |
251 | if (error != 0) | |
252 | goto out; | |
253 | if (intval > PROC_POLICY_BG_ALL) { | |
254 | error = EINVAL; | |
255 | goto out; | |
256 | } | |
257 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
258 | error = proc_remove_bgtaskpolicy(proc->task, intval); | |
259 | } else { | |
260 | /* thread scope */ | |
261 | error = proc_remove_bgthreadpolicy(proc->task, target_threadid, intval); | |
262 | } | |
263 | break; | |
264 | ||
265 | case PROC_POLICY_ACTION_APPLY: | |
266 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
267 | error = proc_apply_bgtaskpolicy(proc->task); | |
268 | } else { | |
269 | /* thread scope */ | |
270 | error = proc_apply_bgthreadpolicy(proc->task, target_threadid); | |
271 | } | |
272 | break; | |
273 | ||
274 | case PROC_POLICY_ACTION_RESTORE: | |
275 | if (scope == PROC_POLICY_SCOPE_PROCESS) { | |
276 | error = proc_restore_bgtaskpolicy(proc->task); | |
277 | } else { | |
278 | /* thread scope */ | |
279 | error = proc_restore_bgthreadpolicy(proc->task, target_threadid); | |
280 | } | |
281 | break; | |
282 | ||
283 | case PROC_POLICY_ACTION_DENYINHERIT: | |
284 | error = proc_denyinherit_policy(proc->task); | |
285 | break; | |
286 | ||
287 | case PROC_POLICY_ACTION_DENYSELFSET: | |
288 | error = proc_denyselfset_policy(proc->task); | |
289 | break; | |
290 | ||
291 | default: | |
292 | return(EINVAL); | |
293 | } | |
294 | ||
295 | out: | |
296 | return(error); | |
297 | } | |
298 | ||
299 | static int | |
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) | |
301 | { | |
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: | |
308 | break; | |
309 | default: | |
310 | return(EINVAL); | |
311 | } | |
312 | return(0); | |
313 | } | |
314 | ||
315 | static int | |
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) | |
317 | { | |
318 | int error = 0; | |
319 | ||
320 | switch(policy_subtype) { | |
321 | case PROC_POLICY_RS_NONE: | |
322 | case PROC_POLICY_RS_VIRTUALMEM: | |
323 | break; | |
324 | default: | |
325 | return(EINVAL); | |
326 | } | |
327 | ||
328 | if (action == PROC_POLICY_ACTION_RESTORE) | |
329 | error = proc_resetpcontrol(proc_pid(proc)); | |
330 | else | |
331 | error = EINVAL; | |
332 | ||
333 | return(error); | |
334 | } | |
335 | ||
336 | ||
337 | static int | |
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) | |
339 | { | |
340 | proc_policy_cpuusage_attr_t cpuattr; | |
341 | int error = 0; | |
342 | ||
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: | |
350 | return(ENOTSUP); | |
351 | break; | |
352 | default: | |
353 | return(EINVAL); | |
354 | case PROC_POLICY_RUSAGE_CPU: | |
355 | break; | |
356 | } | |
357 | ||
358 | switch (action) { | |
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); | |
364 | if (error == 0) | |
365 | error = copyout((proc_policy_cpuusage_attr_t *)&cpuattr, (user_addr_t)attrp, sizeof(proc_policy_cpuusage_attr_t)); | |
366 | break; | |
367 | ||
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)); | |
371 | ||
372 | if (error == 0) { | |
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); | |
377 | } | |
316670eb A |
378 | break; |
379 | ||
380 | case PROC_POLICY_ACTION_RESTORE: | |
381 | error = proc_clear_task_ruse_cpu(proc->task); | |
382 | break; | |
383 | ||
6d2010ae A |
384 | default: |
385 | error = EINVAL; | |
386 | break; | |
387 | ||
388 | } | |
389 | ||
390 | return(error); | |
391 | } | |
392 | ||
316670eb A |
393 | #if CONFIG_EMBEDDED |
394 | static int | |
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) | |
396 | { | |
397 | ||
398 | int error = 0; | |
399 | int state = 0, oldstate = 0; | |
400 | int noteval = 0; | |
401 | ||
402 | ||
403 | ||
404 | switch(policy_subtype) { | |
405 | case PROC_POLICY_APPLIFE_NONE: | |
406 | error = 0; | |
407 | break; | |
408 | ||
409 | case PROC_POLICY_APPLIFE_STATE: | |
410 | #if CONFIG_MACF | |
411 | error = mac_proc_check_sched(current_proc(), proc); | |
412 | if (error) | |
413 | goto out; | |
414 | #endif | |
415 | switch (action) { | |
416 | case PROC_POLICY_ACTION_GET : | |
417 | state = proc_lf_getappstate(proc->task); | |
418 | error = copyout((int *)&state, (user_addr_t)attrp, sizeof(int)); | |
419 | break; | |
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); | |
426 | if (error == 0) { | |
427 | switch (state) { | |
428 | case TASK_APPSTATE_ACTIVE: | |
429 | noteval = NOTE_APPACTIVE; | |
430 | break; | |
431 | case TASK_APPSTATE_BACKGROUND: | |
432 | noteval = NOTE_APPBACKGROUND; | |
433 | break; | |
434 | case TASK_APPSTATE_NONUI: | |
435 | noteval = NOTE_APPNONUI; | |
436 | break; | |
437 | case TASK_APPSTATE_INACTIVE: | |
438 | noteval = NOTE_APPINACTIVE; | |
439 | break; | |
440 | } | |
441 | ||
442 | proc_lock(proc); | |
443 | proc_knote(proc, noteval); | |
444 | proc_unlock(proc); | |
445 | } | |
446 | } | |
447 | break; | |
448 | ||
449 | default: | |
450 | error = EINVAL; | |
451 | break; | |
452 | } | |
453 | break; | |
454 | ||
455 | case PROC_POLICY_APPLIFE_DEVSTATUS: | |
456 | #if CONFIG_MACF | |
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); | |
459 | if (error) { | |
460 | error = EPERM; | |
461 | goto out; | |
462 | } | |
463 | #endif | |
464 | if (action == PROC_POLICY_ACTION_APPLY) { | |
465 | /* Used as a freeze hint */ | |
466 | memorystatus_on_inactivity(-1); | |
467 | ||
468 | /* in future use devicestatus for pid_socketshutdown() */ | |
469 | error = 0; | |
470 | } else { | |
471 | error = EINVAL; | |
472 | } | |
473 | break; | |
474 | ||
475 | case PROC_POLICY_APPLIFE_PIDBIND: | |
476 | #if CONFIG_MACF | |
477 | error = mac_proc_check_suspend_resume(current_proc(), MAC_PROC_CHECK_PIDBIND); | |
478 | if (error) { | |
479 | error = EPERM; | |
480 | goto out; | |
481 | } | |
482 | #endif | |
483 | error = copyin((user_addr_t)attrp, (int *)&state, sizeof(int)); | |
484 | if (error != 0) | |
485 | goto out; | |
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); | |
489 | } else | |
490 | error = EINVAL; | |
491 | break; | |
492 | default: | |
493 | error = EINVAL; | |
494 | break; | |
495 | } | |
496 | ||
497 | out: | |
498 | return(error); | |
499 | } | |
500 | #endif /* CONFIG_EMBEDDED */ | |
501 | ||
6d2010ae A |
502 | |
503 | static int | |
316670eb | 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) |
6d2010ae A |
505 | { |
506 | int error = 0; | |
507 | ||
508 | switch(policy_subtype) { | |
316670eb | 509 | #if !CONFIG_EMBEDDED |
6d2010ae A |
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) { | |
513 | error = EPERM; | |
514 | goto out; | |
515 | } | |
516 | break; | |
517 | case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: | |
518 | /* no special priv needed */ | |
519 | break; | |
316670eb | 520 | #endif /* !CONFIG_EMBEDDED */ |
6d2010ae | 521 | case PROC_POLICY_OSX_APPTYPE_NONE: |
316670eb A |
522 | #if CONFIG_EMBEDDED |
523 | case PROC_POLICY_IOS_RESV1_APPTYPE: | |
524 | case PROC_POLICY_IOS_APPLE_DAEMON: | |
6d2010ae A |
525 | case PROC_POLICY_IOS_APPTYPE: |
526 | case PROC_POLICY_IOS_NONUITYPE: | |
316670eb | 527 | #endif /* CONFIG_EMBEDDED */ |
6d2010ae A |
528 | return(ENOTSUP); |
529 | break; | |
530 | default: | |
531 | return(EINVAL); | |
532 | } | |
533 | ||
534 | switch (action) { | |
535 | case PROC_POLICY_ACTION_ENABLE: | |
536 | /* reapply the app foreground/background policy */ | |
316670eb | 537 | error = proc_enable_task_apptype(target_proc->task, policy_subtype); |
6d2010ae A |
538 | break; |
539 | case PROC_POLICY_ACTION_DISABLE: | |
540 | /* remove the app foreground/background policy */ | |
316670eb | 541 | error = proc_disable_task_apptype(target_proc->task, policy_subtype); |
6d2010ae A |
542 | break; |
543 | default: | |
544 | error = EINVAL; | |
545 | break; | |
546 | } | |
547 | ||
316670eb | 548 | #if !CONFIG_EMBEDDED |
6d2010ae | 549 | out: |
316670eb | 550 | #endif /* !CONFIG_EMBEDDED */ |
6d2010ae A |
551 | return(error); |
552 | } | |
553 | ||
316670eb | 554 | |
6d2010ae A |
555 | int |
556 | proc_apply_resource_actions(void * bsdinfo, int type, int action) | |
557 | { | |
558 | proc_t p = (proc_t)bsdinfo; | |
559 | ||
560 | switch(action) { | |
561 | case PROC_POLICY_RSRCACT_THROTTLE: | |
562 | /* no need to do anything */ | |
563 | break; | |
564 | ||
565 | case PROC_POLICY_RSRCACT_SUSPEND: | |
566 | task_suspend(p->task); | |
567 | break; | |
568 | ||
569 | case PROC_POLICY_RSRCACT_TERMINATE: | |
570 | psignal(p, SIGKILL); | |
571 | break; | |
572 | ||
316670eb | 573 | case PROC_POLICY_RSRCACT_NOTIFY_KQ: |
6d2010ae A |
574 | proc_lock(p); |
575 | proc_knote(p, NOTE_RESOURCEEND | (type & 0xff)); | |
576 | proc_unlock(p); | |
577 | break; | |
316670eb A |
578 | |
579 | case PROC_POLICY_RSRCACT_NOTIFY_EXC: | |
580 | panic("shouldn't be applying exception notification to process!"); | |
581 | break; | |
6d2010ae A |
582 | } |
583 | ||
584 | return(0); | |
585 | } | |
586 | ||
587 | ||
588 | int | |
589 | proc_restore_resource_actions(void * bsdinfo, __unused int type, int action) | |
590 | { | |
591 | proc_t p = (proc_t)bsdinfo; | |
592 | ||
593 | switch(action) { | |
594 | case PROC_POLICY_RSRCACT_THROTTLE: | |
595 | case PROC_POLICY_RSRCACT_TERMINATE: | |
316670eb A |
596 | case PROC_POLICY_RSRCACT_NOTIFY_KQ: |
597 | case PROC_POLICY_RSRCACT_NOTIFY_EXC: | |
6d2010ae A |
598 | /* no need to do anything */ |
599 | break; | |
600 | ||
601 | case PROC_POLICY_RSRCACT_SUSPEND: | |
602 | task_resume(p->task); | |
603 | break; | |
604 | ||
605 | } | |
606 | ||
607 | return(0); | |
608 | } | |
609 |