X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d190cdc3f5544636abb56dc1874be391d3e1b148..refs/heads/master:/libsyscall/wrappers/libproc/libproc.c diff --git a/libsyscall/wrappers/libproc/libproc.c b/libsyscall/wrappers/libproc/libproc.c index cc0321e2d..c3ef51b83 100644 --- a/libsyscall/wrappers/libproc/libproc.c +++ b/libsyscall/wrappers/libproc/libproc.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006, 2010 Apple Inc. All rights reserved. + * Copyright (c) 2006-2018 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -37,82 +37,89 @@ #include "libproc_internal.h" int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize); +int __proc_info_extended_id(int32_t callnum, int32_t pid, uint32_t flavor, uint32_t flags, uint64_t ext_id, uint64_t arg, user_addr_t buffer, int32_t buffersize); __private_extern__ int proc_setthreadname(void * buffer, int buffersize); int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid); int proc_rlimit_control(pid_t pid, int flavor, void *arg); -int -proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) +int +proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) { int retval; - + if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) { - if ((retval = __proc_info(PROC_INFO_CALL_LISTPIDS, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1) - return(0); + if ((retval = __proc_info(PROC_INFO_CALL_LISTPIDS, type, typeinfo, (uint64_t)0, buffer, buffersize)) == -1) { + return 0; + } } else { errno = EINVAL; retval = 0; } - return(retval); + return retval; } -int +int proc_listallpids(void * buffer, int buffersize) { int numpids; numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize); - if (numpids == -1) - return(-1); - else - return(numpids/sizeof(int)); + if (numpids == -1) { + return -1; + } else { + return numpids / sizeof(int); + } } -int +int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) { int numpids; numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize); - if (numpids == -1) - return(-1); - else - return(numpids/sizeof(int)); + if (numpids == -1) { + return -1; + } else { + return numpids / sizeof(int); + } } -int +int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) { int numpids; numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize); - if (numpids == -1) - return(-1); - else - return(numpids/sizeof(int)); + if (numpids == -1) { + return -1; + } else { + return numpids / sizeof(int); + } } -int -proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) +int +proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, arg, buffer, buffersize)) == -1) - return(0); - - return(retval); + if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, arg, buffer, buffersize)) == -1) { + return 0; + } + + return retval; } -int +int proc_pidoriginatorinfo(int flavor, void *buffer, int buffersize) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO, getpid(), flavor, 0, buffer, buffersize)) == -1) - return(0); - - return(retval); + if ((retval = __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO, getpid(), flavor, 0, buffer, buffersize)) == -1) { + return 0; + } + + return retval; } int @@ -120,8 +127,9 @@ proc_listcoalitions(int flavor, int coaltype, void *buffer, int buffersize) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_LISTCOALITIONS, flavor, coaltype, 0, buffer, buffersize)) == -1) + if ((retval = __proc_info(PROC_INFO_CALL_LISTCOALITIONS, flavor, coaltype, 0, buffer, buffersize)) == -1) { return 0; + } return retval; } @@ -129,7 +137,7 @@ proc_listcoalitions(int flavor, int coaltype, void *buffer, int buffersize) int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) { - return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0)); + return __proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0); } int @@ -145,18 +153,19 @@ proc_setthread_cpupercent(uint8_t percentage, uint32_t ms_refill) arg = ((ms_refill << 8) | percentage); - return (proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS, (void *)(uintptr_t)arg)); + return proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS, (void *)(uintptr_t)arg); } -int +int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1) - return(0); - - return (retval); + if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1) { + return 0; + } + + return retval; } @@ -165,22 +174,40 @@ proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int b { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1) - return (0); - return (retval); + if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1) { + return 0; + } + return retval; +} + +int +proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, int buffersize) +{ + int ret; + + if ((ret = __proc_info(PROC_INFO_CALL_PIDDYNKQUEUEINFO, pid, flavor, (uint64_t)kq_id, buffer, buffersize)) == -1) { + return 0; + } + + return ret; } +int +proc_udata_info(int pid, int flavor, void *buffer, int buffersize) +{ + return __proc_info(PROC_INFO_CALL_UDATA_INFO, pid, flavor, 0, buffer, buffersize); +} int proc_name(int pid, void * buffer, uint32_t buffersize) { int retval = 0, len; struct proc_bsdinfo pbsd; - - + + if (buffersize < sizeof(pbsd.pbi_name)) { errno = ENOMEM; - return(0); + return 0; } retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo)); @@ -191,35 +218,27 @@ proc_name(int pid, void * buffer, uint32_t buffersize) bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm)); } len = (int)strlen(buffer); - return(len); + return len; } - return(0); + return 0; } -int +int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) { - int retval = 0, len; - struct proc_regionwithpathinfo reginfo; - + int retval; + struct proc_regionpath path; + if (buffersize < MAXPATHLEN) { errno = ENOMEM; - return(0); + return 0; } - - retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo)); - if (retval != -1) { - len = (int)strlen(®info.prp_vip.vip_path[0]); - if (len != 0) { - if (len > MAXPATHLEN) - len = MAXPATHLEN; - bcopy(®info.prp_vip.vip_path[0], buffer, len); - return(len); - } - return(0); + + retval = proc_pidinfo(pid, PROC_PIDREGIONPATH, (uint64_t)address, &path, sizeof(struct proc_regionpath)); + if (retval != 0) { + return (int)(strlcpy(buffer, path.prpo_path, buffersize)); } - return(0); - + return 0; } int @@ -227,9 +246,10 @@ proc_kmsgbuf(void * buffer, uint32_t buffersize) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0, 0, (uint64_t)0, buffer, buffersize)) == -1) - return(0); - return (retval); + if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0, 0, (uint64_t)0, buffer, buffersize)) == -1) { + return 0; + } + return retval; } int @@ -239,45 +259,73 @@ proc_pidpath(int pid, void * buffer, uint32_t buffersize) if (buffersize < PROC_PIDPATHINFO_SIZE) { errno = ENOMEM; - return(0); + return 0; } - if (buffersize > PROC_PIDPATHINFO_MAXSIZE) { + if (buffersize > PROC_PIDPATHINFO_MAXSIZE) { errno = EOVERFLOW; - return(0); + return 0; } - retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize); if (retval != -1) { len = (int)strlen(buffer); - return(len); + return len; } - return (0); + return 0; } +int +proc_pidpath_audittoken(audit_token_t *audittoken, void * buffer, uint32_t buffersize) +{ + int retval, len; -int + if (buffersize < PROC_PIDPATHINFO_SIZE) { + errno = ENOMEM; + return 0; + } + if (buffersize > PROC_PIDPATHINFO_MAXSIZE) { + errno = EOVERFLOW; + return 0; + } + + int pid = audittoken->val[5]; + int idversion = audittoken->val[7]; + + retval = __proc_info_extended_id(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, PIF_COMPARE_IDVERSION, (uint64_t)idversion, + (uint64_t)0, buffer, buffersize); + if (retval != -1) { + len = (int)strlen(buffer); + return len; + } + return 0; +} + +int proc_libversion(int *major, int * minor) { - - if (major != NULL) + if (major != NULL) { *major = 1; - if (minor != NULL) + } + if (minor != NULL) { *minor = 1; - return(0); + } + return 0; } int proc_setpcontrol(const int control) { - int retval ; + int retval; + + if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE) { + return EINVAL; + } - if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE) - return(EINVAL); + if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1) { + return errno; + } - if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1) - return(errno); - - return(0); + return 0; } @@ -286,12 +334,13 @@ proc_setthreadname(void * buffer, int buffersize) { int retval; - retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize); + retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize); - if (retval == -1) - return(errno); - else - return(0); + if (retval == -1) { + return errno; + } else { + return 0; + } } int @@ -300,7 +349,7 @@ proc_track_dirty(pid_t pid, uint32_t flags) if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) { return errno; } - + return 0; } @@ -308,7 +357,7 @@ int proc_set_dirty(pid_t pid, bool dirty) { if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) { - return errno; + return errno; } return 0; @@ -318,16 +367,16 @@ int proc_get_dirty(pid_t pid, uint32_t *flags) { int retval; - + if (!flags) { return EINVAL; } - + retval = __proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0); if (retval == -1) { - return errno; + return errno; } - + *flags = retval; return 0; @@ -337,7 +386,7 @@ int proc_clear_dirty(pid_t pid, uint32_t flags) { if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_CLEAR, flags, NULL, 0) == -1) { - return errno; + return errno; } return 0; @@ -347,18 +396,18 @@ int proc_terminate(pid_t pid, int *sig) { int retval; - + if (!sig) { return EINVAL; } - + retval = __proc_info(PROC_INFO_CALL_TERMINATE, pid, 0, 0, NULL, 0); if (retval == -1) { - return errno; + return errno; } - + *sig = retval; - + return 0; } @@ -372,18 +421,18 @@ proc_set_cpumon_params(pid_t pid, int percentage, int interval) { proc_policy_cpuusage_attr_t attr; - /* no argument validation ... - * task_set_cpuusage() ignores 0 values and squashes negative - * values into uint32_t. - */ + /* no argument validation ... + * task_set_cpuusage() ignores 0 values and squashes negative + * values into uint32_t. + */ attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC; attr.ppattr_cpu_percentage = percentage; attr.ppattr_cpu_attr_interval = (uint64_t)interval; attr.ppattr_cpu_attr_deadline = 0; - return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, - PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0)); + return __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, + PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0); } int @@ -393,7 +442,7 @@ proc_get_cpumon_params(pid_t pid, int *percentage, int *interval) int ret; ret = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_RESOURCE_USAGE, - PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0); + PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0); if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) { *percentage = attr.ppattr_cpu_percentage; @@ -403,7 +452,7 @@ proc_get_cpumon_params(pid_t pid, int *percentage, int *interval) *interval = 0; } - return (ret); + return ret; } int @@ -416,18 +465,18 @@ proc_set_cpumon_defaults(pid_t pid) attr.ppattr_cpu_attr_interval = 0; attr.ppattr_cpu_attr_deadline = 0; - return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, - PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0)); + return __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, + PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0); } int proc_resume_cpumon(pid_t pid) { return __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_ENABLE, - PROC_POLICY_RESOURCE_USAGE, - PROC_POLICY_RUSAGE_CPU, - NULL, pid, 0); + PROC_POLICY_ACTION_ENABLE, + PROC_POLICY_RESOURCE_USAGE, + PROC_POLICY_RUSAGE_CPU, + NULL, pid, 0); } int @@ -440,8 +489,8 @@ proc_disable_cpumon(pid_t pid) attr.ppattr_cpu_attr_interval = 0; attr.ppattr_cpu_attr_deadline = 0; - return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, - PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0)); + return __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, + PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0); } @@ -459,9 +508,9 @@ proc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval) int current_interval = 0; /* intervals are in seconds */ int ret = 0; - if ((percentage <= 0) || (interval <= 0)) { + if ((percentage <= 0) || (interval <= 0)) { errno = EINVAL; - return (-1); + return -1; } /* @@ -469,33 +518,32 @@ proc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval) * already active. If either the percentage or the * interval is nonzero, then CPU monitoring is * already in use for this process. - * + * * XXX: need set...() and set..fatal() to behave similarly. * Currently, this check prevents 1st party apps (which get a * default non-fatal monitor) not to get a fatal monitor. */ (void)proc_get_cpumon_params(pid, ¤t_percentage, ¤t_interval); - if (current_percentage || current_interval) - { + if (current_percentage || current_interval) { /* * The CPU monitor appears to be active. * We choose not to disturb those settings. */ errno = EBUSY; - return (-1); + return -1; } - + if ((ret = proc_set_cpumon_params(pid, percentage, interval)) != 0) { /* Failed to activate the CPU monitor */ - return (ret); + return ret; } - - if ((ret = proc_rlimit_control(pid, RLIMIT_CPU_USAGE_MONITOR, CPUMON_MAKE_FATAL)) != 0) { + + if ((ret = proc_rlimit_control(pid, RLIMIT_CPU_USAGE_MONITOR, (void *)(uintptr_t)CPUMON_MAKE_FATAL)) != 0) { /* Failed to set termination, back out the CPU monitor settings. */ (void)proc_disable_cpumon(pid); } - return (ret); + return ret; } int @@ -506,7 +554,7 @@ proc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused) params.wm_flags = WAKEMON_ENABLE; params.wm_rate = rate_hz; - return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)); + return proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms); } #ifndef WAKEMON_GET_PARAMS @@ -523,13 +571,13 @@ proc_get_wakemon_params(pid_t pid, int *rate_hz, int *flags) params.wm_flags = WAKEMON_GET_PARAMS; if ((error = proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)) != 0) { - return (error); + return error; } *rate_hz = params.wm_rate; *flags = params.wm_flags; - return (0); + return 0; } int @@ -540,7 +588,7 @@ proc_set_wakemon_defaults(pid_t pid) params.wm_flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS; params.wm_rate = -1; - return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)); + return proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms); } int @@ -551,144 +599,216 @@ proc_disable_wakemon(pid_t pid) params.wm_flags = WAKEMON_DISABLE; params.wm_rate = -1; - return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)); + return proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms); } int proc_list_uptrs(int pid, uint64_t *buf, uint32_t bufsz) { - int i, j; - int nfds, nkns; - int count = 0; - int knote_max = 4096; /* arbitrary starting point */ + return __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDLISTUPTRS, 0, + buf, bufsz); +} - /* if buffer is empty, this call simply counts the knotes */ - if (bufsz > 0 && buf == NULL) { - errno = EFAULT; - return -1; - } +int +proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz) +{ + return __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDLISTDYNKQUEUES, 0, + buf, bufsz); +} - /* get the list of FDs for this process */ - struct proc_fdinfo fdlist[OPEN_MAX+1]; - nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fdlist[1], OPEN_MAX*sizeof(struct proc_fdinfo)); - if (nfds < 0 || nfds > OPEN_MAX) { - return -1; - } - /* Add FD -1, the implicit workq kqueue */ - fdlist[0].proc_fd = -1; - fdlist[0].proc_fdtype = PROX_FDTYPE_KQUEUE; - nfds++; +int +proc_setcpu_percentage(pid_t pid, int action, int percentage) +{ + proc_policy_cpuusage_attr_t attr; - struct kevent_extinfo *kqext = malloc(knote_max * sizeof(struct kevent_extinfo)); - if (!kqext) { - errno = ENOMEM; - return -1; + bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); + attr.ppattr_cpu_attr = action; + attr.ppattr_cpu_percentage = percentage; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; } +} - for (i = 0; i < nfds; i++) { - if (fdlist[i].proc_fdtype != PROX_FDTYPE_KQUEUE) { - continue; - } +int +proc_reset_footprint_interval(pid_t pid) +{ + return proc_rlimit_control(pid, RLIMIT_FOOTPRINT_INTERVAL, (void *)(uintptr_t)FOOTPRINT_INTERVAL_RESET); +} - again: - nkns = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, PROC_PIDFDKQUEUE_EXTINFO, - (uint64_t)fdlist[i].proc_fd, kqext, knote_max * sizeof(struct kevent_extinfo)); - if (nkns < 0) { - if (errno == EBADF) { - /* the FD table can change after enumerating the FDs */ - errno = EAGAIN; - } - free(kqext); - return -1; - } +int +proc_clear_cpulimits(pid_t pid) +{ + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } +} - if (nkns > knote_max) { - /* there are more knotes than we requested - try again with a - * larger buffer */ - free(kqext); - knote_max = nkns + 32; /* small margin in case of extra knotes */ - kqext = malloc(knote_max * sizeof(struct kevent_extinfo)); - if (!kqext) { - errno = ENOMEM; - return -1; - } - goto again; - } +#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) - for (j = 0; j < nkns; j++) { - if (kqext[j].kqext_kev.udata == 0) { - continue; - } +int +proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline) +{ + proc_policy_cpuusage_attr_t attr; - if (bufsz >= sizeof(uint64_t)) { - *buf++ = kqext[j].kqext_kev.udata; - bufsz -= sizeof(uint64_t); - } - count++; - } + bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); + attr.ppattr_cpu_attr = action; + attr.ppattr_cpu_attr_deadline = deadline; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; } - - free(kqext); - return count; } -int -proc_setcpu_percentage(pid_t pid, int action, int percentage) +int +proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline) { proc_policy_cpuusage_attr_t attr; bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); attr.ppattr_cpu_attr = action; attr.ppattr_cpu_percentage = percentage; - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); + attr.ppattr_cpu_attr_deadline = deadline; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } } int -proc_clear_cpulimits(pid_t pid) +proc_appstate(int pid, int * appstatep) { - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); + int state; + + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (proc_policy_attribute_t*)&state, pid, (uint64_t)0) != -1) { + if (appstatep != NULL) { + *appstatep = state; + } + return 0; + } else { + return errno; + } } +int +proc_setappstate(int pid, int appstate) +{ + int state = appstate; + + switch (state) { + case PROC_APPSTATE_NONE: + case PROC_APPSTATE_ACTIVE: + case PROC_APPSTATE_INACTIVE: + case PROC_APPSTATE_BACKGROUND: + case PROC_APPSTATE_NONUI: + break; + default: + return EINVAL; + } + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (proc_policy_attribute_t*)&state, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } +} + +int +proc_devstatusnotify(int devicestatus) +{ + int state = devicestatus; + + switch (devicestatus) { + case PROC_DEVSTATUS_SHORTTERM: + case PROC_DEVSTATUS_LONGTERM: + break; + default: + return EINVAL; + } + + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_DEVSTATUS, (proc_policy_attribute_t*)&state, getpid(), (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } +} + +int +proc_pidbind(int pid, uint64_t threadid, int bind) +{ + int state = bind; + pid_t passpid = pid; + + switch (bind) { + case PROC_PIDBIND_CLEAR: + passpid = getpid(); /* ignore pid on clear */ + break; + case PROC_PIDBIND_SET: + break; + default: + return EINVAL; + } + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_PIDBIND, (proc_policy_attribute_t*)&state, passpid, threadid) != -1) { + return 0; + } else { + return errno; + } +} + +int +proc_can_use_foreground_hw(int pid, uint32_t *reason) +{ + return __proc_info(PROC_INFO_CALL_CANUSEFGHW, pid, 0, 0, reason, sizeof(*reason)); +} +#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */ /* Donate importance to adaptive processes from this process */ -int +int proc_donate_importance_boost() { int rval; +#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_SET, - PROC_POLICY_BOOST, - PROC_POLICY_IMP_DONATION, - NULL, getpid(), 0); + PROC_POLICY_ACTION_ENABLE, + PROC_POLICY_APPTYPE, + PROC_POLICY_IOS_DONATEIMP, + NULL, getpid(), (uint64_t)0); +#else /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */ + rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, + PROC_POLICY_ACTION_SET, + PROC_POLICY_BOOST, + PROC_POLICY_IMP_DONATION, + NULL, getpid(), 0); +#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */ - if (rval == 0) - return (0); - else - return (errno); + if (rval == 0) { + return 0; + } else { + return errno; + } } static __attribute__((noinline)) void -proc_importance_bad_assertion(char *reason) { - (void)reason; +proc_importance_bad_assertion(char *reason) +{ + (void)reason; } -/* +/* * Use the address of these variables as the token. This way, they can be * printed in the debugger as useful names. */ uint64_t important_boost_assertion_token = 0xfafafafafafafafa; uint64_t normal_boost_assertion_token = 0xfbfbfbfbfbfbfbfb; uint64_t non_boost_assertion_token = 0xfcfcfcfcfcfcfcfc; -uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd; +uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd; /* * Accept the boost on a message, or request another boost assertion @@ -701,48 +821,48 @@ uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd; */ int proc_importance_assertion_begin_with_msg(mach_msg_header_t *msg, - __unused mach_msg_trailer_t *trailer, - uint64_t *assertion_token) + __unused mach_msg_trailer_t *trailer, + uint64_t *assertion_token) { int rval = 0; - if (assertion_token == NULL) - return (EINVAL); + if (assertion_token == NULL) { + return EINVAL; + } #define LEGACYBOOSTMASK (MACH_MSGH_BITS_VOUCHER_MASK | MACH_MSGH_BITS_RAISEIMP) #define LEGACYBOOSTED(m) (((m)->msgh_bits & LEGACYBOOSTMASK) == MACH_MSGH_BITS_RAISEIMP) /* Is this a legacy boosted message? */ if (LEGACYBOOSTED(msg)) { - - /* + /* * Have we accepted the implicit boost for this message yet? - * If we haven't accepted it yet, no need to call into kernel. + * If we haven't accepted it yet, no need to call into kernel. */ if ((msg->msgh_bits & MACH_MSGH_BITS_IMPHOLDASRT) == 0) { msg->msgh_bits |= MACH_MSGH_BITS_IMPHOLDASRT; *assertion_token = (uint64_t) &important_boost_assertion_token; - return (0); + return 0; } /* Request an additional boost count */ rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_HOLD, - PROC_POLICY_BOOST, - PROC_POLICY_IMP_IMPORTANT, - NULL, getpid(), 0); + PROC_POLICY_ACTION_HOLD, + PROC_POLICY_BOOST, + PROC_POLICY_IMP_IMPORTANT, + NULL, getpid(), 0); if (rval == 0) { *assertion_token = (uint64_t) &important_boost_assertion_token; - return (0); + return 0; } else if (errno == EOVERFLOW) { proc_importance_bad_assertion("Attempted to take assertion while not boosted"); - return (errno); + return errno; } else { - return (errno); + return errno; } } - - return (EIO); + + return EIO; } @@ -755,26 +875,27 @@ proc_importance_assertion_complete(uint64_t assertion_token) { int rval = 0; - if (assertion_token == 0) - return (0); + if (assertion_token == 0) { + return 0; + } if (assertion_token == (uint64_t) &important_boost_assertion_token) { rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_DROP, - PROC_POLICY_BOOST, - PROC_POLICY_IMP_IMPORTANT, - NULL, getpid(), 0); + PROC_POLICY_ACTION_DROP, + PROC_POLICY_BOOST, + PROC_POLICY_IMP_IMPORTANT, + NULL, getpid(), 0); if (rval == 0) { - return (0); + return 0; } else if (errno == EOVERFLOW) { proc_importance_bad_assertion("Attempted to drop too many assertions"); - return (errno); + return errno; } else { - return (errno); + return errno; } } else { proc_importance_bad_assertion("Attempted to drop assertion with invalid token"); - return (EIO); + return EIO; } } @@ -787,7 +908,7 @@ proc_importance_assertion_complete(uint64_t assertion_token) */ int proc_denap_assertion_begin_with_msg(mach_msg_header_t *msg, - uint64_t *assertion_token) + uint64_t *assertion_token) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -808,92 +929,96 @@ proc_denap_assertion_complete(uint64_t assertion_token) return proc_importance_assertion_complete(assertion_token); } +#if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) int proc_clear_vmpressure(pid_t pid) { - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } } /* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */ -int +int proc_set_owner_vmpressure(void) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1) - return(errno); - - return(0); + if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1) { + return errno; + } + + return 0; } /* mark yourself to delay idle sleep on disk IO */ -int +int proc_set_delayidlesleep(void) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1) - return(errno); + if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1) { + return errno; + } - return(0); + return 0; } /* Reset yourself to delay idle sleep on disk IO, if already set */ -int +int proc_clear_delayidlesleep(void) { int retval; - if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1) - return(errno); + if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1) { + return errno; + } - return(0); + return 0; } /* disable the launch time backgroudn policy and restore the process to default group */ -int +int proc_disable_apptype(pid_t pid, int apptype) { switch (apptype) { - case PROC_POLICY_OSX_APPTYPE_TAL: - case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: - break; - default: - return(EINVAL); + case PROC_POLICY_OSX_APPTYPE_TAL: + case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: + break; + default: + return EINVAL; } - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); - + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } } /* re-enable the launch time background policy if it had been disabled. */ -int +int proc_enable_apptype(pid_t pid, int apptype) { switch (apptype) { - case PROC_POLICY_OSX_APPTYPE_TAL: - case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: - break; - default: - return(EINVAL); - + case PROC_POLICY_OSX_APPTYPE_TAL: + case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: + break; + default: + return EINVAL; } - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); - + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) { + return 0; + } else { + return errno; + } } -#if !TARGET_IPHONE_SIMULATOR +#if !TARGET_OS_SIMULATOR int proc_suppress(__unused pid_t pid, __unused uint64_t *generation) @@ -901,8 +1026,72 @@ proc_suppress(__unused pid_t pid, __unused uint64_t *generation) return 0; } -#endif /* !TARGET_IPHONE_SIMULATOR */ +#endif /* !TARGET_OS_SIMULATOR */ +#endif /* !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */ +int +proc_set_no_smt(void) +{ + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_NO_SMT, 0, NULL, getpid(), (uint64_t)0) == -1) { + return errno; + } + return 0; +} +int +proc_setthread_no_smt(void) +{ + extern uint64_t __thread_selfid(void); + if (__process_policy(PROC_POLICY_SCOPE_THREAD, PROC_POLICY_ACTION_APPLY, PROC_POLICY_NO_SMT, 0, NULL, 0, __thread_selfid()) == -1) { + return errno; + } + return 0; +} +int +proc_set_csm(uint32_t flags) +{ + const uint32_t mask = PROC_CSM_ALL | PROC_CSM_TECS | PROC_CSM_NOSMT; + if ((flags & ~mask) != 0) { + return EINVAL; + } + + if (flags & (PROC_CSM_NOSMT | PROC_CSM_ALL)) { + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_NO_SMT, 0, NULL, getpid(), (uint64_t)0) == -1) { + return errno; + } + } + + if (flags & (PROC_CSM_TECS | PROC_CSM_ALL)) { + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_TECS, 0, NULL, getpid(), (uint64_t)0) == -1) { + return errno; + } + } + + return 0; +} + +int +proc_setthread_csm(uint32_t flags) +{ + extern uint64_t __thread_selfid(void); + const uint32_t mask = PROC_CSM_ALL | PROC_CSM_TECS | PROC_CSM_NOSMT; + if ((flags & ~mask) != 0) { + return EINVAL; + } + + if (flags & (PROC_CSM_NOSMT | PROC_CSM_ALL)) { + if (__process_policy(PROC_POLICY_SCOPE_THREAD, PROC_POLICY_ACTION_APPLY, PROC_POLICY_NO_SMT, 0, NULL, 0, __thread_selfid()) == -1) { + return errno; + } + } + + if (flags & (PROC_CSM_TECS | PROC_CSM_ALL)) { + if (__process_policy(PROC_POLICY_SCOPE_THREAD, PROC_POLICY_ACTION_APPLY, PROC_POLICY_TECS, 0, NULL, 0, __thread_selfid()) == -1) { + return errno; + } + } + + return 0; +}