]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_ktrace.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / bsd / kern / kern_ktrace.c
index af4573ef80e8f5169c38d64d281dc5bb303e79b1..628a19a55688911262c15f56f487dc7df71c9ab5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2015-2017 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -70,7 +70,7 @@ char *proc_name_address(void *p);
 
 kern_return_t ktrace_background_available_notify_user(void);
 
-lck_mtx_t *ktrace_lock;
+static lck_mtx_t *ktrace_mtx;
 
 /*
  * The overall state of ktrace, whether it is unconfigured, in foreground mode,
@@ -105,7 +105,7 @@ static uint32_t ktrace_active_mask = 0;
  *
  * Background tools must be RunAtLoad daemons.
  */
-static boolean_t should_notify_on_init = TRUE;
+static bool should_notify_on_init = true;
 
 /* Set the owning process of ktrace. */
 static void ktrace_set_owning_proc(proc_t p);
@@ -124,7 +124,10 @@ static void ktrace_promote_background(void);
  * This is managed by the user space-oriented function ktrace_set_owning_pid
  * and ktrace_unset_owning_pid.
  */
-boolean_t ktrace_keep_ownership_on_reset = FALSE;
+bool ktrace_keep_ownership_on_reset = false;
+
+/* Whether the kernel is the owner of ktrace. */
+bool ktrace_owner_kernel = false;
 
 /* Allow user space to unset the owning pid and potentially reset ktrace. */
 static void ktrace_set_invalid_owning_pid(void);
@@ -135,6 +138,48 @@ static void ktrace_set_invalid_owning_pid(void);
  */
 int ktrace_root_set_owner_allowed = 0;
 
+/*
+ * If ktrace is guaranteed that it's the only thread running on the system
+ * (e.g., during boot or wake) this flag disables locking requirements.
+ */
+static bool ktrace_single_threaded = false;
+
+void
+ktrace_lock(void)
+{
+       if (!ktrace_single_threaded) {
+               lck_mtx_lock(ktrace_mtx);
+       }
+}
+
+void
+ktrace_unlock(void)
+{
+       if (!ktrace_single_threaded) {
+               lck_mtx_unlock(ktrace_mtx);
+       }
+}
+
+void
+ktrace_assert_lock_held(void)
+{
+       if (!ktrace_single_threaded) {
+               lck_mtx_assert(ktrace_mtx, LCK_MTX_ASSERT_OWNED);
+       }
+}
+
+void
+ktrace_start_single_threaded(void)
+{
+       ktrace_single_threaded = true;
+}
+
+void
+ktrace_end_single_threaded(void)
+{
+       ktrace_single_threaded = false;
+}
+
 static void
 ktrace_reset_internal(uint32_t reset_mask)
 {
@@ -155,7 +200,7 @@ ktrace_reset_internal(uint32_t reset_mask)
                        ktrace_promote_background();
                } else if (ktrace_state == KTRACE_STATE_BG) {
                        /* background tool is resetting ktrace */
-                       should_notify_on_init = TRUE;
+                       should_notify_on_init = true;
                        ktrace_release_ownership();
                        ktrace_state = KTRACE_STATE_OFF;
                }
@@ -165,7 +210,7 @@ ktrace_reset_internal(uint32_t reset_mask)
 void
 ktrace_reset(uint32_t reset_mask)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        if (ktrace_active_mask == 0) {
                if (!ktrace_keep_ownership_on_reset) {
@@ -180,7 +225,6 @@ ktrace_reset(uint32_t reset_mask)
 static void
 ktrace_promote_background(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
        assert(ktrace_state != KTRACE_STATE_BG);
 
        /*
@@ -189,9 +233,9 @@ ktrace_promote_background(void)
         * for the host special port).
         */
        if (ktrace_background_available_notify_user() == KERN_FAILURE) {
-               should_notify_on_init = TRUE;
+               should_notify_on_init = true;
        } else {
-               should_notify_on_init = FALSE;
+               should_notify_on_init = false;
        }
 
        ktrace_release_ownership();
@@ -201,14 +245,13 @@ ktrace_promote_background(void)
 bool
 ktrace_background_active(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
        return (ktrace_state == KTRACE_STATE_BG);
 }
 
 int
 ktrace_read_check(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        if (proc_uniqueid(current_proc()) == ktrace_owning_unique_id)
        {
@@ -222,7 +265,7 @@ ktrace_read_check(void)
 static void
 ktrace_ownership_maintenance(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        /* do nothing if ktrace is not owned */
        if (ktrace_owning_unique_id == 0) {
@@ -248,7 +291,7 @@ ktrace_ownership_maintenance(void)
 int
 ktrace_configure(uint32_t config_mask)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
        assert(config_mask != 0);
 
        proc_t p = current_proc();
@@ -274,6 +317,7 @@ ktrace_configure(uint32_t config_mask)
                        return EPERM;
                }
 
+               ktrace_owner_kernel = false;
                ktrace_set_owning_proc(p);
                ktrace_active_mask |= config_mask;
                return 0;
@@ -295,7 +339,7 @@ ktrace_disable(enum ktrace_state state_to_match)
 int
 ktrace_get_owning_pid(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        ktrace_ownership_maintenance();
        return ktrace_owning_pid;
@@ -304,18 +348,24 @@ ktrace_get_owning_pid(void)
 void
 ktrace_kernel_configure(uint32_t config_mask)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       assert(ktrace_single_threaded == true);
+
+       if (ktrace_owner_kernel) {
+               ktrace_active_mask |= config_mask;
+               return;
+       }
 
        if (ktrace_state != KTRACE_STATE_OFF) {
-               if (ktrace_active_mask & KTRACE_KPERF) {
+               if (ktrace_active_mask & config_mask & KTRACE_KPERF) {
                        kperf_reset();
                }
-               if (ktrace_active_mask & KTRACE_KDEBUG) {
+               if (ktrace_active_mask & config_mask & KTRACE_KDEBUG) {
                        kdebug_reset();
                }
        }
 
-       ktrace_active_mask = config_mask;
+       ktrace_owner_kernel = true;
+       ktrace_active_mask |= config_mask;
        ktrace_state = KTRACE_STATE_FG;
 
        ktrace_release_ownership();
@@ -328,7 +378,7 @@ ktrace_init_background(void)
 {
        int err = 0;
 
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        if ((err = priv_check_cred(kauth_cred_get(), PRIV_KTRACE_BACKGROUND, 0))) {
                return err;
@@ -350,7 +400,7 @@ ktrace_init_background(void)
                                return EINVAL;
                        }
                }
-               should_notify_on_init = FALSE;
+               should_notify_on_init = false;
        }
 
        proc_t p = current_proc();
@@ -369,7 +419,7 @@ void
 ktrace_set_invalid_owning_pid(void)
 {
        if (ktrace_keep_ownership_on_reset) {
-               ktrace_keep_ownership_on_reset = FALSE;
+               ktrace_keep_ownership_on_reset = false;
                ktrace_reset_internal(ktrace_active_mask);
        }
 }
@@ -377,7 +427,7 @@ ktrace_set_invalid_owning_pid(void)
 int
 ktrace_set_owning_pid(int pid)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
+       ktrace_assert_lock_held();
 
        /* allow user space to successfully unset owning pid */
        if (pid == -1) {
@@ -397,7 +447,7 @@ ktrace_set_owning_pid(int pid)
                return ESRCH;
        }
 
-       ktrace_keep_ownership_on_reset = TRUE;
+       ktrace_keep_ownership_on_reset = true;
        ktrace_set_owning_proc(p);
 
        proc_rele(p);
@@ -407,8 +457,8 @@ ktrace_set_owning_pid(int pid)
 static void
 ktrace_set_owning_proc(proc_t p)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
-       assert(p);
+       ktrace_assert_lock_held();
+       assert(p != NULL);
 
        if (ktrace_state != KTRACE_STATE_FG) {
                if (proc_uniqueid(p) == ktrace_bg_unique_id) {
@@ -425,10 +475,11 @@ ktrace_set_owning_proc(proc_t p)
                                ktrace_active_mask = 0;
                        }
                        ktrace_state = KTRACE_STATE_FG;
-                       should_notify_on_init = FALSE;
+                       should_notify_on_init = false;
                }
        }
 
+       ktrace_owner_kernel = false;
        ktrace_owning_unique_id = proc_uniqueid(p);
        ktrace_owning_pid = proc_pid(p);
        strlcpy(ktrace_last_owner_execname, proc_name_address(p),
@@ -438,8 +489,6 @@ ktrace_set_owning_proc(proc_t p)
 static void
 ktrace_release_ownership(void)
 {
-       lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
-
        ktrace_owning_unique_id = 0;
        ktrace_owning_pid = 0;
 }
@@ -477,7 +526,7 @@ ktrace_sysctl SYSCTL_HANDLER_ARGS
        int ret = 0;
        uintptr_t type = (uintptr_t)arg1;
 
-       lck_mtx_lock(ktrace_lock);
+       ktrace_lock();
 
        if (!kauth_cred_issuser(kauth_cred_get())) {
                ret = EPERM;
@@ -498,7 +547,7 @@ ktrace_sysctl SYSCTL_HANDLER_ARGS
        }
 
 out:
-       lck_mtx_unlock(ktrace_lock);
+       ktrace_unlock();
        return ret;
 }
 
@@ -508,7 +557,7 @@ ktrace_init(void)
 {
        static lck_grp_attr_t *lock_grp_attr = NULL;
        static lck_grp_t *lock_grp = NULL;
-       static boolean_t initialized = FALSE;
+       static bool initialized = false;
 
        if (initialized) {
                return;
@@ -518,7 +567,7 @@ ktrace_init(void)
        lock_grp = lck_grp_alloc_init("ktrace", lock_grp_attr);
        lck_grp_attr_free(lock_grp_attr);
 
-       ktrace_lock = lck_mtx_alloc_init(lock_grp, LCK_ATTR_NULL);
-       assert(ktrace_lock);
-       initialized = TRUE;
+       ktrace_mtx = lck_mtx_alloc_init(lock_grp, LCK_ATTR_NULL);
+       assert(ktrace_mtx != NULL);;
+       initialized = true;
 }