1 // Copyright (c) 2016-2021 Apple Inc. All rights reserved.
2 //
3 // @APPLE_OSREFERENCE_LICENSE_HEADER_START@
4 //
5 // This file contains Original Code and/or Modifications of Original Code
6 // as defined in and that are subject to the Apple Public Source License
7 // Version 2.0 (the 'License'). You may not use this file except in
8 // compliance with the License. The rights granted to you under the License
9 // may not be used to create, or enable the creation or redistribution of,
10 // unlawful or unlicensed copies of an Apple operating system, or to
11 // circumvent, violate, or enable the circumvention or violation of, any
12 // terms of an Apple operating system software license agreement.
13 //
14 // Please obtain a copy of the License at
15 // http://www.opensource.apple.com/apsl/ and read it before using this file.
16 //
17 // The Original Code and all software distributed under the License are
18 // distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19 // EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
20 // INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
22 // Please see the License for the specific language governing rights and
23 // limitations under the License.
24 //
25 // @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26
27 #include <stddef.h>
28 #include <stdint.h>
29
30 #include <kern/assert.h>
31 #include <kern/backtrace.h>
32 #include <kern/cambria_layout.h>
33 #include <kern/thread.h>
34 #include <machine/machine_routines.h>
35 #include <sys/errno.h>
36 #include <vm/vm_map.h>
37
38 #if defined(__arm64__)
39 #include <arm/cpu_data.h>
40 #include <arm/cpu_data_internal.h>
41 #endif // defined(__arm64__)
42
43 #if defined(HAS_APPLE_PAC)
44 #include <ptrauth.h>
45 #endif // defined(HAS_APPLE_PAC)
46
47 #if __x86_64__
48 static void
_backtrace_packed_out_of_reach(void)49 _backtrace_packed_out_of_reach(void)
50 {
51 /*
52 * This symbol is used to replace frames that have been "JIT-ed"
53 * or dynamically inserted in the kernel by some kext in a regular
54 * VM mapping that might be outside of the filesets.
55 *
56 * This is an Intel only issue.
57 */
58 }
59 #endif
60
61 // Pack an address according to a particular packing format.
62 static size_t
_backtrace_pack_addr(backtrace_pack_t packing,uint8_t * dst,size_t dst_size,uintptr_t addr)63 _backtrace_pack_addr(backtrace_pack_t packing, uint8_t *dst, size_t dst_size,
64 uintptr_t addr)
65 {
66 switch (packing) {
67 case BTP_NONE:
68 if (dst_size >= sizeof(addr)) {
69 memcpy(dst, &addr, sizeof(addr));
70 }
71 return sizeof(addr);
72 case BTP_KERN_OFFSET_32:;
73 uintptr_t addr_delta = addr - vm_kernel_stext;
74 int32_t addr_packed = (int32_t)addr_delta;
75 #if __x86_64__
76 if ((uintptr_t)(int32_t)addr_delta != addr_delta) {
77 addr = (vm_offset_t)&_backtrace_packed_out_of_reach;
78 addr_delta = addr - vm_kernel_stext;
79 addr_packed = (int32_t)addr_delta;
80 }
81 #else
82 assert((uintptr_t)(int32_t)addr_delta == addr_delta);
83 #endif
84 if (dst_size >= sizeof(addr_packed)) {
85 memcpy(dst, &addr_packed, sizeof(addr_packed));
86 }
87 return sizeof(addr_packed);
88 default:
89 panic("backtrace: unknown packing format %d", packing);
90 }
91 }
92
93 // Since it's only called from threads that we're going to keep executing,
94 // if there's bad data the system is going to die eventually. If this function
95 // is inlined, it doesn't record the frame of the function it's inside (because
96 // there's no stack frame), so prevent that.
97 static size_t __attribute__((noinline, not_tail_called))
backtrace_internal(backtrace_pack_t packing,uint8_t * bt,size_t btsize,void * start_frame,int64_t addr_offset,backtrace_info_t * info_out)98 backtrace_internal(backtrace_pack_t packing, uint8_t *bt,
99 size_t btsize, void *start_frame, int64_t addr_offset,
100 backtrace_info_t *info_out)
101 {
102 thread_t thread = current_thread();
103 uintptr_t *fp;
104 size_t size_used = 0;
105 uintptr_t top, bottom;
106 bool in_valid_stack;
107 assert(bt != NULL);
108 assert(btsize > 0);
109
110 fp = start_frame;
111 bottom = thread->kernel_stack;
112 top = bottom + kernel_stack_size;
113
114 #define IN_STK_BOUNDS(__addr) \
115 (((uintptr_t)(__addr) >= (uintptr_t)bottom) && \
116 ((uintptr_t)(__addr) < (uintptr_t)top))
117
118 in_valid_stack = IN_STK_BOUNDS(fp) || ml_addr_in_non_xnu_stack((uintptr_t)fp);
119
120 if (!in_valid_stack) {
121 fp = NULL;
122 }
123
124 while (fp != NULL && size_used < btsize) {
125 uintptr_t *next_fp = (uintptr_t *)*fp;
126 // Return address is one word higher than frame pointer.
127 uintptr_t ret_addr = *(fp + 1);
128
129 // If the frame pointer is 0, backtracing has reached the top of
130 // the stack and there is no return address. Some stacks might not
131 // have set this up, so bounds check, as well.
132 in_valid_stack = IN_STK_BOUNDS(next_fp) || ml_addr_in_non_xnu_stack((uintptr_t)next_fp);
133
134 if (next_fp == NULL || !in_valid_stack) {
135 break;
136 }
137
138 #if defined(HAS_APPLE_PAC)
139 // Return addresses are signed by arm64e ABI, so strip it.
140 uintptr_t pc = (uintptr_t)ptrauth_strip((void *)ret_addr,
141 ptrauth_key_return_address);
142 #else // defined(HAS_APPLE_PAC)
143 uintptr_t pc = ret_addr;
144 #endif // !defined(HAS_APPLE_PAC)
145 pc += addr_offset;
146 size_used += _backtrace_pack_addr(packing, bt + size_used,
147 btsize - size_used, pc);
148
149 // Stacks grow down; backtracing should always be moving to higher
150 // addresses except when a frame is stitching between two different
151 // stacks.
152 if (next_fp <= fp) {
153 // This check is verbose; it is basically checking whether this
154 // thread is switching between the kernel stack and a non-XNU stack
155 // (or between one non-XNU stack and another, as there can be more
156 // than one). If not, then stop the backtrace as stack switching
157 // should be the only reason as to why the next FP would be lower
158 // than the current FP.
159 if (!ml_addr_in_non_xnu_stack((uintptr_t)fp) &&
160 !ml_addr_in_non_xnu_stack((uintptr_t)next_fp)) {
161 break;
162 }
163 }
164 fp = next_fp;
165 }
166
167 if (info_out) {
168 backtrace_info_t info = BTI_NONE;
169 #if __LP64__
170 info |= BTI_64_BIT;
171 #endif
172 if (fp != NULL && size_used >= btsize) {
173 info |= BTI_TRUNCATED;
174 }
175 *info_out = info;
176 }
177
178 return size_used;
179 #undef IN_STK_BOUNDS
180 }
181
182 static kern_return_t
interrupted_kernel_pc_fp(uintptr_t * pc,uintptr_t * fp)183 interrupted_kernel_pc_fp(uintptr_t *pc, uintptr_t *fp)
184 {
185 #if defined(__x86_64__)
186 x86_saved_state_t *state;
187 bool state_64;
188 uint64_t cs;
189
190 state = current_cpu_datap()->cpu_int_state;
191 if (!state) {
192 return KERN_FAILURE;
193 }
194
195 state_64 = is_saved_state64(state);
196
197 if (state_64) {
198 cs = saved_state64(state)->isf.cs;
199 } else {
200 cs = saved_state32(state)->cs;
201 }
202 // Return early if interrupted a thread in user space.
203 if ((cs & SEL_PL) == SEL_PL_U) {
204 return KERN_FAILURE;
205 }
206
207 if (state_64) {
208 *pc = saved_state64(state)->isf.rip;
209 *fp = saved_state64(state)->rbp;
210 } else {
211 *pc = saved_state32(state)->eip;
212 *fp = saved_state32(state)->ebp;
213 }
214
215 #elif defined(__arm64__)
216
217 struct arm_saved_state *state;
218
219 state = getCpuDatap()->cpu_int_state;
220 if (!state) {
221 return KERN_FAILURE;
222 }
223
224 // Return early if interrupted a thread in user space.
225 if (PSR64_IS_USER(get_saved_state_cpsr(state))) {
226 return KERN_FAILURE;
227 }
228
229 *pc = ml_get_backtrace_pc(state);
230 *fp = get_saved_state_fp(state);
231
232 #else // !defined(__arm64__) && !defined(__x86_64__)
233 #error "unsupported architecture"
234 #endif // !defined(__arm64__) && !defined(__x86_64__)
235
236 return KERN_SUCCESS;
237 }
238
239 __attribute__((always_inline))
240 static uintptr_t
_backtrace_preamble(struct backtrace_control * ctl,uintptr_t * start_frame_out)241 _backtrace_preamble(struct backtrace_control *ctl, uintptr_t *start_frame_out)
242 {
243 backtrace_flags_t flags = ctl ? ctl->btc_flags : 0;
244 uintptr_t start_frame = ctl ? ctl->btc_frame_addr : 0;
245 uintptr_t pc = 0;
246 if (flags & BTF_KERN_INTERRUPTED) {
247 assert(ml_at_interrupt_context() == TRUE);
248
249 uintptr_t fp;
250 kern_return_t kr = interrupted_kernel_pc_fp(&pc, &fp);
251 if (kr != KERN_SUCCESS) {
252 return 0;
253 }
254 *start_frame_out = start_frame ?: fp;
255 } else if (start_frame == 0) {
256 *start_frame_out = (uintptr_t)__builtin_frame_address(0);
257 } else {
258 *start_frame_out = start_frame;
259 }
260 return pc;
261 }
262
263 unsigned int __attribute__((noinline))
backtrace(uintptr_t * bt,unsigned int max_frames,struct backtrace_control * ctl,backtrace_info_t * info_out)264 backtrace(uintptr_t *bt, unsigned int max_frames,
265 struct backtrace_control *ctl, backtrace_info_t *info_out)
266 {
267 unsigned int len_adj = 0;
268 uintptr_t start_frame = ctl ? ctl->btc_frame_addr : 0;
269 uintptr_t pc = _backtrace_preamble(ctl, &start_frame);
270 if (pc) {
271 bt[0] = pc;
272 if (max_frames == 1) {
273 return 1;
274 }
275 bt += 1;
276 max_frames -= 1;
277 len_adj += 1;
278 }
279
280 size_t size = backtrace_internal(BTP_NONE, (uint8_t *)bt,
281 max_frames * sizeof(uintptr_t), (void *)start_frame,
282 ctl ? ctl->btc_addr_offset : 0, info_out);
283 // NULL-terminate the list, if space is available.
284 unsigned int len = size / sizeof(uintptr_t);
285 if (len != max_frames) {
286 bt[len] = 0;
287 }
288
289 return len + len_adj;
290 }
291
292 // Backtrace the current thread's kernel stack as a packed representation.
293 size_t
backtrace_packed(backtrace_pack_t packing,uint8_t * bt,size_t btsize,struct backtrace_control * ctl,backtrace_info_t * info_out)294 backtrace_packed(backtrace_pack_t packing, uint8_t *bt, size_t btsize,
295 struct backtrace_control *ctl,
296 backtrace_info_t *info_out)
297 {
298 unsigned int size_adj = 0;
299 uintptr_t start_frame = ctl ? ctl->btc_frame_addr : 0;
300 uintptr_t pc = _backtrace_preamble(ctl, &start_frame);
301 if (pc) {
302 size_adj = _backtrace_pack_addr(packing, bt, btsize, pc);
303 if (size_adj >= btsize) {
304 return size_adj;
305 }
306 btsize -= size_adj;
307 }
308
309 size_t written_size = backtrace_internal(packing, (uint8_t *)bt, btsize,
310 (void *)start_frame, ctl ? ctl->btc_addr_offset : 0, info_out);
311 return written_size + size_adj;
312 }
313
314 // Convert an array of addresses to a packed representation.
315 size_t
backtrace_pack(backtrace_pack_t packing,uint8_t * dst,size_t dst_size,const uintptr_t * src,unsigned int src_len)316 backtrace_pack(backtrace_pack_t packing, uint8_t *dst, size_t dst_size,
317 const uintptr_t *src, unsigned int src_len)
318 {
319 size_t dst_offset = 0;
320 for (unsigned int i = 0; i < src_len; i++) {
321 size_t pack_size = _backtrace_pack_addr(packing, dst + dst_offset,
322 dst_size - dst_offset, src[i]);
323 if (dst_offset + pack_size >= dst_size) {
324 return dst_offset;
325 }
326 dst_offset += pack_size;
327 }
328 return dst_offset;
329 }
330
331 // Convert a packed backtrace to an array of addresses.
332 unsigned int
backtrace_unpack(backtrace_pack_t packing,uintptr_t * dst,unsigned int dst_len,const uint8_t * src,size_t src_size)333 backtrace_unpack(backtrace_pack_t packing, uintptr_t *dst, unsigned int dst_len,
334 const uint8_t *src, size_t src_size)
335 {
336 switch (packing) {
337 case BTP_NONE:;
338 size_t unpack_size = MIN(dst_len * sizeof(uintptr_t), src_size);
339 memmove(dst, src, unpack_size);
340 return (unsigned int)(unpack_size / sizeof(uintptr_t));
341 case BTP_KERN_OFFSET_32:;
342 unsigned int src_len = src_size / sizeof(int32_t);
343 unsigned int unpack_len = MIN(src_len, dst_len);
344 for (unsigned int i = 0; i < unpack_len; i++) {
345 int32_t addr = 0;
346 memcpy(&addr, src + i * sizeof(int32_t), sizeof(int32_t));
347 dst[i] = vm_kernel_stext + (uintptr_t)addr;
348 }
349 return unpack_len;
350 default:
351 panic("backtrace: unknown packing format %d", packing);
352 }
353 }
354
355 static errno_t
_backtrace_copyin(void * __unused ctx,void * dst,user_addr_t src,size_t size)356 _backtrace_copyin(void * __unused ctx, void *dst, user_addr_t src, size_t size)
357 {
358 return copyin((user_addr_t)src, dst, size);
359 }
360
361 errno_t
backtrace_user_copy_error(void * ctx,void * dst,user_addr_t src,size_t size)362 backtrace_user_copy_error(void *ctx, void *dst, user_addr_t src, size_t size)
363 {
364 #pragma unused(ctx, dst, src, size)
365 return EFAULT;
366 }
367
368 unsigned int
backtrace_user(uintptr_t * bt,unsigned int max_frames,const struct backtrace_control * ctl_in,struct backtrace_user_info * info_out)369 backtrace_user(uintptr_t *bt, unsigned int max_frames,
370 const struct backtrace_control *ctl_in,
371 struct backtrace_user_info *info_out)
372 {
373 static const struct backtrace_control ctl_default = {
374 .btc_user_copy = _backtrace_copyin,
375 };
376 const struct backtrace_control *ctl = ctl_in ?: &ctl_default;
377 uintptr_t pc = 0, next_fp = 0;
378 uintptr_t fp = ctl->btc_frame_addr;
379 bool custom_fp = fp != 0;
380 int64_t addr_offset = ctl ? ctl->btc_addr_offset : 0;
381 vm_map_t map = NULL, old_map = NULL;
382 unsigned int frame_index = 0;
383 int error = 0;
384 size_t frame_size = 0;
385 bool truncated = false;
386 bool user_64 = false;
387 bool allow_async = true;
388 bool has_async = false;
389 uintptr_t async_frame_addr = 0;
390 unsigned int async_index = 0;
391
392 backtrace_user_copy_fn copy = ctl->btc_user_copy ?: _backtrace_copyin;
393 bool custom_copy = copy != _backtrace_copyin;
394 void *ctx = ctl->btc_user_copy_context;
395
396 void *thread = ctl->btc_user_thread;
397 void *cur_thread = NULL;
398 if (thread == NULL) {
399 cur_thread = current_thread();
400 thread = cur_thread;
401 }
402 task_t task = get_threadtask(thread);
403
404 assert(task != NULL);
405 assert(bt != NULL);
406 assert(max_frames > 0);
407
408 if (!custom_copy) {
409 assert(ml_get_interrupts_enabled() == TRUE);
410 if (!ml_get_interrupts_enabled()) {
411 error = EDEADLK;
412 }
413
414 if (cur_thread == NULL) {
415 cur_thread = current_thread();
416 }
417 if (thread != cur_thread) {
418 map = get_task_map_reference(task);
419 if (map == NULL) {
420 error = ENOMEM;
421 goto out;
422 }
423 old_map = vm_map_switch(map);
424 }
425 }
426
427 #define SWIFT_ASYNC_FP_BIT (0x1ULL << 60)
428 #define SWIFT_ASYNC_FP(FP) (((FP) & SWIFT_ASYNC_FP_BIT) != 0)
429 #define SWIFT_ASYNC_FP_CLEAR(FP) ((FP) & ~SWIFT_ASYNC_FP_BIT)
430
431 #if defined(__x86_64__)
432
433 // Don't allow a malformed user stack to copy arbitrary kernel data.
434 #define INVALID_USER_FP(FP) ((FP) == 0 || !IS_USERADDR64_CANONICAL((FP)))
435
436 x86_saved_state_t *state = get_user_regs(thread);
437 if (!state) {
438 error = EINVAL;
439 goto out;
440 }
441
442 user_64 = is_saved_state64(state);
443 if (user_64) {
444 pc = saved_state64(state)->isf.rip;
445 fp = fp != 0 ? fp : saved_state64(state)->rbp;
446 } else {
447 pc = saved_state32(state)->eip;
448 fp = fp != 0 ? fp : saved_state32(state)->ebp;
449 }
450
451 #elif defined(__arm64__)
452
453 struct arm_saved_state *state = get_user_regs(thread);
454 if (!state) {
455 error = EINVAL;
456 goto out;
457 }
458
459 user_64 = is_saved_state64(state);
460 pc = get_saved_state_pc(state);
461 fp = fp != 0 ? fp : get_saved_state_fp(state);
462
463 // ARM expects stack frames to be aligned to 16 bytes.
464 #define INVALID_USER_FP(FP) (((FP) & 0x3UL) != 0UL)
465
466 #else // defined(__arm64__) || defined(__x86_64__)
467 #error "unsupported architecture"
468 #endif // !defined(__arm64__) && !defined(__x86_64__)
469
470 // Only capture the save state PC without a custom frame pointer to walk.
471 if (!ctl || ctl->btc_frame_addr == 0) {
472 bt[frame_index++] = pc + addr_offset;
473 }
474
475 if (frame_index >= max_frames) {
476 goto out;
477 }
478
479 if (fp == 0) {
480 // If the FP is zeroed, then there's no stack to walk, by design. This
481 // happens for workq threads that are being sent back to user space or
482 // during boot-strapping operations on other kinds of threads.
483 goto out;
484 } else if (INVALID_USER_FP(fp)) {
485 // Still capture the PC in this case, but mark the stack as truncated
486 // and "faulting." (Using the frame pointer on a call stack would cause
487 // an exception.)
488 error = EFAULT;
489 truncated = true;
490 goto out;
491 }
492
493 union {
494 struct {
495 uint64_t fp;
496 uint64_t ret;
497 } u64;
498 struct {
499 uint32_t fp;
500 uint32_t ret;
501 } u32;
502 } frame;
503
504 frame_size = 2 * (user_64 ? 8 : 4);
505
506 while (fp != 0 && frame_index < max_frames) {
507 error = copy(ctx, (char *)&frame, fp, frame_size);
508 if (error) {
509 truncated = true;
510 goto out;
511 }
512
513 // Capture this return address before tripping over any errors finding
514 // the next frame to follow.
515 uintptr_t ret_addr = user_64 ? frame.u64.ret : frame.u32.ret;
516 #if defined(HAS_APPLE_PAC)
517 // Return addresses are signed by arm64e ABI, so strip off the auth
518 // bits.
519 bt[frame_index++] = (uintptr_t)ptrauth_strip((void *)ret_addr,
520 ptrauth_key_return_address) + addr_offset;
521 #else // defined(HAS_APPLE_PAC)
522 bt[frame_index++] = ret_addr + addr_offset;
523 #endif // !defined(HAS_APPLE_PAC)
524
525 // Find the next frame to follow.
526 next_fp = user_64 ? frame.u64.fp : frame.u32.fp;
527 bool async_frame = allow_async && SWIFT_ASYNC_FP(next_fp);
528 // There is no 32-bit ABI for Swift async call stacks.
529 if (user_64 && async_frame) {
530 async_index = frame_index - 1;
531 // The async context pointer is just below the stack frame.
532 user_addr_t async_ctx_ptr = fp - 8;
533 user_addr_t async_ctx = 0;
534 error = copy(ctx, (char *)&async_ctx, async_ctx_ptr,
535 sizeof(async_ctx));
536 if (error) {
537 goto out;
538 }
539 #if defined(HAS_APPLE_PAC)
540 async_frame_addr = (uintptr_t)ptrauth_strip((void *)async_ctx,
541 ptrauth_key_process_dependent_data);
542 #else // defined(HAS_APPLE_PAC)
543 async_frame_addr = (uintptr_t)async_ctx;
544 #endif // !defined(HAS_APPLE_PAC)
545 has_async = true;
546 allow_async = false;
547 }
548 next_fp = SWIFT_ASYNC_FP_CLEAR(next_fp);
549 #if defined(HAS_APPLE_PAC)
550 next_fp = (uintptr_t)ptrauth_strip((void *)next_fp,
551 ptrauth_key_process_dependent_data);
552 #endif // defined(HAS_APPLE_PAC)
553 if (INVALID_USER_FP(next_fp)) {
554 break;
555 }
556
557 // Stacks grow down; backtracing should be moving to higher addresses,
558 // unless a custom frame pointer is provided, in which case, an async
559 // stack might be walked, which is allocated on the heap in any order.
560 if ((next_fp == fp) || (!custom_fp && next_fp < fp)) {
561 break;
562 }
563 fp = next_fp;
564 }
565
566 out:
567 if (old_map != NULL) {
568 (void)vm_map_switch(old_map);
569 vm_map_deallocate(map);
570 }
571
572 // NULL-terminate the list, if space is available.
573 if (frame_index < max_frames) {
574 bt[frame_index] = 0;
575 }
576
577 if (info_out) {
578 info_out->btui_error = error;
579 backtrace_info_t info = user_64 ? BTI_64_BIT : BTI_NONE;
580 bool out_of_space = !INVALID_USER_FP(fp) && frame_index == max_frames;
581 if (truncated || out_of_space) {
582 info |= BTI_TRUNCATED;
583 }
584 if (out_of_space && error == 0) {
585 info_out->btui_next_frame_addr = fp;
586 }
587 info_out->btui_info = info;
588 info_out->btui_async_start_index = async_index;
589 info_out->btui_async_frame_addr = async_frame_addr;
590 }
591
592 return frame_index;
593 }
594