]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/process_policy.c
xnu-3789.60.24.tar.gz
[apple/xnu.git] / bsd / kern / process_policy.c
index 9ae4b32bcd2dca057bcdf5bde6a9b8ab0cd678c5..bcf69d7c8f589015827f5b4e30b4f6f5398b7da8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2016 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <mach/mach_types.h>
 #include <mach/vm_param.h>
 #include <kern/task.h>
-#include <kern/lock.h>
 #include <kern/kalloc.h>
 #include <kern/assert.h>
+#include <kern/policy_internal.h>
+
 #include <vm/vm_kern.h>
 #include <vm/vm_map.h>
 #include <mach/host_info.h>
@@ -72,7 +73,7 @@
 #include <vm/vm_protos.h>
 
 static int handle_lowresource(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
-static int handle_resourceuse(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
+static int handle_cpuuse(int action, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
 static int handle_apptype(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
 static int handle_boost(int scope, int action, int policy, int policy_subtype, user_addr_t attrp, proc_t proc, uint64_t target_threadid);
 
@@ -156,7 +157,23 @@ process_policy(__unused struct proc *p, struct process_policy_args * uap, __unus
                        error = handle_lowresource(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid);
                        break;
                case PROC_POLICY_RESOURCE_USAGE:
-                       error = handle_resourceuse(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid);
+                       switch(policy_subtype) {
+                               case PROC_POLICY_RUSAGE_NONE:
+                               case PROC_POLICY_RUSAGE_WIREDMEM:
+                               case PROC_POLICY_RUSAGE_VIRTMEM:
+                               case PROC_POLICY_RUSAGE_DISK:
+                               case PROC_POLICY_RUSAGE_NETWORK:
+                               case PROC_POLICY_RUSAGE_POWER:
+                                       error = ENOTSUP;
+                                       goto out;
+                               default:
+                                       error = EINVAL;
+                                       goto out;
+                               case PROC_POLICY_RUSAGE_CPU:
+                                       break;
+                       }
+
+                       error = handle_cpuuse(action, attrp, target_proc, target_threadid);
                        break;
                case PROC_POLICY_APPTYPE:
                        error = handle_apptype(scope, action, policy, policy_subtype, attrp, target_proc, target_threadid);
@@ -197,49 +214,44 @@ handle_lowresource(__unused int scope, int action, __unused int policy, int poli
 
 
 static int 
-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)
+handle_cpuuse(int action, user_addr_t attrp, proc_t proc, __unused uint64_t target_threadid)
 {
        proc_policy_cpuusage_attr_t     cpuattr;
 #if CONFIG_MACF
        proc_t                          curp = current_proc();
 #endif
-       int                             entitled = TRUE;
+       int                             entitled = FALSE;
+       Boolean                         canEnable = FALSE;
        uint64_t                        interval = -1ULL;       
        int                             error = 0;
-
-       switch(policy_subtype) {
-               case PROC_POLICY_RUSAGE_NONE:
-               case PROC_POLICY_RUSAGE_WIREDMEM:
-               case PROC_POLICY_RUSAGE_VIRTMEM:
-               case PROC_POLICY_RUSAGE_DISK:
-               case PROC_POLICY_RUSAGE_NETWORK:
-               case PROC_POLICY_RUSAGE_POWER:
-                       return(ENOTSUP);
-                       break;
-               default:
-                       return(EINVAL); 
-               case PROC_POLICY_RUSAGE_CPU:
-                       break;
-       }
+       uint8_t                         percentage;
 
 #if CONFIG_MACF
-       if (curp != proc) {
-               /* the cpumon entitlement manages messing with CPU limits on self */
-               error = mac_proc_check_sched(curp, proc);
-               if (error)
-                       return error;
-       }
-
        /*
-        * Allow a process to change CPU usage monitor parameters, unless a MAC policy
-        * overrides it with an entitlement check.
+        * iOS only allows processes to override their own CPU usage monitor
+        * parameters if they have com.apple.private.kernel.override-cpumon.
+        *
+        * Until rdar://24799462 improves our scheme, we are also using the
+        * same entitlement to indicate which processes can resume monitoring
+        * when they otherwise wouldn't be able to.
         */
        entitled = (mac_proc_check_cpumon(curp) == 0) ? TRUE : FALSE;
+       canEnable = (entitled && action == PROC_POLICY_ACTION_ENABLE);
+
+       if (!canEnable && curp != proc) {
+               /* can the current process change scheduling parameters? */
+               error = mac_proc_check_sched(curp, proc);
+               if (error)      return error;
+       }
 #endif
 
-       switch (action) {
-               uint8_t percentage;
+       // on macOS tasks can only set and clear their own CPU limits
+       if ((action == PROC_POLICY_ACTION_APPLY || action == PROC_POLICY_ACTION_RESTORE)
+            && proc != current_proc()) {
+               return (EPERM);
+       }
 
+       switch (action) {
                case PROC_POLICY_ACTION_GET: 
                        error = proc_get_task_ruse_cpu(proc->task, &cpuattr.ppattr_cpu_attr,
                                         &percentage,
@@ -277,10 +289,18 @@ handle_resourceuse(__unused int scope, __unused int action, __unused int policy,
                                        entitled); 
                        break;
 
+               /* restore process to prior state */
                case PROC_POLICY_ACTION_RESTORE:
                        error = proc_clear_task_ruse_cpu(proc->task, entitled);
                        break;
 
+               /* re-enable suspended monitor */
+               case PROC_POLICY_ACTION_ENABLE:
+                       error = task_resume_cpumon(proc->task);
+                       break;
+
+               case PROC_POLICY_ACTION_REMOVE:
+
                default:
                        error = EINVAL;
                        break;
@@ -325,7 +345,7 @@ handle_apptype(         int scope,
                                return (EINVAL);
 
                        /* PROCESS ENABLE APPTYPE HOLDIMP */
-                       error = task_importance_hold_external_assertion(current_task(), 1);
+                       error = task_importance_hold_legacy_external_assertion(current_task(), 1);
 
                        return(error);
 
@@ -336,7 +356,7 @@ handle_apptype(         int scope,
                                return (EINVAL);
 
                        /* PROCESS ENABLE APPTYPE DROPIMP */
-                       error = task_importance_drop_external_assertion(current_task(), 1);
+                       error = task_importance_drop_legacy_external_assertion(current_task(), 1);
 
                        return(error);
 
@@ -358,19 +378,18 @@ handle_apptype(         int scope,
        switch (action) {
                case PROC_POLICY_ACTION_ENABLE:
                        /* PROCESS ENABLE APPTYPE TAL */
-                       proc_set_task_policy(target_proc->task, THREAD_NULL,
-                                             TASK_POLICY_ATTRIBUTE, TASK_POLICY_TAL,
-                                             TASK_POLICY_ENABLE);
+                       proc_set_task_policy(target_proc->task,
+                                            TASK_POLICY_ATTRIBUTE, TASK_POLICY_TAL,
+                                            TASK_POLICY_ENABLE);
                        break;
                case PROC_POLICY_ACTION_DISABLE:
                        /* PROCESS DISABLE APPTYPE TAL */
-                       proc_set_task_policy(target_proc->task, THREAD_NULL,
-                                             TASK_POLICY_ATTRIBUTE, TASK_POLICY_TAL,
-                                             TASK_POLICY_DISABLE);
+                       proc_set_task_policy(target_proc->task,
+                                            TASK_POLICY_ATTRIBUTE, TASK_POLICY_TAL,
+                                            TASK_POLICY_DISABLE);
                        break;
                default:
                        return (EINVAL);
-                       break;
        }
 
        return(0);
@@ -397,17 +416,17 @@ handle_boost(int scope,
 
        switch(policy_subtype) {
                case PROC_POLICY_IMP_IMPORTANT:
-                       if (task_is_importance_receiver(target_proc->task) == FALSE)
+                       if (task_is_importance_receiver_type(target_proc->task) == FALSE)
                                return (EINVAL);
 
                        switch (action) {
                                case PROC_POLICY_ACTION_HOLD:
                                        /* PROCESS HOLD BOOST IMPORTANT */
-                                       error = task_importance_hold_external_assertion(current_task(), 1);
+                                       error = task_importance_hold_legacy_external_assertion(current_task(), 1);
                                        break;
                                case PROC_POLICY_ACTION_DROP:
                                        /* PROCESS DROP BOOST IMPORTANT */
-                                       error = task_importance_drop_external_assertion(current_task(), 1);
+                                       error = task_importance_drop_legacy_external_assertion(current_task(), 1);
                                        break;
                                default:
                                        error = (EINVAL);
@@ -469,6 +488,56 @@ proc_pidbackgrounded(pid_t pid, uint32_t* state)
        return (0);
 }
 
+/*
+ * Get the darwin background state of the originator. If the current
+ * process app type is App, then it is the originator, else if it is
+ * a Daemon, then creator of the Resource Accounting attribute of
+ * the current thread voucher is the originator of the work.
+ */
+int
+proc_get_originatorbgstate(uint32_t *is_backgrounded)
+{
+       uint32_t bgstate;
+       proc_t p = current_proc();
+       uint32_t flagsp;
+       kern_return_t kr;
+       pid_t pid;
+       int ret;
+       thread_t thread = current_thread();
+
+       bgstate = proc_get_effective_thread_policy(thread, TASK_POLICY_DARWIN_BG);
+       
+       /* If current thread or task backgrounded, return background */
+       if (bgstate) {
+               *is_backgrounded = 1;
+               return 0;
+       }
+
+       /* Check if current process app type is App, then return foreground */
+       proc_get_darwinbgstate(p->task, &flagsp);
+       if ((flagsp & PROC_FLAG_APPLICATION) == PROC_FLAG_APPLICATION) {
+               *is_backgrounded = 0;
+               return 0;
+       }
+
+       /*
+        * Get the current voucher origin pid and it's bgstate.The pid
+        * returned here might not be valid or may have been recycled.
+        */
+       kr = thread_get_current_voucher_origin_pid(&pid);
+       if (kr != KERN_SUCCESS) {
+               if (kr == KERN_INVALID_TASK)
+                       return ESRCH;
+               else if (kr == KERN_INVALID_VALUE)
+                       return ENOATTR;
+               else
+                       return EINVAL;
+       }
+
+       ret = proc_pidbackgrounded(pid, is_backgrounded);
+       return ret;
+}
+
 int
 proc_apply_resource_actions(void * bsdinfo, __unused int type, int action)
 {
@@ -499,7 +568,6 @@ proc_apply_resource_actions(void * bsdinfo, __unused int type, int action)
        return(0);
 }
 
-
 int
 proc_restore_resource_actions(void * bsdinfo, __unused int type, int action)
 {