]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_proc.c
xnu-6153.141.1.tar.gz
[apple/xnu.git] / bsd / kern / kern_proc.c
index 1efcb56746637f90d5a32204f2bab4d5d471ed4f..01f548e798049535aa93104b00a90737993fb455 100644 (file)
 #include <sys/persona.h>
 #include <sys/sysent.h>
 #include <sys/reason.h>
+#include <IOKit/IOBSD.h>        /* IOTaskHasEntitlement() */
 
 #ifdef CONFIG_32BIT_TELEMETRY
 #include <sys/kasl.h>
@@ -835,10 +836,20 @@ proc_selfppid(void)
        return current_proc()->p_ppid;
 }
 
-int
+uint64_t
 proc_selfcsflags(void)
 {
-       return current_proc()->p_csflags;
+       return (uint64_t)current_proc()->p_csflags;
+}
+
+int
+proc_csflags(proc_t p, uint64_t *flags)
+{
+       if (p && flags) {
+               *flags = (uint64_t)p->p_csflags;
+               return 0;
+       }
+       return EINVAL;
 }
 
 uint32_t
@@ -935,6 +946,12 @@ proc_name(int pid, char * buf, int size)
 {
        proc_t p;
 
+       if (size <= 0) {
+               return;
+       }
+
+       bzero(buf, size);
+
        if ((p = proc_find(pid)) != PROC_NULL) {
                strlcpy(buf, &p->p_comm[0], size);
                proc_rele(p);
@@ -1266,6 +1283,63 @@ proc_getexecutablevnode(proc_t p)
        return NULLVP;
 }
 
+int
+proc_gettty(proc_t p, vnode_t *vp)
+{
+       if (!p || !vp) {
+               return EINVAL;
+       }
+
+       struct session *procsp = proc_session(p);
+       int err = EINVAL;
+
+       if (procsp != SESSION_NULL) {
+               session_lock(procsp);
+               vnode_t ttyvp = procsp->s_ttyvp;
+               int ttyvid = procsp->s_ttyvid;
+               session_unlock(procsp);
+
+               if (ttyvp) {
+                       if (vnode_getwithvid(ttyvp, ttyvid) == 0) {
+                               *vp = ttyvp;
+                               err = 0;
+                       }
+               } else {
+                       err = ENOENT;
+               }
+
+               session_rele(procsp);
+       }
+
+       return err;
+}
+
+int
+proc_gettty_dev(proc_t p, dev_t *dev)
+{
+       struct session *procsp = proc_session(p);
+       boolean_t has_tty = FALSE;
+
+       if (procsp != SESSION_NULL) {
+               session_lock(procsp);
+
+               struct tty * tp = SESSION_TP(procsp);
+               if (tp != TTY_NULL) {
+                       *dev = tp->t_dev;
+                       has_tty = TRUE;
+               }
+
+               session_unlock(procsp);
+               session_rele(procsp);
+       }
+
+       if (has_tty) {
+               return 0;
+       } else {
+               return EINVAL;
+       }
+}
+
 int
 proc_selfexecutableargs(uint8_t *buf, size_t *buflen)
 {
@@ -2193,6 +2267,7 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
        case CS_OPS_IDENTITY:
        case CS_OPS_BLOB:
        case CS_OPS_TEAMID:
+       case CS_OPS_CLEAR_LV:
                break;          /* not restricted to root */
        default:
                if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
@@ -2229,6 +2304,7 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
        case CS_OPS_SET_STATUS:
        case CS_OPS_CLEARINSTALLER:
        case CS_OPS_CLEARPLATFORM:
+       case CS_OPS_CLEAR_LV:
                if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) {
                        goto out;
                }
@@ -2396,6 +2472,45 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
 
                break;
        }
+       case CS_OPS_CLEAR_LV: {
+               /*
+                * This option is used to remove library validation from
+                * a running process. This is used in plugin architectures
+                * when a program needs to load untrusted libraries. This
+                * allows the process to maintain library validation as
+                * long as possible, then drop it only when required.
+                * Once a process has loaded the untrusted library,
+                * relying on library validation in the future will
+                * not be effective. An alternative is to re-exec
+                * your application without library validation, or
+                * fork an untrusted child.
+                */
+#ifdef CONFIG_EMBEDDED
+               // On embedded platforms, we don't support dropping LV
+               error = ENOTSUP;
+#else
+               /*
+                * if we have the flag set, and the caller wants
+                * to remove it, and they're entitled to, then
+                * we remove it from the csflags
+                *
+                * NOTE: We are fine to poke into the task because
+                * we get a ref to pt when we do the proc_find
+                * at the beginning of this function.
+                *
+                * We also only allow altering ourselves.
+                */
+               if (forself == 1 && IOTaskHasEntitlement(pt->task, CLEAR_LV_ENTITLEMENT)) {
+                       proc_lock(pt);
+                       pt->p_csflags &= (~(CS_REQUIRE_LV | CS_FORCED_LV));
+                       proc_unlock(pt);
+                       error = 0;
+               } else {
+                       error = EPERM;
+               }
+#endif
+               break;
+       }
        case CS_OPS_BLOB: {
                void *start;
                size_t length;
@@ -3748,6 +3863,19 @@ proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t
        return KERN_SUCCESS;
 }
 
+bool
+proc_is_traced(proc_t p)
+{
+       bool ret = FALSE;
+       assert(p != PROC_NULL);
+       proc_lock(p);
+       if (p->p_lflag & P_LTRACED) {
+               ret = TRUE;
+       }
+       proc_unlock(p);
+       return ret;
+}
+
 #ifdef CONFIG_32BIT_TELEMETRY
 void
 proc_log_32bit_telemetry(proc_t p)
@@ -3768,7 +3896,7 @@ proc_log_32bit_telemetry(proc_t p)
         * Get proc name and parent proc name; if the parent execs, we'll get a
         * garbled name.
         */
-       bytes_printed = snprintf(signature_cur_end,
+       bytes_printed = scnprintf(signature_cur_end,
            signature_buf_end - signature_cur_end,
            "%s,%s,", p->p_name,
            (p->p_pptr ? p->p_pptr->p_name : ""));
@@ -3799,7 +3927,7 @@ proc_log_32bit_telemetry(proc_t p)
                identity = "";
        }
 
-       bytes_printed = snprintf(signature_cur_end,
+       bytes_printed = scnprintf(signature_cur_end,
            signature_buf_end - signature_cur_end,
            "%s,%s", teamid, identity);