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