]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/wrappers/terminate_with_reason.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / libsyscall / wrappers / terminate_with_reason.c
1 /*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include <sys/reason.h>
24 #include <sys/types.h>
25 #include <stdint.h>
26 #include <signal.h>
27 #include <os/reason_private.h>
28 #include <unistd.h>
29
30 /* Crash simulation */
31
32 extern int pthread_current_stack_contains_np(const void *, unsigned long);
33 int
34 __darwin_check_fd_set_overflow(int n, const void *fd_set, int unlimited_select)
35 {
36 if (n < 0) {
37 os_fault_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT,
38 &n, sizeof(n), "FD_SET underflow", 0);
39 return 0;
40 }
41
42 if (n >= __DARWIN_FD_SETSIZE) {
43 if (pthread_current_stack_contains_np((const void *) fd_set, sizeof(struct fd_set))) {
44 if (!unlimited_select) {
45 os_fault_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT,
46 &n, sizeof(n), "FD_SET overflow", 0);
47 return 0;
48 } else {
49 return 1;
50 }
51 } else {
52 return 1;
53 }
54 }
55
56 return 1;
57 }
58
59 /* System call entry points */
60 int __terminate_with_payload(int pid, uint32_t reason_namespace, uint64_t reason_code,
61 void *payload, uint32_t payload_size, const char *reason_string,
62 uint64_t reason_flags);
63
64 void __abort_with_payload(uint32_t reason_namespace, uint64_t reason_code,
65 void *payload, uint32_t payload_size, const char *reason_string,
66 uint64_t reason_flags);
67
68 static void abort_with_payload_wrapper_internal(uint32_t reason_namespace, uint64_t reason_code,
69 void *payload, uint32_t payload_size, const char *reason_string,
70 uint64_t reason_flags) __attribute__((noreturn, cold));
71
72 /* System call wrappers */
73 int
74 terminate_with_reason(int pid, uint32_t reason_namespace, uint64_t reason_code,
75 const char *reason_string, uint64_t reason_flags)
76 {
77 return __terminate_with_payload(pid, reason_namespace, reason_code, 0, 0,
78 reason_string, reason_flags);
79 }
80
81 int
82 terminate_with_payload(int pid, uint32_t reason_namespace, uint64_t reason_code,
83 void *payload, uint32_t payload_size,
84 const char *reason_string, uint64_t reason_flags)
85 {
86 return __terminate_with_payload(pid, reason_namespace, reason_code, payload,
87 payload_size, reason_string, reason_flags);
88 }
89
90 static void
91 abort_with_payload_wrapper_internal(uint32_t reason_namespace, uint64_t reason_code,
92 void *payload, uint32_t payload_size, const char *reason_string,
93 uint64_t reason_flags)
94 {
95 sigset_t unmask_signal;
96
97 /* Try to unmask SIGABRT before trapping to the kernel */
98 sigemptyset(&unmask_signal);
99 sigaddset(&unmask_signal, SIGABRT);
100 sigprocmask(SIG_UNBLOCK, &unmask_signal, NULL);
101
102 __abort_with_payload(reason_namespace, reason_code, payload, payload_size,
103 reason_string, reason_flags);
104
105 /* If sending a SIGABRT failed, we fall back to SIGKILL */
106 terminate_with_payload(getpid(), reason_namespace, reason_code, payload, payload_size,
107 reason_string, reason_flags | OS_REASON_FLAG_ABORT);
108
109 __builtin_unreachable();
110 }
111
112 void
113 abort_with_reason(uint32_t reason_namespace, uint64_t reason_code, const char *reason_string,
114 uint64_t reason_flags)
115 {
116 abort_with_payload_wrapper_internal(reason_namespace, reason_code, 0, 0, reason_string, reason_flags);
117 }
118
119 void
120 abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, void *payload,
121 uint32_t payload_size, const char *reason_string,
122 uint64_t reason_flags)
123 {
124 abort_with_payload_wrapper_internal(reason_namespace, reason_code, payload, payload_size,
125 reason_string, reason_flags);
126 }