]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sig.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / kern / kern_sig.c
index 7fa64636b72ce7c74b07b37cd6c6109b46dd7bcc..5d38f292ed97459ae279dbe462a841435ef5e4e0 100644 (file)
@@ -126,6 +126,8 @@ extern int thread_enable_fpe(thread_t act, int onoff);
 extern thread_t        port_name_to_thread(mach_port_name_t port_name);
 extern kern_return_t get_signalact(task_t , thread_t *, int);
 extern unsigned int get_useraddr(void);
+extern boolean_t task_did_exec(task_t task);
+extern boolean_t task_is_exec_copy(task_t task);
 
 /*
  * ---
@@ -1641,18 +1643,11 @@ terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t
 {
        proc_t target_proc = PROC_NULL;
        kauth_cred_t cur_cred = kauth_cred_get();
-       int signum = SIGKILL;
 
        os_reason_t signal_reason = OS_REASON_NULL;
 
        AUDIT_ARG(pid, target_pid);
-       if ((target_pid <= 0) || (cur_proc->p_pid == target_pid)) {
-               return EINVAL;
-       }
-
-       if (reason_namespace == OS_REASON_INVALID ||
-               reason_namespace > OS_REASON_MAX_VALID_NAMESPACE) {
-
+       if ((target_pid <= 0)) {
                return EINVAL;
        }
 
@@ -1663,7 +1658,7 @@ terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t
 
        AUDIT_ARG(process, target_proc);
 
-       if (!cansignal(cur_proc, cur_cred, target_proc, signum, 0)) {
+       if (!cansignal(cur_proc, cur_cred, target_proc, SIGKILL, 0)) {
                proc_rele(target_proc);
                return EPERM;
        }
@@ -1675,7 +1670,17 @@ terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t
        signal_reason = build_userspace_exit_reason(reason_namespace, reason_code, payload, payload_size,
                                                        reason_string, reason_flags);
 
-       psignal_with_reason(target_proc, signum, signal_reason);
+       if (target_pid == cur_proc->p_pid) {
+               /*
+                * psignal_thread_with_reason() will pend a SIGKILL on the specified thread or
+                * return if the thread and/or task are already terminating. Either way, the
+                * current thread won't return to userspace.
+                */
+               psignal_thread_with_reason(target_proc, current_thread(), SIGKILL, signal_reason);
+       } else {
+               psignal_with_reason(target_proc, SIGKILL, signal_reason);
+       }
+
        proc_rele(target_proc);
 
        return 0;
@@ -2036,7 +2041,7 @@ build_signal_reason(int signum, const char *procname)
        reason_buffer_size_estimate = kcdata_estimate_required_buffer_size(2, sizeof(sender_proc->p_name) +
                                                                                sizeof(sender_proc->p_pid));
 
-       ret = os_reason_alloc_buffer(signal_reason, reason_buffer_size_estimate);
+       ret = os_reason_alloc_buffer_noblock(signal_reason, reason_buffer_size_estimate);
        if (ret != 0) {
                printf("build_signal_reason: unable to allocate signal reason buffer.\n");
                return signal_reason;
@@ -2654,6 +2659,12 @@ psignal_try_thread_with_reason(proc_t p, thread_t thread, int signum, struct os_
        psignal_internal(p, TASK_NULL, thread, PSIG_TRY_THREAD, signum, signal_reason);
 }
 
+void
+psignal_thread_with_reason(proc_t p, thread_t thread, int signum, struct os_reason *signal_reason)
+{
+       psignal_internal(p, TASK_NULL, thread, PSIG_THREAD, signum, signal_reason);
+}
+
 /*
  * If the current process has received a signal (should be caught or cause
  * termination, should interrupt current syscall), return the signal number.
@@ -3319,6 +3330,11 @@ bsd_ast(thread_t thread)
        if (p == NULL)
                return;
 
+       /* don't run bsd ast on exec copy or exec'ed tasks */
+       if (task_did_exec(current_task()) || task_is_exec_copy(current_task())) {
+               return;
+       }
+
        if ((p->p_flag & P_OWEUPC) && (p->p_flag & P_PROFIL)) {
                pc = get_useraddr();
                addupc_task(p, pc, 1);