From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40CBD2F5495 for ; Thu, 8 Oct 2026 04:28:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791433682; cv=none; b=YdhWGzOgSCzkwKCNEd9UAdXUInIHHJtECAS+ec9mJ3L/XHmf6GlB+Vybm4LKJdsXu42RXzVkGhnrHfBJ+OxIl8yU6R6CRYaslujLP4OVLtnlsSa9vdKv1UKGKi0KPyG6KhP+BzjBmyXubdObIwjgcQqleG2WsWD+YR+YB7WxX/Y= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791433682; c=relaxed/simple; bh=8yxs7YfzqvRVtKhBlK7Og0qPenjCv6X/6aJgf1antmU=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Type; b=QYCBO4pUq14dHztUjl/RoLj/cKjWiFZzSQx8oYQCkSZDH9iKMPfehc9FYa9+gBT0kI/lEVWmY3prbzlE2KdXqSrtsb4mqGDXmb6I4NwooqtX4OQN4WQ3DVpnkfbZJRYquEq4abDCBhZYWDU+4fipgyxb6nIvftFBgspvBUk6q9I= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=o0pPywgs; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="o0pPywgs" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-cc50ad2d650so1547657a12.1 for ; Wed, 07 Oct 2026 21:28:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791433679; x=1792038479; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=AZ778jZsa/l446uvpFqFZ0Ls/7AJyjZNff1uctiZNtk=; b=o0pPywgsOKUmeXzknQXH7kuIJh/IZK5y1/Fxhobje8t2HC0YhxpNfgGTh2aCpVvaEM 7mLXrnY4STfMPTsEJn88GzIXsiyTO65NLA0TC3NRzxARTA0ewUuujiYNHVRr+vfATBte 6CdOmHgzikifc7IkFY5iBu2wfVDRkodZYj/4GCuJJlwusl8ScliR42B8CizGaNKWIWbq L1K353qqHI5yGBcG/J/HVLHnlPtEpk+Letf9Ks/Fa/a4QmRpzpxjimipmlKUctHVJEds +9giLFYP5LCbhHdRZfEp4a56JJ6eQF49Z38/zB9Mtco8GeBfmrCVUPZM91gU1SMmtzUb 0C/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791433680; x=1792038480; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=AZ778jZsa/l446uvpFqFZ0Ls/7AJyjZNff1uctiZNtk=; b=thdyTgAOkxj0l5L2xs102SmfaJEMmSJ0288gBCWXZrjZt6IisaVMj6SJKUEhdqoaLW qIUU4baI/ORWVC8W0trKP9Rk044bZireqPZWbAS8QRCvjxQKmJUpCcxu8BpL2DPglqF4 glA4ilqDmwil3fT154FFOmq/vZcaH51ltvyCDQ1T7U0pLVwClw9H65iFzRbA5eQC4ka5 00wARI4sMg3Ssic18nhiX8ywDjwQEy7bPjt/bejFgpwPAM2HhEnVqeV78F84ubIjPVbq 9dEmcD9yGDKP6+0NFDO3Hp8CjopH/Hw7neAb8HLk+3YyUc7zKb84Ss+7sNHsau09GzKY Wukg== X-Forwarded-Encrypted: i=1; AKwUvBzo8xoVAqFSEZjz2zK24IyU09vcItvM+Xoz4930cridpTh8HoCQ4D51jz/ujDNLvE24Zy9m5vaGCf/ZRfc=@vger.kernel.org X-Gm-Message-State: AFq9FYLWuc5A0s11cH9fxhabEB7PKJ/F7Wf9zrsC9dITwM0o6cKZEK7r sld5Ar1r8HWbFXCsV+e9z/2v9BybTmmzV+VMWLZIsHuKuhLa+/CJCFZF X-Gm-Gg: AYBFou1eI0dOb1XJZ4oO5oqsBIbxeYXvPLygwgm/Dk75IMJLNjhmeNgU1sjR1sXSY1S RpxH2I+J0hK/wBg7wKCVYnezVCf2XsWadBTgrI/XjT23StP+f2gD2CzyHYrxI+zQMpBMJKXR8Tk x8TWTSdPh3s85AKDqtkQhsMpNnlHJeJTWn5+2zChRCerRJIF144dAeWjnUJnYV9lrz4PkeJ25e3 FVo2E5+En1u4sczhV4NLlMaAZm6Lm0TkeHUvtJ9AV6S37EfSvKOrpJNWC6hj4UXlJo11g+02ugx J9xY3s2mqz646ZzoPOfTCz9MFKFvkKl/g/Tlv7EtWjJjDAzP+LmWrdXrHYFLMD8r2RIt11ijFT2 umqRDy4+Z134Up42a+ChZODbm1H1u8SNmDzoZOmZsRrZVp1FlQ6F1hyqd8HFfxfu6ukMmylHc6r LCZgAsf3dDypB0S2UHvClFY9rZXAseqQtaBUTaHjC6tisIqwAkTpAqTwGIycGuGnlneg== X-Received: by 2002:a17:90b:1e48:b0:3a2:aec0:6bc2 with SMTP id 98e67ed59e1d1-3a8a11974b2mr4050881a91.53.1791433679554; Wed, 07 Oct 2026 21:27:59 -0700 (PDT) Received: from localhost ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3aa0cbea8d3sm2319217a91.16.2026.10.07.21.27.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Oct 2026 21:27:59 -0700 (PDT) From: Cen Zhang To: marcel@holtmann.org, luiz.dentz@gmail.com Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, baijiaju1990@gmail.com, jjzuming@gmail.com, zzzccc427@gmail.com Subject: [PATCH] Bluetooth: 6LoWPAN: Serialize multicast sends with peer removal Date: Thu, 8 Oct 2026 12:27:52 +0800 Message-Id: X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A peer's channel must remain alive until send_mcast_pkt() finishes using it. The multicast walk protects the lowpan_peer with RCU, but peer_del() defers only the peer allocation. On disconnect, l2cap_chan_del() drops the connection-list reference, chan_close_cb() removes the peer and drops the original channel reference, and l2cap_conn_del() drops its temporary reference. A ready channel can then be freed while multicast transmit still holds the peer, causing send_pkt() to write chan->data after free. Another peer can keep the interface up, so the last-peer shutdown does not drain this transmission. Hold devices_lock across the multicast walk and send_pkt() calls so that peer removal cannot release the channel reference until the send finishes. Use the bottom-half-safe variants for all devices_lock critical sections because transmit runs in softirq context. This prevents transmit from interrupting a process-context lock holder on the same CPU and deadlocking. The LE send path uses atomic allocations and does not acquire the channel or connection mutexes, preserving the existing lock order and teardown sequence. The reported access and release path were: [Thu Oct 1 11:52:32 2026] BUG: KASAN: slab-use-after-free in send_pkt+0x2c5/0x300 [Thu Oct 1 11:52:32 2026] Write of size 8 at addr ffff88810be0f4a0 by task python3/535 [...] [Thu Oct 1 11:52:32 2026] Freed by task 502: [...] [Thu Oct 1 11:52:32 2026] l2cap_chan_put+0x273/0x3a0 [Thu Oct 1 11:52:32 2026] l2cap_conn_del+0x36d/0x770 [Thu Oct 1 11:52:32 2026] l2cap_disconn_cfm+0x87/0xd0 [Thu Oct 1 11:52:32 2026] hci_disconn_complete_evt+0x319/0xa30 [...] Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") Assisted-by: LLM Signed-off-by: Cen Zhang --- diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 836add41f5..8732132c47 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -471,6 +471,11 @@ struct lowpan_btle_dev *entry; int err = 0; + /* + * Peer removal drops the channel reference, so RCU alone is not + * enough. + */ + spin_lock_bh(&devices_lock); rcu_read_lock(); list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { @@ -502,6 +507,7 @@ } rcu_read_unlock(); + spin_unlock_bh(&devices_lock); return err; } @@ -657,10 +663,10 @@ lowpan_iphc_uncompress_eui48_lladdr(&peer->peer_addr, peer->lladdr); - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); INIT_LIST_HEAD(&peer->list); peer_add(dev, peer); - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); /* Notifying peers about us needs to be done without locks held */ if (new_netdev) @@ -695,17 +701,17 @@ (*dev)->hdev = chan->conn->hcon->hdev; INIT_LIST_HEAD(&(*dev)->peers); - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); INIT_LIST_HEAD(&(*dev)->list); list_add_rcu(&(*dev)->list, &bt_6lowpan_devices); - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); err = lowpan_register_netdev(netdev, LOWPAN_LLTYPE_BTLE); if (err < 0) { BT_INFO("register_netdev failed %d", err); - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); list_del_rcu(&(*dev)->list); - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); free_netdev(netdev); goto out; } @@ -788,7 +794,7 @@ BT_DBG("chan %p conn %p", chan, chan->conn); - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { dev = lowpan_btle_dev(entry->netdev); @@ -808,7 +814,7 @@ } if (!err && last && dev && !atomic_read(&dev->peer_count)) { - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); cancel_delayed_work_sync(&dev->notify_peers); @@ -817,7 +823,7 @@ INIT_WORK(&entry->delete_netdev, delete_netdev); schedule_work(&entry->delete_netdev); } else { - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); } } @@ -918,18 +924,18 @@ BT_DBG("conn %p dst type %u", conn, dst_type); - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); peer = lookup_peer(conn); if (!peer) { - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); return -ENOENT; } chan = peer->chan; l2cap_chan_hold(chan); - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); BT_DBG("peer %p chan %p", peer, chan); @@ -1053,7 +1059,7 @@ nchans = 0; - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { list_for_each_entry_rcu(peer, &entry->peers, list) { @@ -1070,7 +1076,7 @@ } done: - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); for (i = 0; i < nchans; ++i) { l2cap_chan_close_unlocked(chans[i], ENOENT); @@ -1195,7 +1201,7 @@ struct lowpan_btle_dev *entry; struct lowpan_peer *peer; - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); list_for_each_entry(entry, &bt_6lowpan_devices, list) { list_for_each_entry(peer, &entry->peers, list) @@ -1203,7 +1209,7 @@ &peer->chan->dst, peer->chan->dst_type); } - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); return 0; } @@ -1269,7 +1275,7 @@ switch (event) { case NETDEV_UNREGISTER: - spin_lock(&devices_lock); + spin_lock_bh(&devices_lock); list_for_each_entry(entry, &bt_6lowpan_devices, list) { if (entry->netdev == netdev) { BT_DBG("Unregistered netdev %s %p", @@ -1278,7 +1284,7 @@ break; } } - spin_unlock(&devices_lock); + spin_unlock_bh(&devices_lock); break; }