diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2018-08-16 04:20:46 +0200 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-08-16 06:03:20 +0200 |
commit | 84fe4cc09abc1a5ef3a282db3ed10f4d3f1e6a0b (patch) | |
tree | 8bca92f3c76e42aee803946cd458a0c081862884 /fs/fcntl.c | |
parent | signal: Don't restart fork when signals come in. (diff) | |
download | linux-84fe4cc09abc1a5ef3a282db3ed10f4d3f1e6a0b.tar.xz linux-84fe4cc09abc1a5ef3a282db3ed10f4d3f1e6a0b.zip |
signal: Don't send signals to tasks that don't exist
Recently syzbot reported crashes in send_sigio_to_task and
send_sigurg_to_task in linux-next. Despite finding a reproducer
syzbot apparently did not bisected this or otherwise track down the
offending commit in linux-next.
I happened to see this report and examined the code because I had
recently changed these functions as part of making PIDTYPE_TGID a real
pid type so that fork would does not need to restart when receiving a
signal. By examination I see that I spotted a bug in the code
that could explain the reported crashes.
When I took Oleg's suggestion and optimized send_sigurg and send_sigio
to only send to a single task when type is PIDTYPE_PID or PIDTYPE_TGID
I failed to handle pids that no longer point to tasks. The macro
do_each_pid_task simply iterates for zero iterations. With pid_task
an explicit NULL test is needed.
Update the code to include the missing NULL test.
Fixes: 019191342fec ("signal: Use PIDTYPE_TGID to clearly store where file signals will be sent")
Reported-by: syzkaller-bugs@googlegroups.com
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index a04accf6847f..4137d96534a6 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -791,7 +791,8 @@ void send_sigio(struct fown_struct *fown, int fd, int band) if (type <= PIDTYPE_TGID) { rcu_read_lock(); p = pid_task(pid, PIDTYPE_PID); - send_sigio_to_task(p, fown, fd, band, type); + if (p) + send_sigio_to_task(p, fown, fd, band, type); rcu_read_unlock(); } else { read_lock(&tasklist_lock); @@ -830,7 +831,8 @@ int send_sigurg(struct fown_struct *fown) if (type <= PIDTYPE_TGID) { rcu_read_lock(); p = pid_task(pid, PIDTYPE_PID); - send_sigurg_to_task(p, fown, type); + if (p) + send_sigurg_to_task(p, fown, type); rcu_read_unlock(); } else { read_lock(&tasklist_lock); |