/*
- * Copyright (c) 2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2015-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
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,
*
* 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);
* 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);
*/
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)
{
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;
}
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) {
static void
ktrace_promote_background(void)
{
- lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
assert(ktrace_state != KTRACE_STATE_BG);
/*
* 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();
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)
{
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) {
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();
return EPERM;
}
+ ktrace_owner_kernel = false;
ktrace_set_owning_proc(p);
ktrace_active_mask |= config_mask;
return 0;
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;
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();
{
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;
return EINVAL;
}
}
- should_notify_on_init = FALSE;
+ should_notify_on_init = false;
}
proc_t p = current_proc();
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);
}
}
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) {
return ESRCH;
}
- ktrace_keep_ownership_on_reset = TRUE;
+ ktrace_keep_ownership_on_reset = true;
ktrace_set_owning_proc(p);
proc_rele(p);
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) {
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),
static void
ktrace_release_ownership(void)
{
- lck_mtx_assert(ktrace_lock, LCK_MTX_ASSERT_OWNED);
-
ktrace_owning_unique_id = 0;
ktrace_owning_pid = 0;
}
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;
}
out:
- lck_mtx_unlock(ktrace_lock);
+ ktrace_unlock();
return ret;
}
{
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;
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;
}