Received: by 2002:a05:6a10:c604:0:0:0:0 with SMTP id y4csp270285pxt; Fri, 6 Aug 2021 01:21:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx6qM05808oX6tH7Hjjuvs2/TPAOVVuI4OldGJhFBHvpYu4esVxKKOsHlDyWTtXUSExhYJj X-Received: by 2002:a05:6402:35cf:: with SMTP id z15mr11742497edc.27.1628238105172; Fri, 06 Aug 2021 01:21:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628238105; cv=none; d=google.com; s=arc-20160816; b=D34sAC8OfSvmZlkRx9bqMVYRquSe3/nS7ojfKp47vfx3zrdF4erzDRnN69gyReS/M2 CnYur7wwVqAtJikK9jF2r60qpU4KO3iAtrslZeHf49qWI8PK9G2sRL/KxFputypu4ljf nAG54d2DN6Yun9Q2AgHwzV3FiiIeNHRLax0qMgFsvsh+fQiXpUYJcRjbBN2QL8JeGvuD rYw6hWiXXsMwq4EiKyFczmRyjq2+4U6KDx264ERNGuLTAe++ta6LWuP72iuTnJ6k5WkG gJrO3R1PxIBhRzw4yhrdMd4AkboYvRDJfrC8Pbmsujx81pWBsG+JjR0EVZeXGPMqD1DC Kksg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ZODmH/hfb20rmx8/Uv4nVODwVxaQ5RZXlGpylC8GBF0=; b=GahhlwExMJfzK/aZIW7KbE/nO0vTDM4xhJbHzEL8yiHQCYHTQYbPcV68OnNAQfejzS /9axSvMohZ1ykH7832xXY+JFn7+eB4iQR7HfeSKg5oP+GMeUeVp+z9RyJ9QjurirPU7m dMwt9EyyD9COEpbG2c+uaZ/z73fJe0AjBbco5oa8tzxJrl0wLR2D1Hc8CM9ej0cQpRwH y4ACY0OYqod1I1QZl7i9COCVb3DuiHxwwW26T9iOwRQlBR2X2ivqv+fnR5unp7N+3xKN 3xRRS/DYbT7OGhSwCUUjEVsaheWrCdrT4KJvHNb97dNZMfXvj9B54T66Jgmq6wWTAVOZ gnxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=XEpFkRe9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dk22si7860096edb.537.2021.08.06.01.21.21; Fri, 06 Aug 2021 01:21:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=XEpFkRe9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243528AbhHFIPg (ORCPT + 99 others); Fri, 6 Aug 2021 04:15:36 -0400 Received: from mail.kernel.org ([198.145.29.99]:44752 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243780AbhHFIPM (ORCPT ); Fri, 6 Aug 2021 04:15:12 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5191D61167; Fri, 6 Aug 2021 08:14:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1628237696; bh=cqrmoG3pWPnwv2ePXPLEv+hxWnGFEpxQzJAktEFRZgk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XEpFkRe9YxRCXr3rR3x7WW6RSvABTezdU0G6kxYlq4vBE9hPELiTg1/vn9OtbNsFI rUdg/5j4y7OjO5lo/WPpz4l66MfojVnQHrqHMzU2YbHqgl/88TIW51iaF4yn2/IeGU QGGr0W7D2U/0W/Avl5wa62Qe/U9whepqBdHaSYbs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ziyang Xuan , Oliver Hartkopp , Marc Kleine-Budde Subject: [PATCH 4.4 6/6] can: raw: raw_setsockopt(): fix raw_rcv panic for sock UAF Date: Fri, 6 Aug 2021 10:14:38 +0200 Message-Id: <20210806081109.139571597@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210806081108.939164003@linuxfoundation.org> References: <20210806081108.939164003@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ziyang Xuan commit 54f93336d000229f72c26d8a3f69dd256b744528 upstream. We get a bug during ltp can_filter test as following. =========================================== [60919.264984] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 [60919.265223] PGD 8000003dda726067 P4D 8000003dda726067 PUD 3dda727067 PMD 0 [60919.265443] Oops: 0000 [#1] SMP PTI [60919.265550] CPU: 30 PID: 3638365 Comm: can_filter Kdump: loaded Tainted: G W 4.19.90+ #1 [60919.266068] RIP: 0010:selinux_socket_sock_rcv_skb+0x3e/0x200 [60919.293289] RSP: 0018:ffff8d53bfc03cf8 EFLAGS: 00010246 [60919.307140] RAX: 0000000000000000 RBX: 000000000000001d RCX: 0000000000000007 [60919.320756] RDX: 0000000000000001 RSI: ffff8d5104a8ed00 RDI: ffff8d53bfc03d30 [60919.334319] RBP: ffff8d9338056800 R08: ffff8d53bfc29d80 R09: 0000000000000001 [60919.347969] R10: ffff8d53bfc03ec0 R11: ffffb8526ef47c98 R12: ffff8d53bfc03d30 [60919.350320] perf: interrupt took too long (3063 > 2500), lowering kernel.perf_event_max_sample_rate to 65000 [60919.361148] R13: 0000000000000001 R14: ffff8d53bcf90000 R15: 0000000000000000 [60919.361151] FS: 00007fb78b6b3600(0000) GS:ffff8d53bfc00000(0000) knlGS:0000000000000000 [60919.400812] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [60919.413730] CR2: 0000000000000010 CR3: 0000003e3f784006 CR4: 00000000007606e0 [60919.426479] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [60919.439339] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [60919.451608] PKRU: 55555554 [60919.463622] Call Trace: [60919.475617] [60919.487122] ? update_load_avg+0x89/0x5d0 [60919.498478] ? update_load_avg+0x89/0x5d0 [60919.509822] ? account_entity_enqueue+0xc5/0xf0 [60919.520709] security_sock_rcv_skb+0x2a/0x40 [60919.531413] sk_filter_trim_cap+0x47/0x1b0 [60919.542178] ? kmem_cache_alloc+0x38/0x1b0 [60919.552444] sock_queue_rcv_skb+0x17/0x30 [60919.562477] raw_rcv+0x110/0x190 [can_raw] [60919.572539] can_rcv_filter+0xbc/0x1b0 [can] [60919.582173] can_receive+0x6b/0xb0 [can] [60919.591595] can_rcv+0x31/0x70 [can] [60919.600783] __netif_receive_skb_one_core+0x5a/0x80 [60919.609864] process_backlog+0x9b/0x150 [60919.618691] net_rx_action+0x156/0x400 [60919.627310] ? sched_clock_cpu+0xc/0xa0 [60919.635714] __do_softirq+0xe8/0x2e9 [60919.644161] do_softirq_own_stack+0x2a/0x40 [60919.652154] [60919.659899] do_softirq.part.17+0x4f/0x60 [60919.667475] __local_bh_enable_ip+0x60/0x70 [60919.675089] __dev_queue_xmit+0x539/0x920 [60919.682267] ? finish_wait+0x80/0x80 [60919.689218] ? finish_wait+0x80/0x80 [60919.695886] ? sock_alloc_send_pskb+0x211/0x230 [60919.702395] ? can_send+0xe5/0x1f0 [can] [60919.708882] can_send+0xe5/0x1f0 [can] [60919.715037] raw_sendmsg+0x16d/0x268 [can_raw] It's because raw_setsockopt() concurrently with unregister_netdevice_many(). Concurrent scenario as following. cpu0 cpu1 raw_bind raw_setsockopt unregister_netdevice_many unlist_netdevice dev_get_by_index raw_notifier raw_enable_filters ...... can_rx_register can_rcv_list_find(..., net->can.rx_alldev_list) ...... sock_close raw_release(sock_a) ...... can_receive can_rcv_filter(net->can.rx_alldev_list, ...) raw_rcv(skb, sock_a) BUG After unlist_netdevice(), dev_get_by_index() return NULL in raw_setsockopt(). Function raw_enable_filters() will add sock and can_filter to net->can.rx_alldev_list. Then the sock is closed. Followed by, we sock_sendmsg() to a new vcan device use the same can_filter. Protocol stack match the old receiver whose sock has been released on net->can.rx_alldev_list in can_rcv_filter(). Function raw_rcv() uses the freed sock. UAF BUG is triggered. We can find that the key issue is that net_device has not been protected in raw_setsockopt(). Use rtnl_lock to protect net_device in raw_setsockopt(). Fixes: c18ce101f2e4 ("[CAN]: Add raw protocol") Link: https://lore.kernel.org/r/20210722070819.1048263-1-william.xuanziyang@huawei.com Cc: linux-stable Signed-off-by: Ziyang Xuan Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- net/can/raw.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) --- a/net/can/raw.c +++ b/net/can/raw.c @@ -541,10 +541,18 @@ static int raw_setsockopt(struct socket return -EFAULT; } + rtnl_lock(); lock_sock(sk); - if (ro->bound && ro->ifindex) + if (ro->bound && ro->ifindex) { dev = dev_get_by_index(&init_net, ro->ifindex); + if (!dev) { + if (count > 1) + kfree(filter); + err = -ENODEV; + goto out_fil; + } + } if (ro->bound) { /* (try to) register the new filters */ @@ -581,6 +589,7 @@ static int raw_setsockopt(struct socket dev_put(dev); release_sock(sk); + rtnl_unlock(); break; @@ -593,10 +602,16 @@ static int raw_setsockopt(struct socket err_mask &= CAN_ERR_MASK; + rtnl_lock(); lock_sock(sk); - if (ro->bound && ro->ifindex) + if (ro->bound && ro->ifindex) { dev = dev_get_by_index(&init_net, ro->ifindex); + if (!dev) { + err = -ENODEV; + goto out_err; + } + } /* remove current error mask */ if (ro->bound) { @@ -618,6 +633,7 @@ static int raw_setsockopt(struct socket dev_put(dev); release_sock(sk); + rtnl_unlock(); break;