+static int
+set_gpudeny_proc(struct proc *curp, struct proc *targetp, int priority)
+{
+ int error = 0;
+ kauth_cred_t ucred;
+ kauth_cred_t target_cred;
+
+ ucred = kauth_cred_get();
+ target_cred = kauth_cred_proc_ref(targetp);
+
+ /* TODO: Entitlement instead of uid check */
+
+ if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
+ kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
+ kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
+ error = EPERM;
+ goto out;
+ }
+
+ if (curp == targetp) {
+ error = EPERM;
+ goto out;
+ }
+
+#if CONFIG_MACF
+ error = mac_proc_check_sched(curp, targetp);
+ if (error)
+ goto out;
+#endif
+
+ switch (priority) {
+ case PRIO_DARWIN_GPU_DENY:
+ task_set_gpu_denied(proc_task(targetp), TRUE);
+ break;
+ case PRIO_DARWIN_GPU_ALLOW:
+ task_set_gpu_denied(proc_task(targetp), FALSE);
+ break;
+ default:
+ error = EINVAL;
+ goto out;
+ }
+
+out:
+ kauth_cred_unref(&target_cred);
+ return (error);
+
+}
+
+static int
+proc_set_darwin_role(proc_t curp, proc_t targetp, int priority)
+{
+ int error = 0;
+ uint32_t flagsp = 0;
+
+ kauth_cred_t ucred, target_cred;
+
+ ucred = kauth_cred_get();
+ target_cred = kauth_cred_proc_ref(targetp);
+
+ if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
+ kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
+ kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
+ if (priv_check_cred(ucred, PRIV_SETPRIORITY_DARWIN_ROLE, 0) != 0) {
+ error = EPERM;
+ goto out;
+ }
+ }
+
+ if (curp != targetp) {
+#if CONFIG_MACF
+ if ((error = mac_proc_check_sched(curp, targetp)))
+ goto out;
+#endif
+ }
+
+ proc_get_darwinbgstate(proc_task(targetp), &flagsp);
+ if ((flagsp & PROC_FLAG_APPLICATION) != PROC_FLAG_APPLICATION) {
+ error = ENOTSUP;
+ goto out;
+ }
+
+ integer_t role = 0;
+
+ if ((error = proc_darwin_role_to_task_role(priority, &role)))
+ goto out;
+
+ proc_set_task_policy(proc_task(targetp), TASK_POLICY_ATTRIBUTE,
+ TASK_POLICY_ROLE, role);
+
+out:
+ kauth_cred_unref(&target_cred);
+ return (error);
+}
+
+static int
+proc_get_darwin_role(proc_t curp, proc_t targetp, int *priority)
+{
+ int error = 0;
+ int role = 0;
+
+ kauth_cred_t ucred, target_cred;
+
+ ucred = kauth_cred_get();
+ target_cred = kauth_cred_proc_ref(targetp);
+
+ if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
+ kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
+ kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
+ error = EPERM;
+ goto out;
+ }
+
+ if (curp != targetp) {
+#if CONFIG_MACF
+ if ((error = mac_proc_check_sched(curp, targetp)))
+ goto out;
+#endif
+ }
+
+ role = proc_get_task_policy(proc_task(targetp), TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE);
+
+ *priority = proc_task_role_to_darwin_role(role);
+
+out:
+ kauth_cred_unref(&target_cred);
+ return (error);
+}
+
+
+static int
+get_background_proc(struct proc *curp, struct proc *targetp, int *priority)
+{
+ int external = 0;
+ int error = 0;
+ kauth_cred_t ucred, target_cred;
+
+ ucred = kauth_cred_get();
+ target_cred = kauth_cred_proc_ref(targetp);
+
+ if (!kauth_cred_issuser(ucred) && kauth_cred_getruid(ucred) &&
+ kauth_cred_getuid(ucred) != kauth_cred_getuid(target_cred) &&
+ kauth_cred_getruid(ucred) != kauth_cred_getuid(target_cred)) {
+ error = EPERM;
+ goto out;
+ }
+
+ external = (curp == targetp) ? TASK_POLICY_INTERNAL : TASK_POLICY_EXTERNAL;
+
+ *priority = proc_get_task_policy(current_task(), external, TASK_POLICY_DARWIN_BG);
+
+out:
+ kauth_cred_unref(&target_cred);
+ return (error);
+}
+