]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/sys_coalition.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / kern / sys_coalition.c
index bfbd9c9ca60744ad2460af5d843a430f6593bc67..28e3d3f402a5e4a41a1b93f44aa8a57ba6284fe3 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <sys/coalition.h>
 #include <sys/errno.h>
 
 #include <sys/coalition.h>
 #include <sys/errno.h>
+#include <sys/kauth.h>
 #include <sys/kernel.h>
 #include <sys/sysproto.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/sysproto.h>
 #include <sys/systm.h>
@@ -42,15 +43,13 @@ coalition_create_syscall(user_addr_t cidp, uint32_t flags)
                return EINVAL;
        }
 
                return EINVAL;
        }
 
-       kr = coalition_create_internal(type, role, privileged, &coal);
+       kr = coalition_create_internal(type, role, privileged, &coal, &cid);
        if (kr != KERN_SUCCESS) {
                /* for now, the only kr is KERN_RESOURCE_SHORTAGE */
                error = ENOMEM;
                goto out;
        }
 
        if (kr != KERN_SUCCESS) {
                /* for now, the only kr is KERN_RESOURCE_SHORTAGE */
                error = ENOMEM;
                goto out;
        }
 
-       cid = coalition_id(coal);
-
        coal_dbg("(addr, %u) -> %llu", flags, cid);
        error = copyout(&cid, cidp, sizeof(cid));
 out:
        coal_dbg("(addr, %u) -> %llu", flags, cid);
        error = copyout(&cid, cidp, sizeof(cid));
 out:
@@ -237,7 +236,30 @@ coalition_info_resource_usage(coalition_t coal, user_addr_t buffer, user_size_t
        return copyout(&cru, buffer, MIN(bufsize, sizeof(cru)));
 }
 
        return copyout(&cru, buffer, MIN(bufsize, sizeof(cru)));
 }
 
+#if CONFIG_THREAD_GROUPS
+static int
+coalition_info_set_name_internal(coalition_t coal, user_addr_t buffer, user_size_t bufsize)
+{
+       int error;
+       char name[THREAD_GROUP_MAXNAME];
+
+       if (coalition_type(coal) != COALITION_TYPE_JETSAM) {
+               return EINVAL;
+       }
+       bzero(name, sizeof(name));
+       error = copyin(buffer, name, MIN(bufsize, sizeof(name) - 1));
+       if (error) {
+               return error;
+       }
+       struct thread_group *tg = coalition_get_thread_group(coal);
+       thread_group_set_name(tg, name);
+       thread_group_release(tg);
+       return error;
+}
+
+#else /* CONFIG_THREAD_GROUPS */
 #define coalition_info_set_name_internal(...) 0
 #define coalition_info_set_name_internal(...) 0
+#endif /* CONFIG_THREAD_GROUPS */
 
 static int
 coalition_info_efficiency(coalition_t coal, user_addr_t buffer, user_size_t bufsize)
 
 static int
 coalition_info_efficiency(coalition_t coal, user_addr_t buffer, user_size_t bufsize)
@@ -256,10 +278,36 @@ coalition_info_efficiency(coalition_t coal, user_addr_t buffer, user_size_t bufs
        }
        if (flags & COALITION_FLAGS_EFFICIENT) {
                coalition_set_efficient(coal);
        }
        if (flags & COALITION_FLAGS_EFFICIENT) {
                coalition_set_efficient(coal);
+#if CONFIG_THREAD_GROUPS
+               struct thread_group *tg = coalition_get_thread_group(coal);
+               thread_group_set_flags(tg, THREAD_GROUP_FLAGS_EFFICIENT);
+               thread_group_release(tg);
+#endif /* CONFIG_THREAD_GROUPS */
        }
        return error;
 }
 
        }
        return error;
 }
 
+static int
+coalition_ledger_logical_writes_limit(coalition_t coal, user_addr_t buffer, user_size_t bufsize)
+{
+       int error = 0;
+       int64_t limit = 0;
+
+       if (coalition_type(coal) != COALITION_TYPE_RESOURCE) {
+               error = EINVAL;
+               goto out;
+       }
+       error = copyin(buffer, &limit, MIN(bufsize, sizeof(limit)));
+       if (error) {
+               goto out;
+       }
+
+
+       error = coalition_ledger_set_logical_writes_limit(coal, limit);
+out:
+       return error;
+}
+
 int
 coalition_info(proc_t p, struct coalition_info_args *uap, __unused int32_t *retval)
 {
 int
 coalition_info(proc_t p, struct coalition_info_args *uap, __unused int32_t *retval)
 {
@@ -315,6 +363,60 @@ bad:
        return error;
 }
 
        return error;
 }
 
+int
+coalition_ledger(__unused proc_t p, __unused struct coalition_ledger_args *uap, __unused int32_t *retval)
+{
+       user_addr_t cidp = uap->cid;
+       user_addr_t buffer = uap->buffer;
+       user_addr_t bufsizep = uap->bufsize;
+       user_size_t bufsize;
+       uint32_t operation = uap->operation;
+       int error;
+       uint64_t cid;
+       coalition_t coal = COALITION_NULL;
+
+       if (!kauth_cred_issuser(kauth_cred_get())) {
+               error = EPERM;
+               goto out;
+       }
+
+       error = copyin(cidp, &cid, sizeof(cid));
+       if (error) {
+               goto out;
+       }
+
+       coal = coalition_find_by_id(cid);
+       if (coal == COALITION_NULL) {
+               error = ESRCH;
+               goto out;
+       }
+
+       if (IS_64BIT_PROCESS(p)) {
+               user64_size_t size64;
+               error = copyin(bufsizep, &size64, sizeof(size64));
+               bufsize = (user_size_t)size64;
+       } else {
+               user32_size_t size32;
+               error = copyin(bufsizep, &size32, sizeof(size32));
+               bufsize = (user_size_t)size32;
+       }
+       if (error) {
+               goto out;
+       }
+
+       switch (operation) {
+       case COALITION_LEDGER_SET_LOGICAL_WRITES_LIMIT:
+               error = coalition_ledger_logical_writes_limit(coal, buffer, bufsize);
+               break;
+       default:
+               error = EINVAL;
+       }
+out:
+       if (coal != COALITION_NULL) {
+               coalition_release(coal);
+       }
+       return error;
+}
 #if DEVELOPMENT || DEBUG
 static int sysctl_coalition_get_ids SYSCTL_HANDLER_ARGS
 {
 #if DEVELOPMENT || DEBUG
 static int sysctl_coalition_get_ids SYSCTL_HANDLER_ARGS
 {
@@ -418,8 +520,7 @@ static int sysctl_coalition_get_page_count SYSCTL_HANDLER_ARGS
        memset(pgcount, 0, sizeof(pgcount));
 
        for (int t = 0; t < COALITION_NUM_TYPES; t++) {
        memset(pgcount, 0, sizeof(pgcount));
 
        for (int t = 0; t < COALITION_NUM_TYPES; t++) {
-               coal = COALITION_NULL;
-               coalition_is_leader(tproc->task, t, &coal);
+               coal = task_get_coalition(tproc->task, t);
                if (coal != COALITION_NULL) {
                        int ntasks = 0;
                        pgcount[t] = coalition_get_page_count(coal, &ntasks);
                if (coal != COALITION_NULL) {
                        int ntasks = 0;
                        pgcount[t] = coalition_get_page_count(coal, &ntasks);
@@ -484,7 +585,7 @@ static int sysctl_coalition_get_pid_list SYSCTL_HANDLER_ARGS
                return ESRCH;
        }
 
                return ESRCH;
        }
 
-       (void)coalition_is_leader(tproc->task, type, &coal);
+       coal = task_get_coalition(tproc->task, type);
        if (coal == COALITION_NULL) {
                goto out;
        }
        if (coal == COALITION_NULL) {
                goto out;
        }