Skip to content

Commit 66e58e0

Browse files
Alexei Starovoitovdavem330
authored andcommitted
bpfilter: fix race in pipe access
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: [email protected] Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ff26728 commit 66e58e0

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

net/bpfilter/bpfilter_kern.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,19 @@ static void shutdown_umh(struct umh_info *info)
2424
{
2525
struct task_struct *tsk;
2626

27+
if (!info->pid)
28+
return;
2729
tsk = pid_task(find_vpid(info->pid), PIDTYPE_PID);
2830
if (tsk)
2931
force_sig(SIGKILL, tsk);
3032
fput(info->pipe_to_umh);
3133
fput(info->pipe_from_umh);
34+
info->pid = 0;
3235
}
3336

3437
static void __stop_umh(void)
3538
{
36-
if (IS_ENABLED(CONFIG_INET) &&
37-
bpfilter_process_sockopt) {
39+
if (IS_ENABLED(CONFIG_INET)) {
3840
bpfilter_process_sockopt = NULL;
3941
shutdown_umh(&info);
4042
}
@@ -55,14 +57,16 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
5557
struct mbox_reply reply;
5658
loff_t pos;
5759
ssize_t n;
58-
int ret;
60+
int ret = -EFAULT;
5961

6062
req.is_set = is_set;
6163
req.pid = current->pid;
6264
req.cmd = optname;
6365
req.addr = (long)optval;
6466
req.len = optlen;
6567
mutex_lock(&bpfilter_lock);
68+
if (!info.pid)
69+
goto out;
6670
n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
6771
if (n != sizeof(req)) {
6872
pr_err("write fail %zd\n", n);

0 commit comments

Comments
 (0)