diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 4 | ||||
| -rw-r--r-- | kernel/ksyms.c | 4 | ||||
| -rw-r--r-- | kernel/signal.c | 72 | ||||
| -rw-r--r-- | kernel/sysctl.c | 2 |
4 files changed, 76 insertions, 6 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 8c10cad0e021..bfbae1b15439 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -724,10 +724,10 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start, /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); - /* CLONE_PARENT and CLONE_THREAD re-use the old parent */ + /* CLONE_PARENT re-uses the old parent */ p->p_opptr = current->p_opptr; p->p_pptr = current->p_pptr; - if (!(clone_flags & (CLONE_PARENT | CLONE_THREAD))) { + if (!(clone_flags & CLONE_PARENT)) { p->p_opptr = current; if (!(p->ptrace & PT_PTRACED)) p->p_pptr = current; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index c271a8e6f6fc..42ebfe7f746c 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -251,6 +251,7 @@ EXPORT_SYMBOL(vfs_rename); EXPORT_SYMBOL(vfs_statfs); EXPORT_SYMBOL(generic_read_dir); EXPORT_SYMBOL(generic_file_llseek); +EXPORT_SYMBOL(remote_llseek); EXPORT_SYMBOL(no_llseek); EXPORT_SYMBOL(__pollwait); EXPORT_SYMBOL(poll_freewait); @@ -274,6 +275,9 @@ EXPORT_SYMBOL(lock_may_write); EXPORT_SYMBOL(dcache_readdir); EXPORT_SYMBOL(fd_install); EXPORT_SYMBOL(put_unused_fd); +EXPORT_SYMBOL(get_sb_bdev); +EXPORT_SYMBOL(get_sb_nodev); +EXPORT_SYMBOL(get_sb_single); /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ EXPORT_SYMBOL(default_llseek); diff --git a/kernel/signal.c b/kernel/signal.c index 3741c8a4a6ac..d648cff08eb6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -142,6 +142,35 @@ flush_signal_handlers(struct task_struct *t) } } +/* + * sig_exit - cause the current task to exit due to a signal. + */ + +void +sig_exit(int sig, int exit_code, struct siginfo *info) +{ + struct task_struct *t; + + sigaddset(¤t->pending.signal, sig); + recalc_sigpending(current); + current->flags |= PF_SIGNALED; + + /* Propagate the signal to all the tasks in + * our thread group + */ + if (info && (unsigned long)info != 1 + && info->si_code != SI_TKILL) { + read_lock(&tasklist_lock); + for_each_thread(t) { + force_sig_info(sig, info, t); + } + read_unlock(&tasklist_lock); + } + + do_exit(exit_code); + /* NOTREACHED */ +} + /* Notify the system that a driver wants to block all signals for this * process, and wants to be notified if any signals at all were to be * sent/acted upon. If the notifier routine returns non-zero, then the @@ -589,7 +618,7 @@ kill_pg_info(int sig, struct siginfo *info, pid_t pgrp) retval = -ESRCH; read_lock(&tasklist_lock); for_each_task(p) { - if (p->pgrp == pgrp) { + if (p->pgrp == pgrp && thread_group_leader(p)) { int err = send_sig_info(sig, info, p); if (retval) retval = err; @@ -636,8 +665,15 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) read_lock(&tasklist_lock); p = find_task_by_pid(pid); error = -ESRCH; - if (p) + if (p) { + if (!thread_group_leader(p)) { + struct task_struct *tg; + tg = find_task_by_pid(p->tgid); + if (tg) + p = tg; + } error = send_sig_info(sig, info, p); + } read_unlock(&tasklist_lock); return error; } @@ -660,7 +696,7 @@ static int kill_something_info(int sig, struct siginfo *info, int pid) read_lock(&tasklist_lock); for_each_task(p) { - if (p->pid > 1 && p != current) { + if (p->pid > 1 && p != current && thread_group_leader(p)) { int err = send_sig_info(sig, info, p); ++count; if (err != -EPERM) @@ -985,6 +1021,36 @@ sys_kill(int pid, int sig) return kill_something_info(sig, &info, pid); } +/* + * Kill only one task, even if it's a CLONE_THREAD task. + */ +asmlinkage long +sys_tkill(int pid, int sig) +{ + struct siginfo info; + int error; + struct task_struct *p; + + /* This is only valid for single tasks */ + if (pid <= 0) + return -EINVAL; + + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_TKILL; + info.si_pid = current->pid; + info.si_uid = current->uid; + + read_lock(&tasklist_lock); + p = find_task_by_pid(pid); + error = -ESRCH; + if (p) { + error = send_sig_info(sig, &info, p); + } + read_unlock(&tasklist_lock); + return error; +} + asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) { diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9035ae798d0e..21a5c8fe6543 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -677,7 +677,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char * buf, size_t res; ssize_t error; - de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip; + de = PDE(file->f_dentry->d_inode); if (!de || !de->data) return -ENOTDIR; table = (struct ctl_table *) de->data; |
