this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'feature/sigprocess'

+357 -479
-2
src/dyld/src/dyldAPIs.cpp
··· 125 125 126 126 #ifdef DARLING 127 127 extern "C" int mach_driver_get_fd(void); 128 - extern "C" bool darling_am_i_ptraced(void); 129 128 #endif 130 129 131 130 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib ··· 261 260 #endif 262 261 #ifdef DARLING 263 262 {"__dyld_get_mach_driver_fd", (void*)mach_driver_get_fd }, 264 - {"__dyld_am_i_ptraced", (void*)darling_am_i_ptraced }, 265 263 #endif 266 264 #pragma clang diagnostic pop 267 265 #endif //DEPRECATED_APIS_SUPPORTED
+2 -2
src/kernel/emulation/linux/bsdthread/bsdthread_create.c
··· 42 42 pthread = stack = thread_stack_allocate(stacksize); 43 43 } 44 44 45 - ret = darling_thread_create((void**) stack, pthread_entry_point, thread_start, 45 + ret = darling_thread_create((void**) stack, pthread_entry_point_wrapper, thread_start, 46 46 arg, stacksize, flags); 47 47 #else 48 48 // Implemented in libdyld 49 49 extern int thread_self_trap(void); 50 50 51 51 return __darling_thread_create(((uintptr_t)stack), pthread_obj_size, 52 - pthread_entry_point, thread_start, arg, (uintptr_t) stack, flags, 52 + pthread_entry_point_wrapper, thread_start, arg, (uintptr_t) stack, flags, 53 53 thread_self_trap); 54 54 #endif 55 55
+46 -1
src/kernel/emulation/linux/bsdthread/bsdthread_register.c
··· 2 2 #include "../base.h" 3 3 #include "../errno.h" 4 4 #include "../../../../../platform-include/sys/errno.h" 5 + #include "../signal/sigexc.h" 6 + #include "../mach/lkm.h" 7 + #include "../../../../external/lkm/api.h" 8 + #include <stdint.h> 9 + #include <pthread/tsd_private.h> 5 10 #include <linux-syscalls/linux.h> 6 11 7 12 int pthread_obj_size; ··· 14 19 #define WORKQ_FEATURE_FINEPRIO 0x02 15 20 #define WORKQ_FEATURE_KEVENT 0x40 16 21 22 + struct _pthread_registration_data { 23 + uint64_t version; 24 + 25 + uint64_t dispatch_queue_offset; 26 + uint64_t main_qos; 27 + uint32_t tsd_offset; 28 + uint32_t return_to_kernel_offset; 29 + uint32_t mach_thread_self_offset; 30 + } __attribute__ ((packed)); 31 + 32 + static struct _pthread_registration_data g_pth_regdata; 33 + 17 34 long sys_bsdthread_register(void* thread_start, void* wqthread, int pthsize, 18 - void* dummy, void* targetconc, unsigned long long dpq_offset) 35 + const struct _pthread_registration_data* pth_regdata, 36 + unsigned long pth_regdata_len, unsigned long long dpq_offset) 19 37 { 20 38 pthread_obj_size = pthsize; 21 39 pthread_entry_point = (bsdthread_entry_t) thread_start; 22 40 wqueue_entry_point = (bsdwqthread_entry_t) wqthread; 41 + g_pth_regdata = *pth_regdata; 42 + 43 + struct set_thread_handles_args args; 44 + args.pthread_handle = (unsigned long) _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF); 45 + args.dispatch_qaddr = args.pthread_handle + g_pth_regdata.tsd_offset + g_pth_regdata.dispatch_queue_offset; 46 + 47 + lkm_call(NR_set_thread_handles, &args); 48 + 23 49 return /* WORKQ_FEATURE_KEVENT | WORKQ_FEATURE_FINEPRIO | PTHREAD_FEATURE_QOS_MAINTENANCE 24 50 | PTHREAD_FEATURE_DISPATCHFUNC | PTHREAD_FEATURE_QOS_DEFAULT */ 0; 25 51 } 26 52 53 + void pthread_entry_point_wrapper(void* self, int thread_port, void* funptr, 54 + void* funarg, unsigned long stacksize, unsigned int flags) 55 + { 56 + sigexc_thread_setup(); 57 + 58 + struct set_thread_handles_args args; 59 + args.pthread_handle = (unsigned long) self; 60 + args.dispatch_qaddr = args.pthread_handle + g_pth_regdata.tsd_offset + g_pth_regdata.dispatch_queue_offset; 61 + 62 + lkm_call(NR_set_thread_handles, &args); 63 + pthread_entry_point(self, thread_port, funptr, funarg, stacksize, flags); 64 + } 65 + 66 + void wqueue_entry_point_wrapper(void* self, int thread_port, void* stackaddr, 67 + void* item, int reuse, int nevents) 68 + { 69 + sigexc_thread_setup(); 70 + wqueue_entry_point(self, thread_port, stackaddr, item, reuse, nevents); 71 + }
+8 -1
src/kernel/emulation/linux/bsdthread/bsdthread_register.h
··· 9 9 extern bsdthread_entry_t pthread_entry_point; 10 10 extern bsdwqthread_entry_t wqueue_entry_point; 11 11 12 + struct _pthread_registration_data; 13 + 12 14 long sys_bsdthread_register(void* thread_start, void* wqthread, int pthsize, 13 - void* dummy, void* targetconc, unsigned long long dpq_offset); 15 + const struct _pthread_registration_data* pth_regdata, 16 + unsigned long pth_regdata_len, unsigned long long dpq_offset); 17 + void pthread_entry_point_wrapper(void* self, int thread_port, void* funptr, 18 + void* funarg, unsigned long stacksize, unsigned int flags); 19 + void wqueue_entry_point_wrapper(void* self, int thread_port, void* stackaddr, 20 + void* item, int reuse, int nevents); 14 21 15 22 #endif 16 23
+1 -1
src/kernel/emulation/linux/bsdthread/workq_kernreturn.c
··· 246 246 // __simple_printf("Spawning a new thread, nevents=%d\n", (wq_event != NULL) ? wq_event->nevents : -1); 247 247 wq_event_pending = wq_event; 248 248 249 - __darling_thread_create(512*1024, pthread_obj_size, wqueue_entry_point, 0, 249 + __darling_thread_create(512*1024, pthread_obj_size, wqueue_entry_point_wrapper, 0, 250 250 (wq_event != NULL) ? wq_event->events : NULL, flags, 251 251 (wq_event != NULL) ? wq_event->nevents : 0, 252 252 thread_self_trap);
+24 -21
src/kernel/emulation/linux/misc/ptrace.c
··· 63 63 ret = lkm_call(NR_set_tracer, &args); 64 64 if (ret < 0) 65 65 ret = errno_linux_to_bsd(ret); 66 - else 67 - { 68 - // This triggers darling_sigexc_self() in the remote process. 69 - ret = linux_sigqueue(pid, SIGNAL_SIGEXC_TOGGLE, SIGRT_MAGIC_ENABLE_SIGEXC); 70 66 71 - if (ret < 0) 72 - ret = errno_linux_to_bsd(ret); 73 - // This doesn't work if the process is stopped, e.g. when spawning a stopped 74 - // process via posix_spawn(). So now we have to resume the process so that 75 - // it gets the RT signal above and triggers a fake SIGSTOP on its own. 76 - // int pstate = lkm_call(NR_pid_get_state, (void*)(long) pid); 77 - // if (pstate & 4 /* __TASK_STOPPED */) 78 - // sys_kill(pid, SIGCONT, 1); 79 - } 67 + sys_kill(pid, SIGSTOP, 1); 68 + 69 + struct ptrace_sigexc_args args2; 70 + args2.pid = pid; 71 + args2.sigexc = 1; 72 + 73 + ret = lkm_call(NR_ptrace_sigexc, &args2); 80 74 81 75 cmd = "PT_ATTACHEXC"; 82 76 break; ··· 105 99 case PT_DETACH: 106 100 { 107 101 // Tell the tracee to restore original application signal handlers. 108 - linux_sigqueue(pid, SIGNAL_SIGEXC_TOGGLE, SIGRT_MAGIC_DISABLE_SIGEXC); 102 + //linux_sigqueue(pid, SIGNAL_SIGEXC_TOGGLE, SIGRT_MAGIC_DISABLE_SIGEXC); 103 + 104 + //ret = 0; //LINUX_SYSCALL(__NR_ptrace, LINUX_PTRACE_DETACH, pid, addr, data); 105 + struct ptrace_sigexc_args args; 106 + args.pid = pid; 107 + args.sigexc = 0; 109 108 110 - ret = 0; //LINUX_SYSCALL(__NR_ptrace, LINUX_PTRACE_DETACH, pid, addr, data); 109 + ret = lkm_call(NR_ptrace_sigexc, &args); 111 110 112 111 // if (ret < 0) 113 112 // ret = errno_linux_to_bsd(ret); ··· 118 117 case PT_SIGEXC: 119 118 { 120 119 lkm_call(0x1028, "sigexc: self via ptrace\n"); 121 - darling_sigexc_self(); 122 - ret = 0; 120 + 121 + struct ptrace_sigexc_args args; 122 + args.pid = getpid(); 123 + args.sigexc = 1; 124 + 125 + ret = lkm_call(NR_ptrace_sigexc, &args); 123 126 124 127 // return ret; 125 128 cmd = "PT_SIGEXC"; break; ··· 148 151 if (tid < 0) 149 152 return -ESRCH; 150 153 151 - int signal = 0; 152 - if (data != -1) 153 - signal = signum_bsd_to_linux(data); 154 + struct ptrace_thupdate_args args; 155 + args.tid = tid; 156 + args.signum = data; 154 157 155 - ret = linux_sigqueue_thread(pid, tid, SIGNAL_SIGEXC_THUPDATE, signal); 158 + ret = lkm_call(NR_ptrace_thupdate, &args); 156 159 if (ret < 0) 157 160 ret = errno_linux_to_bsd(ret); 158 161
+2 -2
src/kernel/emulation/linux/process/execve.c
··· 119 119 } 120 120 121 121 linux_sigset_t set; 122 - set = (1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 123 - set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 122 + set = (1ull << (SIGNAL_SIGEXC_SUSPEND-1)); 123 + //set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 124 124 125 125 LINUX_SYSCALL(__NR_rt_sigprocmask, 0 /* LINUX_SIG_BLOCK */, 126 126 &set, NULL, sizeof(linux_sigset_t));
+7 -1
src/kernel/emulation/linux/signal/duct_signals.c
··· 62 62 return SIGUSR1; 63 63 case LINUX_SIGUSR2: 64 64 return SIGUSR2; 65 + // Hack! This is what we send instead of SIGSTOP to allow the target process to receive the signal 66 + // and pass it through the LKM. 67 + case LINUX_SIGSTKFLT: 68 + return SIGSTOP; 65 69 default: 66 70 return 0; 67 71 } ··· 102 106 case SIGURG: 103 107 return LINUX_SIGURG; 104 108 case SIGSTOP: 105 - return LINUX_SIGSTOP; 109 + // Hack! See above. 110 + //return LINUX_SIGSTOP; 111 + return LINUX_SIGSTKFLT; 106 112 case SIGTSTP: 107 113 return LINUX_SIGTSTP; 108 114 case SIGCONT:
+2 -2
src/kernel/emulation/linux/signal/kill.c
··· 16 16 17 17 // If we're stopping a process we're debugging, do an emulated SIGSTOP 18 18 // so that the tracee has a chance to talk to us before stopping. 19 - if (signum == SIGSTOP && pid > 0) 19 + /*if (signum == SIGSTOP && pid > 0) 20 20 { 21 21 int tracer = lkm_call(NR_get_tracer, (void*)(long)pid); 22 22 if (tracer == getpid()) ··· 24 24 linux_sigqueue(pid, SIGNAL_SIGEXC_THUPDATE, -LINUX_SIGSTOP); 25 25 return 0; 26 26 } 27 - } 27 + }*/ 28 28 29 29 linux_signum = signum_bsd_to_linux(signum); 30 30 if (!linux_signum)
+100 -4
src/kernel/emulation/linux/signal/sigaction.c
··· 17 17 18 18 // Libc uses only one trampoline 19 19 void (*sa_tramp)(void*, int, int, struct bsd_siginfo*, void*) = 0; 20 - bsd_sig_handler* sig_handlers[32]; 20 + bsd_sig_handler* sig_handlers[32] = { 21 + [LINUX_SIGWINCH] = (bsd_sig_handler*) SIG_IGN, 22 + [LINUX_SIGCHLD] = (bsd_sig_handler*) SIG_IGN, 23 + [LINUX_SIGURG] = (bsd_sig_handler*) SIG_IGN, 24 + }; 21 25 int sig_flags[32]; 22 26 unsigned int sig_masks[32]; 23 27 ··· 41 45 return 0; 42 46 } 43 47 48 + if (nsa != NULL && linux_signum == LINUX_SIGCHLD) 49 + { 50 + sa_tramp = nsa->sa_tramp; 51 + if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN 52 + && nsa->sa_sigaction != SIG_ERR) 53 + { 54 + sa.sa_sigaction = &handler_linux_to_bsd; 55 + } 56 + else 57 + sa.sa_sigaction = (linux_sig_handler*) nsa->sa_sigaction; 58 + 59 + sigset_bsd_to_linux(&nsa->sa_mask, &sa.sa_mask); 60 + sa.sa_flags = sigflags_bsd_to_linux(nsa->sa_flags) | LINUX_SA_RESTORER; 61 + sa.sa_restorer = sig_restorer; 62 + 63 + ret = LINUX_SYSCALL(__NR_rt_sigaction, linux_signum, 64 + (nsa != NULL) ? &sa : NULL, &olsa, 65 + sizeof(sa.sa_mask)); 66 + 67 + if (ret < 0) 68 + return errno_linux_to_bsd(ret); 69 + 70 + if (osa != NULL) 71 + { 72 + if (olsa.sa_sigaction == handler_linux_to_bsd) 73 + osa->sa_sigaction = sig_handlers[linux_signum]; 74 + else // values such as SIG_DFL 75 + osa->sa_sigaction = (bsd_sig_handler*) olsa.sa_sigaction; 76 + sigset_linux_to_bsd(&olsa.sa_mask, &osa->sa_mask); 77 + osa->sa_flags = sigflags_linux_to_bsd(olsa.sa_flags); 78 + } 79 + } 80 + else 81 + { 82 + ret = 0; 83 + 84 + if (osa != NULL) 85 + { 86 + osa->sa_sigaction = sig_handlers[linux_signum]; 87 + osa->sa_flags = sig_flags[linux_signum]; 88 + osa->sa_mask = sig_masks[linux_signum]; 89 + } 90 + } 91 + 92 + if (nsa != NULL && ret >= 0) 93 + { 94 + // __simple_printf("Saving handler for signal %d: %p\n", linux_signum, nsa->sa_sigaction); 95 + sig_handlers[linux_signum] = nsa->sa_sigaction; 96 + sig_flags[linux_signum] = nsa->sa_flags; 97 + sig_masks[linux_signum] = nsa->sa_mask; 98 + } 99 + 100 + return 0; 101 + } 102 + 103 + #if 0 104 + long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sigaction* osa) 105 + { 106 + int ret, linux_signum; 107 + struct linux_sigaction sa, olsa; 108 + 109 + linux_signum = signum_bsd_to_linux(signum); 110 + if (linux_signum == 0) 111 + { 112 + // Some software (e.g. Node.js) tries to set up handlers for all signals by 113 + // walking through all signal numbers incrementally. They end up hitting 114 + // signals that don't exist on Linux and then bail out if they receive 115 + // an error. 116 + // Fake that everyting is all right. 117 + 118 + if (osa != NULL) 119 + memset(osa, 0, sizeof(*osa)); 120 + 121 + return 0; 122 + } 123 + 44 124 if (nsa != NULL) 45 125 { 46 126 sa_tramp = nsa->sa_tramp; 47 - if (darling_am_i_ptraced()) 127 + /*if (darling_am_i_ptraced()) 48 128 { 49 129 sa.sa_sigaction = &sigexc_handler; 50 130 } 51 - else if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN 131 + else*/ if (nsa->sa_sigaction != SIG_DFL && nsa->sa_sigaction != SIG_IGN 52 132 && nsa->sa_sigaction != SIG_ERR) 53 133 { 54 134 sa.sa_sigaction = &handler_linux_to_bsd; ··· 87 167 88 168 return 0; 89 169 } 170 + #endif 90 171 91 172 static void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_ucontext* bc, struct bsd_mcontext* bm) 92 173 { ··· 193 274 194 275 // __simple_printf("Handling signal %d\n", linux_signum); 195 276 196 - sig_handlers[linux_signum](bsd_signum, info ? &binfo : NULL, (lc != NULL) ? &bc : NULL); 277 + bsd_sig_handler* handler = sig_handlers[linux_signum]; 278 + if (sig_flags[linux_signum] & LINUX_SA_RESETHAND) 279 + { 280 + switch (linux_signum) 281 + { 282 + case LINUX_SIGWINCH: 283 + case LINUX_SIGCHLD: 284 + case LINUX_SIGURG: 285 + sig_handlers[linux_signum] = (bsd_sig_handler*) SIG_IGN; 286 + break; 287 + default: 288 + sig_handlers[linux_signum] = NULL; // SIG_DFL 289 + } 290 + } 291 + 292 + handler(bsd_signum, info ? &binfo : NULL, (lc != NULL) ? &bc : NULL); 197 293 198 294 if (lc != NULL) 199 295 {
+162 -427
src/kernel/emulation/linux/signal/sigexc.c
··· 1 + #include "sigaction.h" 1 2 #include "sigexc.h" 2 3 #include "../base.h" 3 4 #include "../unistd/exit.h" 4 5 #include <stddef.h> 5 6 #include <sys/signal.h> 6 7 #include <linux-syscalls/linux.h> 7 - #include <pthread/tsd_private.h> 8 - #include "signal/mach_exc.h" 9 - #include "signal/exc.h" 10 8 #include "sigaltstack.h" 11 9 #include "../mach/lkm.h" 12 10 #include "../../../../external/lkm/api.h" 13 11 #include "../../../libsyscall/wrappers/_libkernel_init.h" 12 + #include "../../../../../platform-include/sys/mman.h" 13 + #include "../mman/mman.h" 14 14 #include "kill.h" 15 15 #include "../simple.h" 16 16 ··· 29 29 void darling_sigexc_uninstall(void); 30 30 void sigrt_handler(int signum, struct linux_siginfo* info, void* ctxt); 31 31 32 - #define SIGEXC_TSD_KEY 102 33 - #define SIGEXC_CONTEXT_TSD_KEY 103 34 - static char sigexc_altstack[8192]; 35 - static struct bsd_stack orig_stack; 32 + static char sigexc_altstack[8*1024]; 36 33 37 34 #if defined(__x86_64__) 38 35 static void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s); ··· 46 43 static void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx); 47 44 #endif 48 45 49 - static void state_to_kernel(struct linux_ucontext* ctxt, thread_t thread); 46 + static void state_from_kernel(struct linux_ucontext* ctxt, const struct thread_state* kernel_state); 47 + static void state_to_kernel(struct linux_ucontext* ctxt, struct thread_state* kernel_state); 50 48 51 49 #define DEBUG_SIGEXC 52 50 #ifdef DEBUG_SIGEXC ··· 57 55 58 56 void sigexc_setup1(void) 59 57 { 60 - kern_printf("sigexc_setup1()"); 61 - // Setup handler for SIGNAL_SIGEXC_TOGGLE and SIGNAL_SIGEXC_THUPDATE 62 - handle_rt_signal(SIGNAL_SIGEXC_TOGGLE); 63 - handle_rt_signal(SIGNAL_SIGEXC_THUPDATE); 58 + handle_rt_signal(SIGNAL_SIGEXC_SUSPEND); 64 59 } 65 60 66 61 void sigexc_setup2(void) 67 62 { 68 - kern_printf("sigexc_setup2()\n"); 69 - 70 63 linux_sigset_t set; 71 - set = (1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 72 - set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 64 + set = (1ull << (SIGNAL_SIGEXC_SUSPEND-1)); 65 + //set |= (1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 73 66 74 67 LINUX_SYSCALL(__NR_rt_sigprocmask, 1 /* LINUX_SIG_UNBLOCK */, 75 68 &set, NULL, sizeof(linux_sigset_t)); 76 - 77 - // If we have a tracer (i.e. we are a new process after execve), 78 - // enable sigexc handling and send SIGTRAP to self to allow 79 - // the debugger to handle this situation. 80 - if (!am_i_ptraced && lkm_call(NR_get_tracer, NULL) != 0) 81 - { 82 - kern_printf("sigexc: the parent is traced\n"); 83 - darling_sigexc_self(); 84 - sigexc_handler(LINUX_SIGTRAP, NULL, NULL); 85 - } 86 69 } 87 70 88 - void sigexc_setup(void) 71 + static void dump_gregs(const struct linux_gregset* regs) 89 72 { 90 - #ifdef VARIANT_DYLD 91 - sigexc_setup1(); 92 - if (lkm_call(NR_started_suspended, 0)) 73 + unsigned long long* p = (unsigned long long*) regs; 74 + for (int i = 0; i < 23; i++) 93 75 { 94 - kern_printf("sigexc: waiting for signal\n"); 95 - 96 - // sigsuspend until resumed or debugger attached 97 - linux_sigset_t set = -1ll; 98 - set &= ~(1ull << (LINUX_SIGCONT-1)); 99 - set &= ~(1ull << (SIGNAL_SIGEXC_TOGGLE-1)); 100 - set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 101 - 102 - LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8); 103 - 104 - kern_printf("sigexc: done waiting for signal\n"); 76 + kern_printf("sigexc: gregs 0x%x\n", p[i]); 105 77 } 106 - sigexc_setup2(); 107 - #else 108 - sigexc_setup1(); 109 - 110 - // get am_i_ptraced value from dyld 111 - bool (*is_traced)(void); 112 - _libkernel_functions->dyld_func_lookup("__dyld_am_i_ptraced", (void**) &is_traced); 113 - am_i_ptraced = is_traced(); 114 - 115 - if (am_i_ptraced) 116 - { 117 - // We have to take over from dyld's build of this file, because 118 - // we rely on having accurate signal handler information of the running application. 119 - kern_printf("sigexc: taking over sigexc handling\n"); 120 - darling_sigexc_self(); 121 - } 122 - #endif 123 78 } 124 79 125 80 static void handle_rt_signal(int signum) ··· 128 83 struct linux_sigaction sa; 129 84 130 85 sa.sa_sigaction = sigrt_handler; 131 - sa.sa_mask = 0; 132 - sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART; 86 + sa.sa_mask = (1ull << (SIGNAL_SIGEXC_SUSPEND-1)); 87 + sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK; 133 88 sa.sa_restorer = sig_restorer; 134 89 135 90 rv = LINUX_SYSCALL(__NR_rt_sigaction, signum, ··· 141 96 //external/lkm_call(0x1028, buf); 142 97 } 143 98 144 - bool darling_am_i_ptraced(void) 99 + void sigexc_setup(void) 145 100 { 146 - return am_i_ptraced; 101 + darling_sigexc_self(); 102 + sigexc_setup1(); 103 + sigexc_setup2(); 104 + #ifdef VARIANT_DYLD 105 + if (lkm_call(NR_started_suspended, 0)) 106 + { 107 + kern_printf("sigexc: start_suspended -> suspending (ret to %p)\n", __builtin_return_address(0)); 108 + task_suspend(mach_task_self()); 109 + kern_printf("sigexc: start_suspended -> wokenup (ret to %p)\n", __builtin_return_address(0)); 110 + } 111 + else if (lkm_call(NR_get_tracer, NULL) != 0) 112 + { 113 + kern_printf("sigexc: already traced -> SIGTRAP\n"); 114 + sys_kill(0, SIGTRAP, 0); 115 + } 116 + #else 117 + 118 + #endif 147 119 } 148 120 149 121 void sigrt_handler(int signum, struct linux_siginfo* info, void* ctxt) 150 122 { 151 - kern_printf("sigexc: sigrt_handler signum=%d, si_value=%x\n", signum, info->si_value); 123 + #if defined(__x86_64__) 124 + x86_thread_state64_t tstate; 125 + x86_float_state64_t fstate; 126 + #elif defined(__i386__) 127 + x86_thread_state32_t tstate; 128 + x86_float_state32_t fstate; 129 + #endif 152 130 153 - if (signum == SIGNAL_SIGEXC_TOGGLE) 154 - { 155 - if (((uint32_t) info->si_value) == SIGRT_MAGIC_ENABLE_SIGEXC) 156 - { 157 - darling_sigexc_self(); 131 + struct thread_suspended_args args; 132 + args.state.tstate = &tstate; 133 + args.state.fstate = &fstate; 158 134 159 - // Stop on attach 160 - sigexc_handler(LINUX_SIGSTOP, NULL, (struct linux_ucontext*) ctxt); 161 - } 162 - else if (((uint32_t) info->si_value) == SIGRT_MAGIC_DISABLE_SIGEXC) 163 - { 164 - darling_sigexc_uninstall(); 165 - } 166 - } 167 - else if (signum == SIGNAL_SIGEXC_THUPDATE) 168 - { 169 - if (!am_i_ptraced) 170 - return; 135 + kern_printf("sigexc: sigrt_handler SUSPEND\n"); 136 + 137 + thread_t thread = mach_thread_self(); 138 + state_to_kernel(ctxt, &args.state); 171 139 172 - // Examine info->si_value 173 - // If 0, drop the signal 174 - // If >0, process the signal 175 - // If <0, introduce a new signal 176 - int sig = info->si_value; 177 - if (sig == SIGNAL_THREAD_SUSPEND) 178 - { 179 - kern_printf("sigexc: SIGNAL_THREAD_SUSPEND\n"); 180 - if (_pthread_getspecific_direct(SIGEXC_TSD_KEY) == 0) 181 - sigexc_fake_suspend(ctxt); 182 - else 183 - { 184 - kern_printf("sigexc: already suspended\n"); 185 - void* ctxt = _pthread_getspecific_direct(SIGEXC_CONTEXT_TSD_KEY); 140 + lkm_call(NR_thread_suspended, &args); 186 141 187 - if (ctxt) 188 - { 189 - thread_t thread = mach_thread_self(); 190 - state_to_kernel(ctxt, thread); 191 - kern_printf("sigexc: state_to_kernel complete\n"); 192 - } 193 - } 194 - } 195 - else if (sig == SIGNAL_THREAD_RESUME) 196 - { 197 - kern_printf("sigexc: SIGNAL_THREAD_RESUME\n"); 198 - } 199 - else if (sig < 0) 200 - { 201 - // This is only used to pass a SIGSTOP to the traced process (from the debugger) 202 - // and have it passed back through the sigexc mechanism. 203 - // See sys_kill(). 204 - sigexc_handler(-sig, NULL, (struct linux_ucontext*) ctxt); 205 - } 206 - else 207 - { 208 - // This is the debugger telling us how to deal with the signal. 209 - _pthread_setspecific_direct(SIGEXC_TSD_KEY, sig); 210 - } 211 - } 142 + state_from_kernel(ctxt, &args.state); 212 143 } 144 + 213 145 214 146 void darling_sigexc_self(void) 215 147 { ··· 219 151 // Make sigexc_handler the handler for all signals in the process 220 152 for (int i = 1; i <= 31; i++) 221 153 { 222 - if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL) 154 + if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL || i == LINUX_SIGCHLD) 223 155 continue; 224 156 225 157 struct linux_sigaction sa; 226 158 sa.sa_sigaction = (linux_sig_handler*) sigexc_handler; 227 159 sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run 160 + sa.sa_mask |= (1ull << (SIGNAL_SIGEXC_SUSPEND-1)); 228 161 sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK; 229 162 sa.sa_restorer = sig_restorer; 230 163 ··· 238 171 .ss_size = sizeof(sigexc_altstack), 239 172 .ss_flags = 0 240 173 }; 241 - sys_sigaltstack(&newstack, &orig_stack); 174 + sys_sigaltstack(&newstack, NULL); 242 175 } 243 - void darling_sigexc_uninstall(void) 244 - { 245 - am_i_ptraced = false; 246 176 247 - // __simple_printf("darling_sigexc_uninstall()\n"); 248 - for (int i = 1; i <= 31; i++) 249 - { 250 - if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL) 251 - continue; 252 - 253 - struct linux_sigaction sa; 254 177 255 - if (sig_handlers[i] == SIG_DFL || sig_handlers[i] != SIG_IGN 256 - || sig_handlers[i] != SIG_ERR) 257 - { 258 - sa.sa_sigaction = (linux_sig_handler*) sig_handlers[i]; 259 - } 260 - else 261 - sa.sa_sigaction = &handler_linux_to_bsd; 262 - 263 - sa.sa_mask = sig_masks[i]; 264 - sa.sa_flags = sig_flags[i]; 265 - sa.sa_restorer = sig_restorer; 266 - 267 - LINUX_SYSCALL(__NR_rt_sigaction, i, 268 - &sa, NULL, 269 - sizeof(sa.sa_mask)); 270 - } 271 - 272 - sys_sigaltstack(&orig_stack, NULL); 273 - } 274 - 275 - static mach_port_t get_exc_port(int type, int* behavior) 276 - { 277 - mach_msg_type_number_t count = 0; 278 - exception_mask_t masks[EXC_TYPES_COUNT]; 279 - mach_port_t ports[EXC_TYPES_COUNT]; 280 - exception_behavior_t behaviors[EXC_TYPES_COUNT]; 281 - thread_state_flavor_t flavors[EXC_TYPES_COUNT]; 282 - 283 - kern_return_t result = task_get_exception_ports(mach_task_self(), 1 << type, 284 - masks, &count, ports, behaviors, flavors); 285 - 286 - if (result != KERN_SUCCESS) 287 - return 0; 288 - 289 - for (int i = 0; i < count; i++) 290 - { 291 - if (masks[i] & (1 << type)) 292 - { 293 - if (behavior != NULL) 294 - *behavior = behaviors[i]; 295 - return ports[i]; 296 - } 297 - } 298 - 299 - return 0; 300 - } 301 - 302 - static void state_to_kernel(struct linux_ucontext* ctxt, thread_t thread) 178 + static void state_to_kernel(struct linux_ucontext* ctxt, struct thread_state* kernel_state) 303 179 { 304 180 #if defined(__x86_64__) 305 - x86_thread_state64_t tstate; 306 - x86_float_state64_t fstate; 307 181 308 - if (ctxt != NULL) 309 - { 310 - mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate); 311 - mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate); 312 - /* 313 - #ifdef __x86_64__ 314 - if (bsd_signum == SIGTRAP) 315 - { 316 - uint8_t* rip = (uint8_t*) ctxt->uc_mcontext.gregs.rip; 317 - kern_printf("rip is %p\n", rip); 318 - kern_printf("Value at rip-1 on suspend: 0x%x\n", *(rip-1)); 319 - } 320 - #endif 321 - */ 322 - } 323 - else 324 - { 325 - memset(&tstate, 0, sizeof(tstate)); 326 - memset(&fstate, 0, sizeof(fstate)); 327 - } 182 + dump_gregs(&ctxt->uc_mcontext.gregs); 183 + mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state64_t*) kernel_state->tstate); 184 + mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state64_t*) kernel_state->fstate); 328 185 329 - __simple_kprintf("sigexc: Telling kernel our RIP is %p\n", tstate.__rip); 330 - 331 - thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, x86_THREAD_STATE64_COUNT); 332 - thread_set_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, x86_FLOAT_STATE64_COUNT); 333 186 #elif defined(__i386__) 334 - x86_thread_state32_t tstate; 335 - x86_float_state32_t fstate; 336 - 337 - if (ctxt != NULL) 338 - { 339 - mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, &tstate); 340 - mcontext_to_float_state(ctxt->uc_mcontext.fpregs, &fstate); 341 - } 342 - else 343 - { 344 - memset(&tstate, 0, sizeof(tstate)); 345 - memset(&fstate, 0, sizeof(fstate)); 346 - } 347 - 348 - thread_set_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, x86_THREAD_STATE32_COUNT); 349 - thread_set_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, x86_FLOAT_STATE32_COUNT); 187 + mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state32_t*) kernel_state->tstate); 188 + mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state32_t*) kernel_state->fstate); 350 189 #endif 351 190 352 191 } 353 192 354 - static void state_from_kernel(struct linux_ucontext* ctxt, thread_t thread) 193 + static void state_from_kernel(struct linux_ucontext* ctxt, const struct thread_state* kernel_state) 355 194 { 356 195 #if defined(__x86_64__) 357 - x86_thread_state64_t tstate; 358 - x86_float_state64_t fstate; 359 - mach_msg_type_number_t count; 360 196 361 - count = x86_THREAD_STATE64_COUNT; 362 - thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t) &tstate, &count); 363 - count = x86_FLOAT_STATE64_COUNT; 364 - thread_get_state(thread, x86_FLOAT_STATE64, (thread_state_t) &fstate, &count); 197 + thread_state_to_mcontext((x86_thread_state64_t*) kernel_state->tstate, &ctxt->uc_mcontext.gregs); 198 + float_state_to_mcontext((x86_float_state64_t*) kernel_state->fstate, ctxt->uc_mcontext.fpregs); 365 199 366 - thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs); 367 - float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs); 200 + dump_gregs(&ctxt->uc_mcontext.gregs); 368 201 369 202 #elif defined(__i386__) 370 - x86_thread_state32_t tstate; 371 - x86_float_state32_t fstate; 372 - mach_msg_type_number_t count; 373 - 374 - count = x86_THREAD_STATE32_COUNT; 375 - thread_get_state(thread, x86_THREAD_STATE32, (thread_state_t) &tstate, &count); 376 - count = x86_FLOAT_STATE32_COUNT; 377 - thread_get_state(thread, x86_FLOAT_STATE32, (thread_state_t) &fstate, &count); 378 - 379 - thread_state_to_mcontext(&tstate, &ctxt->uc_mcontext.gregs); 380 - float_state_to_mcontext(&fstate, ctxt->uc_mcontext.fpregs); 203 + thread_state_to_mcontext((x86_thread_state32_t*) kernel_state->tstate, &ctxt->uc_mcontext.gregs); 204 + float_state_to_mcontext((x86_float_state32_t*) kernel_state->fstate, ctxt->uc_mcontext.fpregs); 381 205 #endif 382 206 } 383 207 384 - void sigexc_fake_suspend(struct linux_ucontext* ctxt) 385 - { 386 - if (_pthread_getspecific_direct(SIGEXC_TSD_KEY) != 0) 387 - return; 388 - thread_t thread = mach_thread_self(); 389 - 390 - kern_printf("sigexc_fake_suspend -> state_to_kernel\n"); 391 - state_to_kernel(ctxt, thread); 392 - 393 - linux_sigset_t set = -1ll; 394 - set &= ~(1ull << (SIGNAL_SIGEXC_THUPDATE-1)); 395 - 396 - LINUX_SYSCALL(__NR_rt_sigsuspend, &set, 8); 397 - 398 - kern_printf("sigexc_fake_suspend -> state_from_kernel\n"); 399 - state_from_kernel(ctxt, thread); 400 - } 401 - 402 - // syscall tracking 403 - #define LINUX_TRAP_BRKPT 1 404 - // single-stepping 405 - #define LINUX_TRAP_TRACE 2 406 - // ??? 407 - #define LINUX_TRAP_BRANCH 3 408 - // memory watchpoint 409 - #define LINUX_TRAP_HWBKPT 4 410 - // int3 (on x86, other platforms probably use TRAP_BRKPT) 411 - #define LINUX_SI_KERNEL 0x80 412 - 413 208 void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt) 414 209 { 415 210 kern_printf("sigexc_handler(%d, %p, %p)\n", linux_signum, info, ctxt); 416 211 417 - if (!darling_am_i_ptraced()) 418 - { 419 - kern_printf("sigexc: NOT TRACED!\n"); 420 - return; 421 - } 422 - 212 + 423 213 if (linux_signum == LINUX_SIGCONT) 424 214 return; 425 215 426 - // Send a Mach message to the debugger. 427 - // The debugger may use ptrace(PT_THUPDATE) to change how the signal is processed. 428 - 429 - int mach_exception, behavior; 430 - long long codes[EXCEPTION_CODE_MAX] = { 0 }; 431 - mach_port_t port; 432 - thread_t thread = mach_thread_self(); 433 - 434 216 int bsd_signum = signum_linux_to_bsd(linux_signum); 435 217 if (bsd_signum <= 0) 436 218 { ··· 438 220 return; 439 221 } 440 222 441 - if (linux_signum == 11) 442 - { 443 - kern_printf("sigexc: faulting address: %p, code: %d\n", info->si_addr, info->si_code); 444 - } 223 + struct sigprocess_args sigprocess; 224 + sigprocess.signum = bsd_signum; 445 225 446 - // SIGSEGV + SIGBUS -> EXC_BAD_ACCESS 447 - // SIGTRAP -> EXC_BREAKPOINT 448 - // SIGILL -> EXC_BAD_INSTRUCTION 449 - // SIGFPE -> EXC_ARITHMETIC 450 - // * -> EXC_SOFTWARE with EXC_SOFT_SIGNAL (e.g. SIGSTOP) 226 + memcpy(&sigprocess.linux_siginfo, info, sizeof(*info)); 227 + 228 + #ifdef __x86_64__ 229 + kern_printf("sigexc: have RIP 0x%x\n", ctxt->uc_mcontext.gregs.rip); 230 + #endif 451 231 452 - // Only real exceptions produced by the CPU get translated to these 453 - // Mach exceptions. The rest comes as EXC_SOFTWARE. 454 - if (info != NULL && info->si_code != 0) 455 - { 456 - switch (bsd_signum) 457 - { 458 - case SIGSEGV: 459 - mach_exception = EXC_BAD_ACCESS; 460 - codes[0] = EXC_I386_GPFLT; 461 - break; 462 - case SIGBUS: 463 - mach_exception = EXC_BAD_ACCESS; 464 - codes[0] = EXC_I386_ALIGNFLT; 465 - break; 466 - case SIGILL: 467 - mach_exception = EXC_BAD_INSTRUCTION; 468 - codes[0] = EXC_I386_INVOP; 469 - break; 470 - case SIGFPE: 471 - mach_exception = EXC_ARITHMETIC; 472 - codes[0] = info->si_code; 473 - break; 474 - case SIGTRAP: 475 - mach_exception = EXC_BREAKPOINT; 476 - codes[0] = (info->si_code == LINUX_SI_KERNEL) ? EXC_I386_BPT : EXC_I386_SGL; 232 + thread_t thread = mach_thread_self(); 477 233 478 - if (info->si_code == LINUX_TRAP_HWBKPT) 479 - { 480 - // Memory watchpoint triggered 481 - struct last_triggered_watchpoint_args args; 482 - if (lkm_call(NR_last_triggered_watchpoint, &args) == 0) 483 - { 484 - codes[1] = args.address; 485 - // codes[2] = args.flags; 486 - } 487 - } 488 - break; 489 - default: 490 - mach_exception = EXC_SOFTWARE; 491 - codes[0] = EXC_SOFT_SIGNAL; 492 - codes[1] = bsd_signum; 493 - } 494 - } 495 - else 496 - { 497 - mach_exception = EXC_SOFTWARE; 498 - codes[0] = EXC_SOFT_SIGNAL; 499 - codes[1] = bsd_signum; 500 - } 234 + #if defined(__x86_64__) 235 + x86_thread_state64_t tstate; 236 + x86_float_state64_t fstate; 237 + #elif defined(__i386__) 238 + x86_thread_state32_t tstate; 239 + x86_float_state32_t fstate; 240 + #endif 501 241 502 - port = get_exc_port(mach_exception, &behavior); 242 + sigprocess.state.tstate = &tstate; 243 + sigprocess.state.fstate = &fstate; 503 244 504 - // Pass register states to LKM 505 - state_to_kernel(ctxt, thread); 245 + state_to_kernel(ctxt, &sigprocess.state); 246 + lkm_call(NR_sigprocess, &sigprocess); 247 + state_from_kernel(ctxt, &sigprocess.state); 506 248 507 - // __simple_printf("Passing Mach exception to port %d\n", port); 508 - if (port != 0) 249 + if (!sigprocess.signum) 509 250 { 510 - _pthread_setspecific_direct(SIGEXC_TSD_KEY, bsd_signum); 511 - _pthread_setspecific_direct(SIGEXC_CONTEXT_TSD_KEY, ctxt); 512 - 513 - kern_return_t ret; 251 + kern_printf("sigexc: drop signal\n"); 252 + return; 253 + } 514 254 515 - if (behavior & MACH_EXCEPTION_CODES) 516 - { 517 - ret = mach_exception_raise(port, thread, mach_task_self(), mach_exception, codes, sizeof(codes) / sizeof(codes[0])); 518 - } 519 - else 520 - { 521 - exception_data_type_t small_codes[2] = { (exception_data_type_t) codes[0], (exception_data_type_t) codes[1] }; 522 - ret = exception_raise(port, thread, mach_task_self(), mach_exception, small_codes, sizeof(small_codes) / sizeof(small_codes[0])); 523 - } 255 + linux_signum = signum_bsd_to_linux(sigprocess.signum); 524 256 525 - if (ret == MACH_RCV_PORT_DIED || ret == MACH_SEND_INVALID_DEST) 257 + if (sig_handlers[linux_signum] != SIG_IGN) 258 + { 259 + if (sig_handlers[linux_signum]) 526 260 { 527 - kern_printf("Exception handler death? ret is 0x%x\n", ret); 528 - darling_sigexc_uninstall(); 529 - } 261 + kern_printf("sigexc: will forward signal to app handler (%p)\n", sig_handlers[linux_signum]); 530 262 531 - bsd_signum = _pthread_getspecific_direct(SIGEXC_TSD_KEY); 532 - _pthread_setspecific_direct(SIGEXC_TSD_KEY, 0); 533 - } 263 + // Update the signal mask to what the application actually wanted 264 + linux_sigset_t set = sig_masks[linux_signum]; 534 265 535 - // Get (possibly updated by GDB) register states from LKM 536 - if (ctxt != NULL) 537 - state_from_kernel(ctxt, thread); 266 + // Keep the current signal blocked, which is the default behavior 267 + if (!(sig_flags[linux_signum] & LINUX_SA_NODEFER)) 268 + set |= (1ull << (linux_signum-1)); 538 269 539 - // Pass the signal to the application handler or emulate the effects of the signal if SIG_DFL is set. 540 - if (bsd_signum) 541 - { 542 - const int linux_signum = signum_bsd_to_linux(bsd_signum); 270 + LINUX_SYSCALL(__NR_rt_sigprocmask, 2 /* LINUX_SIG_SETMASK */, 271 + &set, NULL, sizeof(linux_sigset_t)); 543 272 544 - bsd_sig_handler* handler = sig_handlers[linux_signum]; 545 - if (handler == SIG_DFL || handler == SIG_ERR) 273 + handler_linux_to_bsd(linux_signum, info, ctxt); 274 + } 275 + else 546 276 { 547 - /* 548 - switch (bsd_signum) 277 + if (sigprocess.signum == SIGTSTP || sigprocess.signum == SIGSTOP) 278 + { 279 + kern_printf("sigexc: emulating SIGTSTP/SIGSTOP\n"); 280 + LINUX_SYSCALL(__NR_kill, 0, LINUX_SIGSTOP); 281 + } 282 + else 549 283 { 550 - // We have to stop the process manually 551 - case SIGSTOP: 552 - case SIGTSTP: 553 - task_suspend(mach_task_self()); 554 - break; 284 + kern_printf("sigexc: emulating default signal effects\n"); 285 + // Set handler to SIG_DFL 286 + struct linux_sigaction sa; 287 + sa.sa_sigaction = (linux_sig_handler*) NULL; // SIG_DFL 288 + sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run 289 + sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK; 290 + sa.sa_restorer = sig_restorer; 291 + 292 + LINUX_SYSCALL(__NR_rt_sigaction, linux_signum, 293 + &sa, NULL, 294 + sizeof(sa.sa_mask)); 555 295 556 - // These signals do nothing by default 557 - case SIGCHLD: 558 - case SIGWINCH: 559 - case SIGURG: 560 - break; 561 - case SIGTRAP: 562 - if (ctxt == NULL) 563 - break; // This trap wasn't caused by int3, carry on 564 - 565 - // Other signals cause termination or core dump. 566 - default: 567 - { 568 - int linux_signum = signum_bsd_to_linux(bsd_signum); 569 - sys_exit(linux_signum); 570 - } 296 + // Resend signal to self 297 + LINUX_SYSCALL(__NR_kill, 0, linux_signum); 571 298 } 572 - */ 573 - } 574 - else if (handler != SIG_IGN) 575 - { 576 - handler_linux_to_bsd(linux_signum, info, ctxt); 577 299 } 578 300 } 579 - 301 + 580 302 kern_printf("sigexc: handler (%d) returning\n", linux_signum); 581 303 } 304 + 305 + #define DUMPREG(regname) kern_printf("sigexc: " #regname ": 0x%x\n", regs->regname); 582 306 583 307 #if defined(__x86_64__) 584 308 void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s) ··· 605 329 s->__fs = regs->fs; 606 330 s->__gs = regs->gs; 607 331 608 - kern_printf("sigexc: saving to kernel: RIP %p, eflags 0x%x\n", regs->rip, regs->efl); 332 + kern_printf("sigexc: saving to kernel:\n"); 333 + DUMPREG(rip); 334 + DUMPREG(efl); 335 + DUMPREG(rax); 336 + DUMPREG(rbx); 337 + DUMPREG(rcx); 338 + DUMPREG(rdx); 339 + DUMPREG(rdi); 340 + DUMPREG(rsi); 341 + DUMPREG(rbp); 342 + DUMPREG(rsp); 609 343 } 610 344 611 345 void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state64_t* s) ··· 651 385 regs->fs = s->__fs; 652 386 regs->gs = s->__gs; 653 387 654 - kern_printf("sigexc: Next RIP will be %p, eflags: 0x%x\n", regs->rip, regs->efl); // single step trace bit is 0x100 388 + kern_printf("sigexc: restored from kernel:\n"); 389 + DUMPREG(rip); 390 + DUMPREG(efl); 391 + DUMPREG(rax); 392 + DUMPREG(rbx); 393 + DUMPREG(rcx); 394 + DUMPREG(rdx); 395 + DUMPREG(rdi); 396 + DUMPREG(rsi); 397 + DUMPREG(rbp); 398 + DUMPREG(rsp); 655 399 } 656 400 657 401 void float_state_to_mcontext(const x86_float_state64_t* s, linux_fpregset_t fx) ··· 746 490 } 747 491 #endif 748 492 749 - #define LINUX_SI_QUEUE (-1) 750 - int linux_sigqueue(int pid, int rtsig, int value) 493 + void sigexc_thread_setup(void) 751 494 { 752 - struct linux_siginfo si; 495 + struct bsd_stack newstack = { 496 + .ss_size = sizeof(sigexc_altstack), 497 + .ss_flags = 0 498 + }; 753 499 754 - memset(&si, 0, sizeof(si)); 755 - si.si_signo = rtsig; 756 - si.si_code = LINUX_SI_QUEUE; 757 - si.si_pid = getpid(); 758 - si.si_uid = LINUX_SYSCALL(__NR_getuid); 759 - si.si_value = value; 760 - 761 - return LINUX_SYSCALL(__NR_rt_sigqueueinfo, pid, rtsig, &si); 500 + newstack.ss_sp = (void*) sys_mmap(NULL, sizeof(sigexc_altstack), PROT_READ | PROT_WRITE, 501 + MAP_ANON | MAP_PRIVATE, -1, 0); 502 + sys_sigaltstack(&newstack, NULL); 762 503 } 763 504 764 - int linux_sigqueue_thread(int pid, int tid, int rtsig, int value) 505 + void sigexc_thread_exit(void) 765 506 { 766 - struct linux_siginfo si; 767 - 768 - memset(&si, 0, sizeof(si)); 769 - si.si_signo = rtsig; 770 - si.si_code = LINUX_SI_QUEUE; 771 - si.si_pid = getpid(); 772 - si.si_uid = LINUX_SYSCALL(__NR_getuid); 773 - si.si_value = value; 507 + struct bsd_stack oldstack; 508 + sys_sigaltstack(NULL, &oldstack); 774 509 775 - return LINUX_SYSCALL(__NR_rt_tgsigqueueinfo, pid, tid, rtsig, &si); 510 + sys_munmap(oldstack.ss_sp, oldstack.ss_flags); 776 511 } 777 512
+3 -15
src/kernel/emulation/linux/signal/sigexc.h
··· 6 6 7 7 // NOTE: Keep these definitions up to date with lkm/darling/binfmt.c! 8 8 // Uses one of the below magic values to toggle the debugging state 9 - #define SIGNAL_SIGEXC_TOGGLE LINUX_SIGRTMIN 10 - 11 - // A BSD signal number is passed as value 12 - #define SIGNAL_SIGEXC_THUPDATE (LINUX_SIGRTMIN + 1) 13 - 14 - #define SIGNAL_THREAD_SUSPEND -100 15 - #define SIGNAL_THREAD_RESUME -101 16 - 17 - #define SIGRT_MAGIC_ENABLE_SIGEXC 0xdebdeb01 18 - #define SIGRT_MAGIC_DISABLE_SIGEXC 0xdebdeb00 9 + #define SIGNAL_SIGEXC_SUSPEND LINUX_SIGRTMIN 19 10 20 11 void sigexc_setup(void); 21 - 22 - // Is this process currently traced by a debugger? 23 - bool darling_am_i_ptraced(void); 24 12 25 13 // for PT_SIGEXC to handle this operation synchronously 26 14 void darling_sigexc_self(void); 27 15 void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt); 28 16 29 - int linux_sigqueue(int pid, int rtsig, int value); 30 - int linux_sigqueue_thread(int pid, int tid, int rtsig, int value); 17 + void sigexc_thread_setup(void); 18 + void sigexc_thread_exit(void); 31 19 32 20 #endif 33 21