Skip to content

Commit

Permalink
bpfilter: fix race in pipe access
Browse files Browse the repository at this point in the history
syzbot reported the following crash
[  338.293946] bpfilter: read fail -512
[  338.304515] kasan: GPF could be caused by NULL-ptr deref or user memory access
[  338.311863] general protection fault: 0000 [#1] SMP KASAN
[  338.344360] RIP: 0010:__vfs_write+0x4a6/0x960
[  338.426363] Call Trace:
[  338.456967]  __kernel_write+0x10c/0x380
[  338.460928]  __bpfilter_process_sockopt+0x1d8/0x35b
[  338.487103]  bpfilter_mbox_request+0x4d/0xb0
[  338.491492]  bpfilter_ip_get_sockopt+0x6b/0x90

This can happen when multiple cpus trying to talk to user mode process
via bpfilter_mbox_request(). One cpu grabs the mutex while another goes to
sleep on the same mutex. Then former cpu sees that umh pipe is down and
shuts down the pipes. Later cpu finally acquires the mutex and crashes
on freed pipe.
Fix the race by using info.pid as an indicator that umh and pipes are healthy
and check it after acquiring the mutex.

Fixes: d2ba09c ("net: add skeleton of bpfilter kernel module")
Reported-by: syzbot+7ade6c94abb2774c0fee@syzkaller.appspotmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alexei Starovoitov authored and David S. Miller committed Jun 8, 2018
1 parent ff26728 commit 66e58e0
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions net/bpfilter/bpfilter_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ static void shutdown_umh(struct umh_info *info)
{
struct task_struct *tsk;

if (!info->pid)
return;
tsk = pid_task(find_vpid(info->pid), PIDTYPE_PID);
if (tsk)
force_sig(SIGKILL, tsk);
fput(info->pipe_to_umh);
fput(info->pipe_from_umh);
info->pid = 0;
}

static void __stop_umh(void)
{
if (IS_ENABLED(CONFIG_INET) &&
bpfilter_process_sockopt) {
if (IS_ENABLED(CONFIG_INET)) {
bpfilter_process_sockopt = NULL;
shutdown_umh(&info);
}
Expand All @@ -55,14 +57,16 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
struct mbox_reply reply;
loff_t pos;
ssize_t n;
int ret;
int ret = -EFAULT;

req.is_set = is_set;
req.pid = current->pid;
req.cmd = optname;
req.addr = (long)optval;
req.len = optlen;
mutex_lock(&bpfilter_lock);
if (!info.pid)
goto out;
n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
if (n != sizeof(req)) {
pr_err("write fail %zd\n", n);
Expand Down

0 comments on commit 66e58e0

Please sign in to comment.