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);
/*
* ---
{
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;
}
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;
}
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;
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;
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.
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);