diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2018-07-20 14:30:23 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-07-21 10:43:12 -0500 |
commit | 24122c7f4969adeeaeca3fb1656a31569e9aa59b (patch) | |
tree | 723eaf26f05f49f54df40fc6af0155f5eb880738 /kernel/signal.c | |
parent | 2118e1f53f6f0973a1d9a6a7dc9296959bf39ec0 (diff) | |
download | linux-24122c7f4969adeeaeca3fb1656a31569e9aa59b.tar.bz2 |
signal: Pass pid and pid type into send_sigqueue
Make the code more maintainable by performing more of the signal
related work in send_sigqueue.
A quick inspection of do_timer_create will show that this code path
does not lookup a thread group by a thread's pid. Making it safe
to find the task pointed to by it_pid with "pid_task(it_pid, type)";
This supports the changes needed in fork to tell if a signal was sent
to a single process or a group of processes.
Having the pid to task transition in signal.c will also make it easier
to sort out races with de_thread and and the thread group leader
exiting when it comes time to address that.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 8d8a940422a8..40feb14e276d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1664,17 +1664,20 @@ void sigqueue_free(struct sigqueue *q) __sigqueue_free(q); } -int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) +int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type) { int sig = q->info.si_signo; struct sigpending *pending; + struct task_struct *t; unsigned long flags; int ret, result; BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); ret = -1; - if (!likely(lock_task_sighand(t, &flags))) + rcu_read_lock(); + t = pid_task(pid, type); + if (!t || !likely(lock_task_sighand(t, &flags))) goto ret; ret = 1; /* the signal is ignored */ @@ -1696,15 +1699,16 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) q->info.si_overrun = 0; signalfd_notify(t, sig); - pending = group ? &t->signal->shared_pending : &t->pending; + pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending; list_add_tail(&q->list, &pending->list); sigaddset(&pending->signal, sig); - complete_signal(sig, t, group); + complete_signal(sig, t, type != PIDTYPE_PID); result = TRACE_SIGNAL_DELIVERED; out: - trace_signal_generate(sig, &q->info, t, group, result); + trace_signal_generate(sig, &q->info, t, type != PIDTYPE_PID, result); unlock_task_sighand(t, &flags); ret: + rcu_read_unlock(); return ret; } |