diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2003-07-07 01:31:32 -0700 |
|---|---|---|
| committer | Steve French <cifs.adm@hostme.bitkeeper.com> | 2003-07-07 01:31:32 -0700 |
| commit | 62133cb1109242fde586f965cff48c85eaa7f52b (patch) | |
| tree | 07656df61505697ba63078a7b1b0bf76890c1288 | |
| parent | f597d1debdd1f5314a0177cb68d1d0ced960929b (diff) | |
[PATCH] tgkill patch for safe inter-thread signals
This is the updated versions of the patch Ingo sent some time ago to
implement a new tgkill() syscall which specifies the target thread
without any possibility of ambiguity or thread ID wrap races, by passing
in both the thread group _and_ the thread ID as the arguments.
This is really needed since many/most people still run with limited PID
ranges (maybe due to legacy apps breaking) and the PID reuse can cause
problems.
| -rw-r--r-- | arch/i386/kernel/entry.S | 1 | ||||
| -rw-r--r-- | include/asm-i386/unistd.h | 3 | ||||
| -rw-r--r-- | kernel/signal.c | 50 |
3 files changed, 51 insertions, 3 deletions
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 5aef7a47a383..dafcae8663c8 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -876,5 +876,6 @@ ENTRY(sys_call_table) .long sys_clock_nanosleep .long sys_statfs64 .long sys_fstatfs64 + .long sys_tgkill nr_syscalls=(.-sys_call_table)/4 diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index b1bdc016eed5..f39e505e3eb4 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -275,8 +275,9 @@ #define __NR_clock_nanosleep (__NR_timer_create+8) #define __NR_statfs64 268 #define __NR_fstatfs64 269 +#define __NR_tgkill 270 -#define NR_syscalls 270 +#define NR_syscalls 271 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */ diff --git a/kernel/signal.c b/kernel/signal.c index dbefbea7623e..7ac72191b30b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -579,8 +579,8 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s) /* * Bad permissions for sending the signal */ -static inline int check_kill_permission(int sig, struct siginfo *info, - struct task_struct *t) +static int check_kill_permission(int sig, struct siginfo *info, + struct task_struct *t) { int error = -EINVAL; if (sig < 0 || sig > _NSIG) @@ -2088,6 +2088,52 @@ sys_kill(int pid, int sig) return kill_something_info(sig, &info, pid); } +/** + * sys_tkill - send signal to one specific thread + * @tgid: the thread group ID of the thread + * @pid: the PID of the thread + * @sig: signal to be sent + * + * This syscall also checks the tgid and returns -ESRCH even if the PID + * exists but it's not belonging to the target process anymore. This + * method solves the problem of threads exiting and PIDs getting reused. + */ +asmlinkage long sys_tgkill(int tgid, int pid, int sig) +{ + struct siginfo info; + int error; + struct task_struct *p; + + /* This is only valid for single tasks */ + if (pid <= 0 || tgid <= 0) + return -EINVAL; + + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_TKILL; + info.si_pid = current->tgid; + info.si_uid = current->uid; + + read_lock(&tasklist_lock); + p = find_task_by_pid(pid); + error = -ESRCH; + if (p && (p->tgid == tgid)) { + error = check_kill_permission(sig, &info, p); + /* + * The null signal is a permissions and process existence + * probe. No signal is actually delivered. + */ + if (!error && sig && p->sighand) { + spin_lock_irq(&p->sighand->siglock); + handle_stop_signal(sig, p); + error = specific_send_sig_info(sig, &info, p); + spin_unlock_irq(&p->sighand->siglock); + } + } + read_unlock(&tasklist_lock); + return error; +} + /* * Send a signal to only one task, even if it's a CLONE_THREAD task. */ |
