diff --git a/src/kernel/emulation/linux/CMakeLists.txt b/src/kernel/emulation/linux/CMakeLists.txt index fe39d196d..cac658344 100644 --- a/src/kernel/emulation/linux/CMakeLists.txt +++ b/src/kernel/emulation/linux/CMakeLists.txt @@ -157,6 +157,7 @@ set(emulation_sources bsdthread/disable_threadsignal.c bsdthread/workq_kernreturn.c bsdthread/workq_open.c + bsdthread/pthread_kill.c psynch/psynch_mutexwait.c psynch/psynch_mutexdrop.c syscalls-table.S diff --git a/src/kernel/emulation/linux/bsdthread/pthread_kill.c b/src/kernel/emulation/linux/bsdthread/pthread_kill.c new file mode 100644 index 000000000..a5cac5a8b --- /dev/null +++ b/src/kernel/emulation/linux/bsdthread/pthread_kill.c @@ -0,0 +1,21 @@ +#include "pthread_kill.h" +#include "../base.h" +#include "../errno.h" +#include "../signal/duct_signals.h" +#include "../../../../../platform-include/sys/errno.h" +#include +#include "../../../mach_server/client/lkm.h" +#include "../../../../lkm/api.h" +#include "../simple.h" + +long sys_pthread_kill(int thread_port, int sig) +{ + struct pthread_kill_args args; + + args.thread_port = thread_port; + args.sig = signum_bsd_to_linux(sig); + + return lkm_call(NR_pthread_kill_trap, &args); + +} + diff --git a/src/kernel/emulation/linux/bsdthread/pthread_kill.h b/src/kernel/emulation/linux/bsdthread/pthread_kill.h new file mode 100644 index 000000000..23f970657 --- /dev/null +++ b/src/kernel/emulation/linux/bsdthread/pthread_kill.h @@ -0,0 +1,7 @@ +#ifndef PTHREAD_KILL_H +#define PTHREAD_KILL_H + +long sys_pthread_kill(int thread_port, int sig); + +#endif + diff --git a/src/kernel/emulation/linux/syscalls.c b/src/kernel/emulation/linux/syscalls.c index 52ecc4b4a..ac6a7d323 100644 --- a/src/kernel/emulation/linux/syscalls.c +++ b/src/kernel/emulation/linux/syscalls.c @@ -117,6 +117,7 @@ #include "psynch/psynch_mutexdrop.h" #include "bsdthread/workq_kernreturn.h" #include "bsdthread/workq_open.h" +#include "bsdthread/pthread_kill.h" void* __bsd_syscall_table[512] = { [1] = sys_exit, @@ -237,6 +238,7 @@ void* __bsd_syscall_table[512] = { [244] = sys_posix_spawn, [301] = sys_psynch_mutexwait, [302] = sys_psynch_mutexdrop, + [328] = sys_pthread_kill, [329] = sys_sigprocmask, // __pthread_sigmask [331] = sys_disable_threadsignal, [334] = sys_semwait_signal, diff --git a/src/lkm/Makefile b/src/lkm/Makefile index be7aa3930..87947dd3a 100644 --- a/src/lkm/Makefile +++ b/src/lkm/Makefile @@ -22,7 +22,7 @@ ifneq ($(KERNELRELEASE),) mig/taskServer.o mig/thread_actServer.o \ servers/thread_act.o \ mig/duct.o proc_entry.o bsd_ioctl.o \ - psynch/psynch_mutex.o + psynch/psynch_mutex.o psynch/pthread_kill.o # Otherwise we were called directly from the command # line; invoke the kernel build system. diff --git a/src/lkm/api.h b/src/lkm/api.h index e7510fc38..2992cc4d2 100644 --- a/src/lkm/api.h +++ b/src/lkm/api.h @@ -46,6 +46,7 @@ enum { NR_get_api_version = DARLING_MACH_API_BASE, NR_bsdthread_terminate_trap, NR_psynch_mutexwait_trap, NR_psynch_mutexdrop_trap, + NR_pthread_kill_trap, }; struct mach_port_mod_refs_args @@ -167,4 +168,10 @@ struct psynch_mutexdrop_args uint32_t flags; }; +struct pthread_kill_args +{ + int thread_port; + int sig; +}; + #endif diff --git a/src/lkm/psynch/pthread_kill.c b/src/lkm/psynch/pthread_kill.c new file mode 100644 index 000000000..1b34480a9 --- /dev/null +++ b/src/lkm/psynch/pthread_kill.c @@ -0,0 +1,87 @@ +/* + * Darling Mach Linux Kernel Module + * Copyright (C) 2015 Lubos Dolezel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "../mach_includes.h" +#include "pthread_kill.h" +#include +#include +#include +#include +#include +#include "../servers/thread_act.h" +#include "../ipc_types.h" +#include "../ipc_space.h" +#include "../ipc_right.h" +#include "../darling_task.h" + +int pthread_kill_trap(mach_task_t* task, + struct pthread_kill_args* in_args) +{ + struct pthread_kill_args args; + darling_mach_port_right_t* right = NULL; + int ret; + pid_t tid; + struct siginfo info; + struct task_struct *t; + + if (copy_from_user(&args, in_args, sizeof(args))) + return -EFAULT; + + ipc_space_lock(&task->namespace); + right = ipc_space_lookup(&task->namespace, args.thread_port); + + ipc_space_unlock(&task->namespace); + if (right == NULL) + { + ret = -EINVAL; + goto err; + } + + tid = get_thread_pid(right->port); + ipc_port_unlock(right->port); + + if (tid == 0) + { + // Not a thread port + ret = -EINVAL; + goto err; + } + + rcu_read_lock(); + t = pid_task(find_pid_ns(tid, &init_pid_ns), PIDTYPE_PID); + + if (t == NULL) + { + rcu_read_unlock(); + ret = -ESRCH; + goto err; + } + + info.si_signo = args.sig; + info.si_code = SI_TKILL; + info.si_pid = t->tgid; + info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); + info.si_errno = 0; + + ret = send_sig_info(args.sig, &info, t); + rcu_read_unlock(); + +err: + return ret; +} diff --git a/src/lkm/psynch/pthread_kill.h b/src/lkm/psynch/pthread_kill.h new file mode 100644 index 000000000..c5310a258 --- /dev/null +++ b/src/lkm/psynch/pthread_kill.h @@ -0,0 +1,30 @@ +/* + * Darling Mach Linux Kernel Module + * Copyright (C) 2015 Lubos Dolezel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTHREAD_KILL_H +#define PTHREAD_KILL_H +#include "../api.h" +#include "../ipc_types.h" + +int pthread_kill_trap(mach_task_t* task, + struct pthread_kill_args* args); + + +#endif /* PTHREAD_KILL_H */ + diff --git a/src/lkm/servers/thread_act.c b/src/lkm/servers/thread_act.c index c70617bda..70cb1a8c3 100644 --- a/src/lkm/servers/thread_act.c +++ b/src/lkm/servers/thread_act.c @@ -56,6 +56,9 @@ pid_t get_thread_pid(darling_mach_port_t* port) { struct thread_private* priv; + if (port->server_port.subsystem != (mig_subsystem_t) &thread_act_subsystem) + return 0; + priv = (struct thread_private*) port->server_port.private_data; return priv->thread_id; } diff --git a/src/lkm/traps.c b/src/lkm/traps.c index 7246a8c74..d1feaadc2 100644 --- a/src/lkm/traps.c +++ b/src/lkm/traps.c @@ -43,6 +43,7 @@ #include "servers/thread_act.h" #include "primitives/semaphore.h" #include "psynch/psynch_mutex.h" +#include "psynch/pthread_kill.h" MODULE_LICENSE("GPL"); @@ -79,6 +80,7 @@ static const trap_handler mach_traps[30] = { [sc(NR_bsdthread_terminate_trap)] = (trap_handler) bsdthread_terminate_trap, [sc(NR_psynch_mutexwait_trap)] = (trap_handler) psynch_mutexwait_trap, [sc(NR_psynch_mutexdrop_trap)] = (trap_handler) psynch_mutexdrop_trap, + [sc(NR_pthread_kill_trap)] = (trap_handler) pthread_kill_trap, }; #undef sc