From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alexei Starovoitov Subject: [PATCH net] bpfilter: fix race in pipe access Date: Thu, 7 Jun 2018 15:31:14 -0700 Message-ID: <20180607223114.189970-1-ast@kernel.org> Mime-Version: 1.0 Content-Type: text/plain Cc: , , , , To: "David S . Miller" Return-path: Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:43838 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751938AbeFGWbQ (ORCPT ); Thu, 7 Jun 2018 18:31:16 -0400 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w57MTxdq019075 for ; Thu, 7 Jun 2018 15:31:16 -0700 Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2jfart8gph-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 07 Jun 2018 15:31:16 -0700 Sender: netdev-owner@vger.kernel.org List-ID: 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: d2ba09c17a06 ("net: add skeleton of bpfilter kernel module") Reported-by: syzbot+7ade6c94abb2774c0fee@syzkaller.appspotmail.com Signed-off-by: Alexei Starovoitov --- net/bpfilter/bpfilter_kern.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index b13d058f8c34..09522573f611 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -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); } @@ -55,7 +57,7 @@ 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; @@ -63,6 +65,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int 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); -- 2.9.5