xref: /xnu-10002.61.3/bsd/kern/kern_ktrace.c (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1 /*
2  * Copyright (c) 2015-2017 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * This file manages the ownership of ktrace and its subsystems, like kdebug
31  * and kperf, as well as the overall state of the system, whether it is in
32  * foreground or background mode.
33  *
34  * When unconfigured or in background mode, any root process can take ownership
35  * of ktrace and configure it, changing the state to foreground and, in the case
36  * of a transition out of background, resetting the background configuration.
37  *
38  * When in foreground mode, if the owning process is still running, only it may
39  * configure ktrace.  If it exits, ktrace keeps running but any root process can
40  * change the configuration.  When ktrace is reset, the state changes back to
41  * unconfigured and a notification is sent on the ktrace_background host special
42  * port.
43  *
44  * If a process has set itself as the background tool, using the init_background
45  * sysctl, it can configure ktrace only when ktrace is off or already in
46  * background mode.  The first attempt to configure ktrace by the background pid
47  * when it is off results in the transition to background mode.
48  */
49 
50 #include <sys/ktrace.h>
51 
52 #include <mach/host_priv.h>
53 #include <mach/mach_types.h>
54 #include <mach/ktrace_background.h>
55 
56 #include <sys/kauth.h>
57 #include <sys/priv.h>
58 #include <sys/proc.h>
59 char *proc_name_address(void *p);
60 #include <sys/sysctl.h>
61 #include <sys/vm.h>
62 #include <os/log.h>
63 #include <IOKit/IOBSD.h>
64 
65 #include <kern/locks.h>
66 #include <kern/assert.h>
67 
68 #include <sys/kdebug.h>
69 #include <kperf/kperf.h>
70 
71 #include <kern/host.h>
72 
73 #define KTRACE_ALLOW_ENTITLEMENT "com.apple.private.ktrace-allow"
74 
75 kern_return_t ktrace_background_available_notify_user(void);
76 
77 static LCK_GRP_DECLARE(ktrace_grp, "ktrace");
78 static LCK_MTX_DECLARE(ktrace_mtx, &ktrace_grp);
79 
80 /*
81  * The overall state of ktrace, whether it is unconfigured, in foreground mode,
82  * or in background mode.  The state determines which processes can configure
83  * ktrace.
84  */
85 static ktrace_state_t ktrace_state = KTRACE_STATE_OFF;
86 
87 /* The true owner of ktrace, checked by ktrace_access_check(). */
88 static uint64_t ktrace_owning_unique_id = 0;
89 static pid_t ktrace_owning_pid = 0;
90 
91 /*
92  * The background pid of ktrace, automatically made the owner when
93  * transitioning to background mode.
94  */
95 static uint64_t ktrace_bg_unique_id = 0;
96 static pid_t ktrace_bg_pid = 0;
97 
98 /* The name of the last process to configure ktrace. */
99 static char ktrace_last_owner_execname[MAXCOMLEN + 1] = { 0 };
100 
101 /*
102  * Which subsystems of ktrace (currently kdebug and kperf) are active.
103  */
104 static uint32_t ktrace_active_mask = 0;
105 
106 /*
107  * At boot or when a daemon has been newly loaded, it's necessary to bootstrap
108  * user space background tools by sending a background available notification
109  * when the init_background sysctl is made.
110  *
111  * Background tools must be RunAtLoad daemons.
112  */
113 static bool should_notify_on_init = true;
114 
115 /* Set the owning process of ktrace. */
116 static void ktrace_set_owning_proc(proc_t p);
117 
118 /* Reset ktrace ownership back to unowned. */
119 static void ktrace_release_ownership(void);
120 
121 /* Make the background tool the owner of ktrace. */
122 static void ktrace_promote_background(void);
123 
124 /*
125  * If user space sets a pid manually (through kperf "blessing"), ktrace should
126  * not treat resets as releasing ownership.  At that point, ownership is only
127  * released when the owner is set to an invalid pid.
128  *
129  * This is managed by the user space-oriented function ktrace_set_owning_pid
130  * and ktrace_unset_owning_pid.
131  */
132 bool ktrace_keep_ownership_on_reset = false;
133 
134 /* Whether the kernel is the owner of ktrace. */
135 bool ktrace_owner_kernel = false;
136 
137 /* Allow user space to unset the owning pid and potentially reset ktrace. */
138 static void ktrace_set_invalid_owning_pid(void);
139 
140 /*
141  * This flag allows any root process to set a new ktrace owner.  It is
142  * currently used by Instruments.
143  */
144 int ktrace_root_set_owner_allowed = 0;
145 
146 /*
147  * If ktrace is guaranteed that it's the only thread running on the system
148  * (e.g., during boot or wake) this flag disables locking requirements.
149  */
150 static bool ktrace_single_threaded = false;
151 
152 __startup_func
153 static void
ktrace_startup(void)154 ktrace_startup(void)
155 {
156 	extern void kpc_init(void);
157 #if KPC
158 	kpc_init();
159 #endif /* KPC */
160 #if KPERF
161 	kperf_init();
162 #endif /* KPERF */
163 	kdebug_startup();
164 }
165 STARTUP(KTRACE, STARTUP_RANK_FIRST, ktrace_startup);
166 
167 void
ktrace_lock(void)168 ktrace_lock(void)
169 {
170 	if (!ktrace_single_threaded) {
171 		lck_mtx_lock(&ktrace_mtx);
172 	}
173 }
174 
175 void
ktrace_unlock(void)176 ktrace_unlock(void)
177 {
178 	if (!ktrace_single_threaded) {
179 		lck_mtx_unlock(&ktrace_mtx);
180 	}
181 }
182 
183 void
ktrace_assert_lock_held(void)184 ktrace_assert_lock_held(void)
185 {
186 	if (!ktrace_single_threaded) {
187 		lck_mtx_assert(&ktrace_mtx, LCK_MTX_ASSERT_OWNED);
188 	}
189 }
190 
191 void
ktrace_start_single_threaded(void)192 ktrace_start_single_threaded(void)
193 {
194 	ktrace_single_threaded = true;
195 }
196 
197 void
ktrace_end_single_threaded(void)198 ktrace_end_single_threaded(void)
199 {
200 	ktrace_single_threaded = false;
201 }
202 
203 static void
ktrace_reset_internal(uint32_t reset_mask)204 ktrace_reset_internal(uint32_t reset_mask)
205 {
206 	if (!ktrace_keep_ownership_on_reset) {
207 		ktrace_active_mask &= ~reset_mask;
208 	}
209 
210 	if (reset_mask & KTRACE_KPERF) {
211 		kperf_reset();
212 	}
213 	if (reset_mask & KTRACE_KDEBUG) {
214 		kdebug_reset();
215 	}
216 
217 	if (ktrace_active_mask == 0) {
218 		if (ktrace_state == KTRACE_STATE_FG) {
219 			/* transition from foreground to background */
220 			ktrace_promote_background();
221 		} else if (ktrace_state == KTRACE_STATE_BG) {
222 			/* background tool is resetting ktrace */
223 			should_notify_on_init = true;
224 			ktrace_release_ownership();
225 			ktrace_state = KTRACE_STATE_OFF;
226 		}
227 	}
228 }
229 
230 void
ktrace_reset(uint32_t reset_mask)231 ktrace_reset(uint32_t reset_mask)
232 {
233 	ktrace_assert_lock_held();
234 
235 	if (ktrace_active_mask == 0) {
236 		if (!ktrace_keep_ownership_on_reset) {
237 			assert(ktrace_state == KTRACE_STATE_OFF);
238 		}
239 		return;
240 	}
241 
242 	ktrace_reset_internal(reset_mask);
243 }
244 
245 static void
ktrace_promote_background(void)246 ktrace_promote_background(void)
247 {
248 	assert(ktrace_state != KTRACE_STATE_BG);
249 
250 	os_log(OS_LOG_DEFAULT, "ktrace: promoting background tool");
251 
252 	/*
253 	 * Remember to send a background available notification on the next init
254 	 * if the notification failed (meaning no task holds the receive right
255 	 * for the host special port).
256 	 */
257 	if (ktrace_background_available_notify_user() == KERN_FAILURE) {
258 		should_notify_on_init = true;
259 	} else {
260 		should_notify_on_init = false;
261 	}
262 
263 	ktrace_release_ownership();
264 	ktrace_state = KTRACE_STATE_OFF;
265 }
266 
267 bool
ktrace_background_active(void)268 ktrace_background_active(void)
269 {
270 	return ktrace_state == KTRACE_STATE_BG;
271 }
272 
273 static bool
_current_task_can_own_ktrace(void)274 _current_task_can_own_ktrace(void)
275 {
276 	bool allow_non_superuser = false;
277 	bool is_superuser = kauth_cred_issuser(kauth_cred_get());
278 
279 #if DEVELOPMENT || DEBUG
280 	allow_non_superuser = IOTaskHasEntitlement(current_task(),
281 	    KTRACE_ALLOW_ENTITLEMENT);
282 #endif /* DEVELOPMENT || DEBUG */
283 
284 	return is_superuser || allow_non_superuser;
285 }
286 
287 int
ktrace_read_check(void)288 ktrace_read_check(void)
289 {
290 	ktrace_assert_lock_held();
291 
292 	if (proc_uniqueid(current_proc()) == ktrace_owning_unique_id) {
293 		return 0;
294 	}
295 
296 	return _current_task_can_own_ktrace() ? 0 : EPERM;
297 }
298 
299 /* If an owning process has exited, reset the ownership. */
300 static void
ktrace_ownership_maintenance(void)301 ktrace_ownership_maintenance(void)
302 {
303 	ktrace_assert_lock_held();
304 
305 	/* do nothing if ktrace is not owned */
306 	if (ktrace_owning_unique_id == 0) {
307 		return;
308 	}
309 
310 	/* reset ownership if process cannot be found */
311 
312 	proc_t owning_proc = proc_find(ktrace_owning_pid);
313 
314 	if (owning_proc != NULL) {
315 		/* make sure the pid was not recycled */
316 		if (proc_uniqueid(owning_proc) != ktrace_owning_unique_id) {
317 			ktrace_release_ownership();
318 		}
319 
320 		proc_rele(owning_proc);
321 	} else {
322 		ktrace_release_ownership();
323 	}
324 }
325 
326 int
ktrace_configure(uint32_t config_mask)327 ktrace_configure(uint32_t config_mask)
328 {
329 	ktrace_assert_lock_held();
330 	assert(config_mask != 0);
331 
332 	proc_t p = current_proc();
333 
334 	/* if process clearly owns ktrace, allow */
335 	if (proc_uniqueid(p) == ktrace_owning_unique_id) {
336 		ktrace_active_mask |= config_mask;
337 		return 0;
338 	}
339 
340 	/* background configure while foreground is active is not allowed */
341 	if (proc_uniqueid(p) == ktrace_bg_unique_id &&
342 	    ktrace_state == KTRACE_STATE_FG) {
343 		return EBUSY;
344 	}
345 
346 	ktrace_ownership_maintenance();
347 
348 	/* allow process to gain control when unowned or background */
349 	if (ktrace_owning_unique_id == 0 || ktrace_state == KTRACE_STATE_BG) {
350 		if (!_current_task_can_own_ktrace()) {
351 			return EPERM;
352 		}
353 
354 		ktrace_owner_kernel = false;
355 		ktrace_set_owning_proc(p);
356 		ktrace_active_mask |= config_mask;
357 		return 0;
358 	}
359 
360 	/* owned by an existing, different process */
361 	return EBUSY;
362 }
363 
364 void
ktrace_disable(ktrace_state_t state_to_match)365 ktrace_disable(ktrace_state_t state_to_match)
366 {
367 	if (ktrace_state == state_to_match) {
368 		kernel_debug_disable();
369 		kperf_disable_sampling();
370 	}
371 }
372 
373 int
ktrace_get_owning_pid(void)374 ktrace_get_owning_pid(void)
375 {
376 	ktrace_assert_lock_held();
377 
378 	ktrace_ownership_maintenance();
379 	return ktrace_owning_pid;
380 }
381 
382 void
ktrace_kernel_configure(uint32_t config_mask)383 ktrace_kernel_configure(uint32_t config_mask)
384 {
385 	assert(ktrace_single_threaded == true);
386 
387 	if (ktrace_owner_kernel) {
388 		ktrace_active_mask |= config_mask;
389 		return;
390 	}
391 
392 	if (ktrace_state != KTRACE_STATE_OFF) {
393 		if (ktrace_active_mask & config_mask & KTRACE_KPERF) {
394 			kperf_reset();
395 		}
396 		if (ktrace_active_mask & config_mask & KTRACE_KDEBUG) {
397 			kdebug_reset();
398 		}
399 	}
400 
401 	ktrace_owner_kernel = true;
402 	ktrace_active_mask |= config_mask;
403 	ktrace_state = KTRACE_STATE_FG;
404 
405 	ktrace_release_ownership();
406 	strlcpy(ktrace_last_owner_execname, "kernel_task",
407 	    sizeof(ktrace_last_owner_execname));
408 }
409 
410 static errno_t
ktrace_init_background(void)411 ktrace_init_background(void)
412 {
413 	int err = 0;
414 
415 	ktrace_assert_lock_held();
416 
417 	if ((err = priv_check_cred(kauth_cred_get(), PRIV_KTRACE_BACKGROUND, 0))) {
418 		return err;
419 	}
420 
421 	/*
422 	 * When a background tool first checks in, send a notification if ktrace
423 	 * is available.
424 	 */
425 	if (should_notify_on_init) {
426 		if (ktrace_state == KTRACE_STATE_OFF) {
427 			/*
428 			 * This notification can only fail if a process does not
429 			 * hold the receive right for the host special port.
430 			 * Return an error and don't make the current process
431 			 * the background tool.
432 			 */
433 			if (ktrace_background_available_notify_user() == KERN_FAILURE) {
434 				return EINVAL;
435 			}
436 		}
437 		should_notify_on_init = false;
438 	}
439 
440 	proc_t p = current_proc();
441 
442 	ktrace_bg_unique_id = proc_uniqueid(p);
443 	ktrace_bg_pid = proc_pid(p);
444 
445 	if (ktrace_state == KTRACE_STATE_BG) {
446 		ktrace_set_owning_proc(p);
447 	}
448 
449 	return 0;
450 }
451 
452 void
ktrace_set_invalid_owning_pid(void)453 ktrace_set_invalid_owning_pid(void)
454 {
455 	os_log(OS_LOG_DEFAULT, "ktrace: manually invalidating owning process");
456 	if (ktrace_keep_ownership_on_reset) {
457 		ktrace_keep_ownership_on_reset = false;
458 		ktrace_reset_internal(ktrace_active_mask);
459 	}
460 }
461 
462 int
ktrace_set_owning_pid(int pid)463 ktrace_set_owning_pid(int pid)
464 {
465 	ktrace_assert_lock_held();
466 
467 	/* allow user space to successfully unset owning pid */
468 	if (pid == -1) {
469 		ktrace_set_invalid_owning_pid();
470 		return 0;
471 	}
472 
473 	/* use ktrace_reset or ktrace_release_ownership, not this */
474 	if (pid == 0) {
475 		ktrace_set_invalid_owning_pid();
476 		return EINVAL;
477 	}
478 
479 	proc_t p = proc_find(pid);
480 	if (!p) {
481 		ktrace_set_invalid_owning_pid();
482 		return ESRCH;
483 	}
484 
485 	ktrace_keep_ownership_on_reset = true;
486 	os_log(OS_LOG_DEFAULT, "ktrace: manually setting owning process");
487 	ktrace_set_owning_proc(p);
488 
489 	proc_rele(p);
490 	return 0;
491 }
492 
493 static void
ktrace_set_owning_proc(proc_t p)494 ktrace_set_owning_proc(proc_t p)
495 {
496 	ktrace_assert_lock_held();
497 	assert(p != NULL);
498 	ktrace_state_t old_state = ktrace_state;
499 
500 	if (ktrace_state != KTRACE_STATE_FG) {
501 		if (proc_uniqueid(p) == ktrace_bg_unique_id) {
502 			ktrace_state = KTRACE_STATE_BG;
503 		} else {
504 			if (ktrace_state == KTRACE_STATE_BG) {
505 				if (ktrace_active_mask & KTRACE_KPERF) {
506 					kperf_reset();
507 				}
508 				if (ktrace_active_mask & KTRACE_KDEBUG) {
509 					kdebug_reset();
510 				}
511 
512 				ktrace_active_mask = 0;
513 			}
514 			ktrace_state = KTRACE_STATE_FG;
515 			should_notify_on_init = false;
516 		}
517 	}
518 
519 	ktrace_owner_kernel = false;
520 	ktrace_owning_unique_id = proc_uniqueid(p);
521 	ktrace_owning_pid = proc_pid(p);
522 	strlcpy(ktrace_last_owner_execname, proc_name_address(p),
523 	    sizeof(ktrace_last_owner_execname));
524 	os_log(OS_LOG_DEFAULT, "ktrace: changing state from %d to %d, owned by "
525 	    "%s[%d]", old_state, ktrace_state, ktrace_last_owner_execname,
526 	    ktrace_owning_pid);
527 }
528 
529 static void
ktrace_release_ownership(void)530 ktrace_release_ownership(void)
531 {
532 	ktrace_owning_unique_id = 0;
533 	ktrace_owning_pid = 0;
534 }
535 
536 #define SYSCTL_INIT_BACKGROUND (1)
537 
538 static int ktrace_sysctl SYSCTL_HANDLER_ARGS;
539 
540 SYSCTL_NODE(, OID_AUTO, ktrace, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "ktrace");
541 
542 SYSCTL_UINT(_ktrace, OID_AUTO, state, CTLFLAG_RD | CTLFLAG_LOCKED,
543     &ktrace_state, 0,
544     "");
545 
546 SYSCTL_UINT(_ktrace, OID_AUTO, active_mask, CTLFLAG_RD | CTLFLAG_LOCKED,
547     &ktrace_active_mask, 0,
548     "");
549 
550 SYSCTL_INT(_ktrace, OID_AUTO, owning_pid, CTLFLAG_RD | CTLFLAG_LOCKED,
551     &ktrace_owning_pid, 0,
552     "pid of the process that owns ktrace");
553 
554 SYSCTL_INT(_ktrace, OID_AUTO, background_pid, CTLFLAG_RD | CTLFLAG_LOCKED,
555     &ktrace_bg_pid, 0,
556     "pid of the background ktrace tool");
557 
558 SYSCTL_STRING(_ktrace, OID_AUTO, configured_by, CTLFLAG_RD | CTLFLAG_LOCKED,
559     ktrace_last_owner_execname, 0,
560     "execname of process that last configured ktrace");
561 
562 SYSCTL_PROC(_ktrace, OID_AUTO, init_background, CTLFLAG_RW | CTLFLAG_LOCKED,
563     (void *)SYSCTL_INIT_BACKGROUND, sizeof(int),
564     ktrace_sysctl, "I", "initialize calling process as background");
565 
566 static int
567 ktrace_sysctl SYSCTL_HANDLER_ARGS
568 {
569 #pragma unused(oidp, arg2)
570 	int ret = 0;
571 	uintptr_t type = (uintptr_t)arg1;
572 
573 	ktrace_lock();
574 
575 	if (!kauth_cred_issuser(kauth_cred_get())) {
576 		ret = EPERM;
577 		goto out;
578 	}
579 
580 	if (type == SYSCTL_INIT_BACKGROUND) {
581 		if (req->newptr != USER_ADDR_NULL) {
582 			ret = ktrace_init_background();
583 			goto out;
584 		} else {
585 			ret = EINVAL;
586 			goto out;
587 		}
588 	} else {
589 		ret = EINVAL;
590 		goto out;
591 	}
592 
593 out:
594 	ktrace_unlock();
595 	return ret;
596 }
597