From: Sasha Levin Date: Sat, 28 Mar 2026 13:08:44 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v6.6.131~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8cc5cd7ab82fd4836290bb76211627ff73a3d233;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-5.10/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..956ad96f61 --- /dev/null +++ b/queue-5.10/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From f01b752bc3336971283f1279b95315fe9e6daa66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index de4606d2eb643..95f7e363c2f6a 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3522,7 +3522,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3587,12 +3587,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-5.10/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..40b9ca3f81 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From c4a64ec3dcc71e34de53fdeff37697f0228cce57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 3010044f0810b..a27a6ab6c2b61 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -1780,8 +1780,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-5.10/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..dfae1ccb21 --- /dev/null +++ b/queue-5.10/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From 69a6f29b6d1509c524a4d055a13b71cadd7e5a79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 7495ca34c9e7e..ee107360e3bc2 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-5.10/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..77a04533a2 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From f957edce1ee4cfc9471ba2f8a0eeb68e396a8289 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index bca96302e59e5..e7af7faf558e8 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2543,6 +2543,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4526,14 +4529,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-5.10/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..f140e0a4f0 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From d6c8fabc92897bfd82e0505ba15b53ebe0b095f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 5465b537f0e72..9e071db3b649f 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1637,6 +1637,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-5.10/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..3f0dbbace2 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 5e669f52fe7df053f5154cbb2ebe30a8193523af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index ed113cfdce23b..bca96302e59e5 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7660,6 +7660,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-5.10/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-5.10/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..8069a6af05 --- /dev/null +++ b/queue-5.10/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From c01b99bd32e1579cc9ac8214c28c5952f11101a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index 3e77a52709aaa..97c48f350ce0b 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -469,7 +469,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -573,7 +573,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 2be4a239f31e4..550d46d1c60a4 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -200,7 +200,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-5.10/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-5.10/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..206326a575 --- /dev/null +++ b/queue-5.10/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 4b8f3e47f05d9b314903c655dd30ad5bff3914ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index fb48f8ba5dcc8..d79acecd50dfe 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -200,8 +200,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-5.10/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-5.10/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..ac5a71a589 --- /dev/null +++ b/queue-5.10/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 3784616e31534b4e519e302c51f0b995368d1ebd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 295bc1799002a..0d5fc4f8c6adb 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -275,10 +275,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 9df910dfc348a..a1d20dd4be3c7 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -310,10 +310,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-5.10/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-5.10/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..03a1af6f87 --- /dev/null +++ b/queue-5.10/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From d0033e6bf646f64588805e01f8e398583a8b64cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index cf98a00296edf..c934cae9f0d41 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -549,6 +549,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-5.10/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-5.10/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..b5174702a8 --- /dev/null +++ b/queue-5.10/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From f67bae13e13edb5417b3467d46d344e5087707c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 4614fae54ed7f..1c9b2d67c3ed4 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3147,6 +3147,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-5.10/net-macb-use-the-current-queue-number-for-stats.patch b/queue-5.10/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..0b2b2af2d9 --- /dev/null +++ b/queue-5.10/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From 3eb9120a596381e0bd27429135c52f864683cac0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index f49e4e0494db3..bdbb05a95519b 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -2786,7 +2786,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-5.10/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-5.10/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..788334c8b3 --- /dev/null +++ b/queue-5.10/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From b8d2e9384b66ac40bda3fea07c84c807fc17d9a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 72cf13bbf3dd3..70cc8854b8d53 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -146,11 +146,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -169,6 +173,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-5.10/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-5.10/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..6110fce16a --- /dev/null +++ b/queue-5.10/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From 1e408937ceee3ed8a371e35963d50a5b952c07d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index 5f20538cbf990..0845905520f8c 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -129,9 +129,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-5.10/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-5.10/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..1180728055 --- /dev/null +++ b/queue-5.10/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From c1e9f2a79599b809234270469deb9e7c0574e1ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 9fe2c5b3523c5..8d35e17a0f7e7 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -860,8 +860,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -875,17 +875,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2618,7 +2612,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index c1d02c0b4f005..c43d9819df067 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1249,9 +1249,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1278,10 +1278,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-5.10/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-5.10/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..7b8595d88d --- /dev/null +++ b/queue-5.10/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From b7c7b7cb493d470da6f413a73958360f91232cd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-5.10/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-5.10/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..eebf02fc52 --- /dev/null +++ b/queue-5.10/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From 4b99857c12a81b147701463652f9186b56917778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 516a9f05a87a7..e53e225d9489f 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -607,11 +607,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-5.10/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-5.10/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..ee15a44e19 --- /dev/null +++ b/queue-5.10/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From 3b3d60848b769ab685253f5ded061ef9bf4e8d93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 5db17768ec2ad..dcb0a5e592775 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-5.10/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-5.10/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..5f47317723 --- /dev/null +++ b/queue-5.10/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From dbb5a344697b3be2b6a32c3367df50fcf94c8879 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 80c09070ea9fa..3a71ba47224c4 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -632,15 +632,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-5.10/netfilter-nft_payload-reject-out-of-range-attributes.patch b/queue-5.10/netfilter-nft_payload-reject-out-of-range-attributes.patch new file mode 100644 index 0000000000..02d3502108 --- /dev/null +++ b/queue-5.10/netfilter-nft_payload-reject-out-of-range-attributes.patch @@ -0,0 +1,45 @@ +From 11270cec37ab6fe42f8065cf0b076162b6baf19b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:09:37 +0200 +Subject: netfilter: nft_payload: reject out-of-range attributes via policy + +From: Florian Westphal + +[ Upstream commit e7af210e6dd0de633d3f4850383310cf57473bc8 ] + +Now that nla_policy allows range checks for bigendian data make use of +this to reject such attributes. At this time, reject happens later +from the init or select_ops callbacks, but its prone to errors. + +In the future, new attributes can be handled via NLA_POLICY_MAX_BE +and exiting ones can be converted one by one. + +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_payload.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index f607cd7f203ad..f59ad5fb42575 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -119,10 +119,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { + [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, ++ [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), + [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, ++ [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), + [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, + }; + +-- +2.51.0 + diff --git a/queue-5.10/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch b/queue-5.10/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch new file mode 100644 index 0000000000..4b60beabf2 --- /dev/null +++ b/queue-5.10/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch @@ -0,0 +1,85 @@ +From b2fa0464536e0ce30b2de571885ccd340cc691a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jul 2023 09:52:29 +0200 +Subject: netlink: allow be16 and be32 types in all uint policy checks + +From: Florian Westphal + +[ Upstream commit 5fac9b7c16c50c6c7699517f582b56e3743f453a ] + +__NLA_IS_BEINT_TYPE(tp) isn't useful. NLA_BE16/32 are identical to +NLA_U16/32, the only difference is that it tells the netlink validation +functions that byteorder conversion might be needed before comparing +the value to the policy min/max ones. + +After this change all policy macros that can be used with UINT types, +such as NLA_POLICY_MASK() can also be used with NLA_BE16/32. + +This will be used to validate nf_tables flag attributes which +are in bigendian byte order. + +Signed-off-by: Florian Westphal +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 10 +++------- + lib/nlattr.c | 6 ++++++ + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index fed93bd3424ff..d3d088dc0ae80 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -374,12 +374,11 @@ struct nla_policy { + #define NLA_POLICY_BITFIELD32(valid) \ + { .type = NLA_BITFIELD32, .bitfield32_valid = valid } + +-#define __NLA_IS_UINT_TYPE(tp) \ +- (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) ++#define __NLA_IS_UINT_TYPE(tp) \ ++ (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || \ ++ tp == NLA_U64 || tp == NLA_BE16 || tp == NLA_BE32) + #define __NLA_IS_SINT_TYPE(tp) \ + (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) +-#define __NLA_IS_BEINT_TYPE(tp) \ +- (tp == NLA_BE16 || tp == NLA_BE32) + + #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) + #define NLA_ENSURE_UINT_TYPE(tp) \ +@@ -393,7 +392,6 @@ struct nla_policy { + #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ + (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ + __NLA_IS_SINT_TYPE(tp) || \ +- __NLA_IS_BEINT_TYPE(tp) || \ + tp == NLA_MSECS || \ + tp == NLA_BINARY) + tp) + #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ +@@ -401,8 +399,6 @@ struct nla_policy { + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) +-#define NLA_ENSURE_BEINT_TYPE(tp) \ +- (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) + + #define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index 440beb1626be3..d88ba6feb8c3d 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -355,6 +355,12 @@ static int nla_validate_mask(const struct nla_policy *pt, + case NLA_U64: + value = nla_get_u64(nla); + break; ++ case NLA_BE16: ++ value = ntohs(nla_get_be16(nla)); ++ break; ++ case NLA_BE32: ++ value = ntohl(nla_get_be32(nla)); ++ break; + default: + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-5.10/netlink-hide-validation-union-fields-from-kdoc.patch b/queue-5.10/netlink-hide-validation-union-fields-from-kdoc.patch new file mode 100644 index 0000000000..7a93631597 --- /dev/null +++ b/queue-5.10/netlink-hide-validation-union-fields-from-kdoc.patch @@ -0,0 +1,77 @@ +From dc85f476dec4a4eb202b66290738bedf33bfc9f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 14:21:07 -0700 +Subject: netlink: hide validation union fields from kdoc + +From: Jakub Kicinski + +[ Upstream commit 7354c9024f2835f6122ed9612e21ab379df050f9 ] + +Mark the validation fields as private, users shouldn't set +them directly and they are too complicated to explain in +a more succinct way (there's already a long explanation +in the comment above). + +The strict_start_type field is set directly and has a dedicated +comment so move that above the "private" section. + +Link: https://lore.kernel.org/r/20221027212107.2639255-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 45370f84d6442..9d5d6aa690c56 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -317,19 +317,10 @@ struct nla_policy { + u8 validation_type; + u16 len; + union { +- const u32 bitfield32_valid; +- const u32 mask; +- const char *reject_message; +- const struct nla_policy *nested_policy; +- struct netlink_range_validation *range; +- struct netlink_range_validation_signed *range_signed; +- struct { +- s16 min, max; +- u8 network_byte_order:1; +- }; +- int (*validate)(const struct nlattr *attr, +- struct netlink_ext_ack *extack); +- /* This entry is special, and used for the attribute at index 0 ++ /** ++ * @strict_start_type: first attribute to validate strictly ++ * ++ * This entry is special, and used for the attribute at index 0 + * only, and specifies special data about the policy, namely it + * specifies the "boundary type" where strict length validation + * starts for any attribute types >= this value, also, strict +@@ -348,6 +339,20 @@ struct nla_policy { + * was added to enforce strict validation from thereon. + */ + u16 strict_start_type; ++ ++ /* private: use NLA_POLICY_*() to set */ ++ const u32 bitfield32_valid; ++ const u32 mask; ++ const char *reject_message; ++ const struct nla_policy *nested_policy; ++ struct netlink_range_validation *range; ++ struct netlink_range_validation_signed *range_signed; ++ struct { ++ s16 min, max; ++ u8 network_byte_order:1; ++ }; ++ int (*validate)(const struct nlattr *attr, ++ struct netlink_ext_ack *extack); + }; + }; + +-- +2.51.0 + diff --git a/queue-5.10/netlink-introduce-bigendian-integer-types.patch b/queue-5.10/netlink-introduce-bigendian-integer-types.patch new file mode 100644 index 0000000000..fb47a30976 --- /dev/null +++ b/queue-5.10/netlink-introduce-bigendian-integer-types.patch @@ -0,0 +1,220 @@ +From 0ce17906913190c23f97c4c70418d677fce5d8fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 13:34:07 +0100 +Subject: netlink: introduce bigendian integer types + +From: Florian Westphal + +[ Upstream commit ecaf75ffd5f5db320d8b1da0198eef5a5ce64a3f ] + +Jakub reported that the addition of the "network_byte_order" +member in struct nla_policy increases size of 32bit platforms. + +Instead of scraping the bit from elsewhere Johannes suggested +to add explicit NLA_BE types instead, so do this here. + +NLA_POLICY_MAX_BE() macro is removed again, there is no need +for it: NLA_POLICY_MAX(NLA_BE.., ..) will do the right thing. + +NLA_BE64 can be added later. + +Fixes: 08724ef69907 ("netlink: introduce NLA_POLICY_MAX_BE") +Reported-by: Jakub Kicinski +Suggested-by: Johannes Berg +Signed-off-by: Florian Westphal +Link: https://lore.kernel.org/r/20221031123407.9158-1-fw@strlen.de +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 19 +++++++++-------- + lib/nlattr.c | 41 ++++++++++++++----------------------- + net/netfilter/nft_payload.c | 6 +++--- + 3 files changed, 28 insertions(+), 38 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 9d5d6aa690c56..fed93bd3424ff 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -181,6 +181,8 @@ enum { + NLA_S64, + NLA_BITFIELD32, + NLA_REJECT, ++ NLA_BE16, ++ NLA_BE32, + __NLA_TYPE_MAX, + }; + +@@ -231,6 +233,7 @@ enum nla_policy_validation { + * NLA_U32, NLA_U64, + * NLA_S8, NLA_S16, + * NLA_S32, NLA_S64, ++ * NLA_BE16, NLA_BE32, + * NLA_MSECS Leaving the length field zero will verify the + * given type fits, using it verifies minimum length + * just like "All other" +@@ -261,6 +264,8 @@ enum nla_policy_validation { + * NLA_U16, + * NLA_U32, + * NLA_U64, ++ * NLA_BE16, ++ * NLA_BE32, + * NLA_S8, + * NLA_S16, + * NLA_S32, +@@ -349,7 +354,6 @@ struct nla_policy { + struct netlink_range_validation_signed *range_signed; + struct { + s16 min, max; +- u8 network_byte_order:1; + }; + int (*validate)(const struct nlattr *attr, + struct netlink_ext_ack *extack); +@@ -374,6 +378,8 @@ struct nla_policy { + (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) + #define __NLA_IS_SINT_TYPE(tp) \ + (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) ++#define __NLA_IS_BEINT_TYPE(tp) \ ++ (tp == NLA_BE16 || tp == NLA_BE32) + + #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) + #define NLA_ENSURE_UINT_TYPE(tp) \ +@@ -387,6 +393,7 @@ struct nla_policy { + #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ + (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ + __NLA_IS_SINT_TYPE(tp) || \ ++ __NLA_IS_BEINT_TYPE(tp) || \ + tp == NLA_MSECS || \ + tp == NLA_BINARY) + tp) + #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ +@@ -394,6 +401,8 @@ struct nla_policy { + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) ++#define NLA_ENSURE_BEINT_TYPE(tp) \ ++ (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) + + #define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ +@@ -424,14 +433,6 @@ struct nla_policy { + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MAX, \ + .max = _max, \ +- .network_byte_order = 0, \ +-} +- +-#define NLA_POLICY_MAX_BE(tp, _max) { \ +- .type = NLA_ENSURE_UINT_TYPE(tp), \ +- .validation_type = NLA_VALIDATE_MAX, \ +- .max = _max, \ +- .network_byte_order = 1, \ + } + + #define NLA_POLICY_MASK(tp, _mask) { \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index 8825ad4f45bfe..440beb1626be3 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -125,10 +125,12 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + range->max = U8_MAX; + break; + case NLA_U16: ++ case NLA_BE16: + case NLA_BINARY: + range->max = U16_MAX; + break; + case NLA_U32: ++ case NLA_BE32: + range->max = U32_MAX; + break; + case NLA_U64: +@@ -160,31 +162,6 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + } + } + +-static u64 nla_get_attr_bo(const struct nla_policy *pt, +- const struct nlattr *nla) +-{ +- switch (pt->type) { +- case NLA_U16: +- if (pt->network_byte_order) +- return ntohs(nla_get_be16(nla)); +- +- return nla_get_u16(nla); +- case NLA_U32: +- if (pt->network_byte_order) +- return ntohl(nla_get_be32(nla)); +- +- return nla_get_u32(nla); +- case NLA_U64: +- if (pt->network_byte_order) +- return be64_to_cpu(nla_get_be64(nla)); +- +- return nla_get_u64(nla); +- } +- +- WARN_ON_ONCE(1); +- return 0; +-} +- + static int nla_validate_range_unsigned(const struct nla_policy *pt, + const struct nlattr *nla, + struct netlink_ext_ack *extack, +@@ -198,9 +175,13 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + value = nla_get_u8(nla); + break; + case NLA_U16: ++ value = nla_get_u16(nla); ++ break; + case NLA_U32: ++ value = nla_get_u32(nla); ++ break; + case NLA_U64: +- value = nla_get_attr_bo(pt, nla); ++ value = nla_get_u64(nla); + break; + case NLA_MSECS: + value = nla_get_u64(nla); +@@ -208,6 +189,12 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + case NLA_BINARY: + value = nla_len(nla); + break; ++ case NLA_BE16: ++ value = ntohs(nla_get_be16(nla)); ++ break; ++ case NLA_BE32: ++ value = ntohl(nla_get_be32(nla)); ++ break; + default: + return -EINVAL; + } +@@ -335,6 +322,8 @@ static int nla_validate_int_range(const struct nla_policy *pt, + case NLA_U64: + case NLA_MSECS: + case NLA_BINARY: ++ case NLA_BE16: ++ case NLA_BE32: + return nla_validate_range_unsigned(pt, nla, extack, validate); + case NLA_S8: + case NLA_S16: +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index f59ad5fb42575..ae0c4cd2dd1c5 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -119,10 +119,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { + [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), +- [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), ++ [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, + }; + +-- +2.51.0 + diff --git a/queue-5.10/netlink-introduce-nla_policy_max_be.patch b/queue-5.10/netlink-introduce-nla_policy_max_be.patch new file mode 100644 index 0000000000..aaaeeec9da --- /dev/null +++ b/queue-5.10/netlink-introduce-nla_policy_max_be.patch @@ -0,0 +1,109 @@ +From b203988f5ec543b7755f2676057977949ce2d681 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:09:36 +0200 +Subject: netlink: introduce NLA_POLICY_MAX_BE + +From: Florian Westphal + +[ Upstream commit 08724ef69907214ce622344fe4945412e38368f0 ] + +netlink allows to specify allowed ranges for integer types. +Unfortunately, nfnetlink passes integers in big endian, so the existing +NLA_POLICY_MAX() cannot be used. + +At the moment, nfnetlink users, such as nf_tables, need to resort to +programmatic checking via helpers such as nft_parse_u32_check(). + +This is both cumbersome and error prone. This adds NLA_POLICY_MAX_BE +which adds range check support for BE16, BE32 and BE64 integers. + +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 9 +++++++++ + lib/nlattr.c | 31 +++++++++++++++++++++++++++---- + 2 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 7356f41d23bac..45370f84d6442 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -325,6 +325,7 @@ struct nla_policy { + struct netlink_range_validation_signed *range_signed; + struct { + s16 min, max; ++ u8 network_byte_order:1; + }; + int (*validate)(const struct nlattr *attr, + struct netlink_ext_ack *extack); +@@ -418,6 +419,14 @@ struct nla_policy { + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MAX, \ + .max = _max, \ ++ .network_byte_order = 0, \ ++} ++ ++#define NLA_POLICY_MAX_BE(tp, _max) { \ ++ .type = NLA_ENSURE_UINT_TYPE(tp), \ ++ .validation_type = NLA_VALIDATE_MAX, \ ++ .max = _max, \ ++ .network_byte_order = 1, \ + } + + #define NLA_POLICY_MASK(tp, _mask) { \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index aa8fc4371e930..8825ad4f45bfe 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -160,6 +160,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + } + } + ++static u64 nla_get_attr_bo(const struct nla_policy *pt, ++ const struct nlattr *nla) ++{ ++ switch (pt->type) { ++ case NLA_U16: ++ if (pt->network_byte_order) ++ return ntohs(nla_get_be16(nla)); ++ ++ return nla_get_u16(nla); ++ case NLA_U32: ++ if (pt->network_byte_order) ++ return ntohl(nla_get_be32(nla)); ++ ++ return nla_get_u32(nla); ++ case NLA_U64: ++ if (pt->network_byte_order) ++ return be64_to_cpu(nla_get_be64(nla)); ++ ++ return nla_get_u64(nla); ++ } ++ ++ WARN_ON_ONCE(1); ++ return 0; ++} ++ + static int nla_validate_range_unsigned(const struct nla_policy *pt, + const struct nlattr *nla, + struct netlink_ext_ack *extack, +@@ -173,12 +198,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + value = nla_get_u8(nla); + break; + case NLA_U16: +- value = nla_get_u16(nla); +- break; + case NLA_U32: +- value = nla_get_u32(nla); +- break; + case NLA_U64: ++ value = nla_get_attr_bo(pt, nla); ++ break; + case NLA_MSECS: + value = nla_get_u64(nla); + break; +-- +2.51.0 + diff --git a/queue-5.10/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-5.10/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..8e19903ced --- /dev/null +++ b/queue-5.10/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From 0dc8f5984c43228c3267679f72b6805666fa3e4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 873c9073e4111..78472b1929705 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -562,8 +562,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -575,13 +574,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); +@@ -591,6 +590,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-5.10/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-5.10/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..29a91bbeed --- /dev/null +++ b/queue-5.10/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From 4521e12013844e53a4a8b448620d75bead66f5ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 54f952620b214..2185fd5596fc7 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2911,6 +2911,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-5.10/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-5.10/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..3a652f40ed --- /dev/null +++ b/queue-5.10/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From 947c058d301fe86c1638b1a256b118379c75507d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index 730581d130649..8045475583186 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1111,9 +1111,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-5.10/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-5.10/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..705320986b --- /dev/null +++ b/queue-5.10/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From 62fbfa17edc94111632dd0169f5eb016e90eda07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index 0d46706afd2da..d8a9a215a14cd 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-5.10/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-5.10/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..e16936003e --- /dev/null +++ b/queue-5.10/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From e14fc7e676f871fc9498c5c49fa53788f6b766eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 99337557408b5..c58510d7ea0d8 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -501,11 +501,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 038d104989..31c7947db6 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -246,3 +246,34 @@ asoc-fsl_easrc-fix-event-generation-in-fsl_easrc_iec.patch asoc-fsl_easrc-fix-event-generation-in-fsl_easrc_iec.patch-25677 dma-buf-include-ioctl.h-in-uapi-header.patch alsa-hda-realtek-add-headset-jack-quirk-for-thinkpad.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +xfrm-fix-the-usage-of-skb-sk.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +af_key-validate-families-in-pfkey_send_migrate.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netlink-introduce-nla_policy_max_be.patch +netfilter-nft_payload-reject-out-of-range-attributes.patch +netlink-hide-validation-union-fields-from-kdoc.patch +netlink-introduce-bigendian-integer-types.patch +netlink-allow-be16-and-be32-types-in-all-uint-policy.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-5.10/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-5.10/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..3675ab887e --- /dev/null +++ b/queue-5.10/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From 249338df95e094a53d468de84ba45d6bd7748b10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index b1243edf7f3a0..02d1d8d1fdea4 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -1736,6 +1736,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-5.10/xfrm-fix-the-usage-of-skb-sk.patch b/queue-5.10/xfrm-fix-the-usage-of-skb-sk.patch new file mode 100644 index 0000000000..c3b156d962 --- /dev/null +++ b/queue-5.10/xfrm-fix-the-usage-of-skb-sk.patch @@ -0,0 +1,135 @@ +From 32717a86dc91fb3b97ae8a0b0a13fb7f91bcfde7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 11:46:03 +0100 +Subject: xfrm: Fix the usage of skb->sk + +From: Steffen Klassert + +[ Upstream commit 1620c88887b16940e00dbe57dd38c74eda9bad9e ] + +xfrm assumed to always have a full socket at skb->sk. +This is not always true, so fix it by converting to a +full socket before it is used. + +Signed-off-by: Steffen Klassert +Reviewed-by: Eric Dumazet +Stable-dep-of: 0c0eef8ccd24 ("esp: fix skb leak with espintcp and async crypto") +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 2 +- + net/ipv6/esp6.c | 2 +- + net/ipv6/xfrm6_output.c | 4 ++-- + net/xfrm/xfrm_interface_core.c | 2 +- + net/xfrm/xfrm_output.c | 7 ++++--- + net/xfrm/xfrm_policy.c | 2 +- + 6 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index adfefcd88bbcc..295bc1799002a 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -278,7 +278,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 39154531d4559..9df910dfc348a 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -313,7 +313,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c +index ee349c2438782..a8fc778ce465c 100644 +--- a/net/ipv6/xfrm6_output.c ++++ b/net/ipv6/xfrm6_output.c +@@ -89,14 +89,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + toobig = skb->len > mtu && !skb_is_gso(skb); + +- if (toobig && xfrm6_local_dontfrag(skb->sk)) { ++ if (toobig && xfrm6_local_dontfrag(sk)) { + xfrm6_local_rxpmtu(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; + } else if (toobig && xfrm6_noneed_fragment(skb)) { + skb->ignore_df = 1; + goto skip_frag; +- } else if (!skb->ignore_df && toobig && skb->sk) { ++ } else if (!skb->ignore_df && toobig && sk) { + xfrm_local_error(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; +diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c +index 9eaf0174d9981..fc5967ccaddca 100644 +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -368,7 +368,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + skb_dst_set(skb, dst); + skb->dev = tdev; + +- err = dst_output(xi->net, skb->sk, skb); ++ err = dst_output(xi->net, skb_to_full_sk(skb), skb); + if (net_xmit_eval(err) == 0) { + struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); + +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 40f7a98abdd1c..7c588973cfa1b 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -645,7 +645,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) + !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { + skb->protocol = htons(ETH_P_IP); + +- if (skb->sk) ++ if (skb->sk && sk_fullsock(skb->sk)) + xfrm_local_error(skb, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, +@@ -681,6 +681,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + { + int mtu, ret = 0; + struct dst_entry *dst = skb_dst(skb); ++ struct sock *sk = skb_to_full_sk(skb); + + if (skb->ignore_df) + goto out; +@@ -695,9 +696,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + skb->dev = dst->dev; + skb->protocol = htons(ETH_P_IPV6); + +- if (xfrm6_local_dontfrag(skb->sk)) ++ if (xfrm6_local_dontfrag(sk)) + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); +- else if (skb->sk) ++ else if (sk) + xfrm_local_error(skb, mtu); + else + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 64b971bb1d36a..c4ebfaa0b2ed0 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2858,7 +2858,7 @@ static void xfrm_policy_queue_process(struct timer_list *t) + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- dst_output(net, skb->sk, skb); ++ dst_output(net, skb_to_full_sk(skb), skb); + } + + out: +-- +2.51.0 + diff --git a/queue-5.15/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-5.15/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..3e1ba00e12 --- /dev/null +++ b/queue-5.15/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From 910a5fb7b03b37abd70141b05c4f68b7232603ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 925fe4f89966b..638333f1b8c7d 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-5.15/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..3fcc7ef4fa --- /dev/null +++ b/queue-5.15/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From 43dd4c67f3c9e9837567146c5f0c6a28bc83a3db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a79fd106fad7a..12bcc07e2e502 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -1845,8 +1845,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-5.15/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..bd3ae1ce84 --- /dev/null +++ b/queue-5.15/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From e52576cda4d3df12b9467fe6abaeb3d502f8dc0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index e4e5b26e2c33b..02c2122b452a8 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-5.15/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..e7c61cfe84 --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From 008a1ab9843c8bb8db4ad196d2ab255ccdf308a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index e69c6041437b0..ef71a43ab702d 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2541,6 +2541,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4515,14 +4518,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-5.15/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..03e2bcd00a --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From e14530e0d5cfa846ebb4b9fb5695d5febdcc7ec1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 8e2e6d1a6dd15..faaa5e4525c07 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1649,6 +1649,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-5.15/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..061c8aab19 --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 1fd0845bbe582175356d965bb1ca19759252281c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 5010c200b2c41..e69c6041437b0 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7650,6 +7650,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-5.15/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..2a6a7e4aca --- /dev/null +++ b/queue-5.15/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From 82d9401c98ead4811dfc998a8855d252b0af2acd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index d98648bcc1a85..d0ef74c45914c 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -311,7 +311,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -320,11 +320,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-5.15/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-5.15/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..c84aa948db --- /dev/null +++ b/queue-5.15/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From e8f97af84704784ef2c42380462ea47b9e58ae7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index edf01b73d2878..85b01dea76dff 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -469,7 +469,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -573,7 +573,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 0533a3c4ff0e1..f81f8a698071e 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-5.15/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-5.15/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..e48216ca58 --- /dev/null +++ b/queue-5.15/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 48baa8363721a7e5babf930b170f1eba2e9baa28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index d7b91f82b0dce..96f4d63390aea 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -218,8 +218,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-5.15/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-5.15/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..2c10cc7d80 --- /dev/null +++ b/queue-5.15/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 65faa611caa6633e9182bcbcb94ce4fecadb57da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 272b64fd09eed..c69cee3feff00 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -275,10 +275,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 57e48dd905a48..e87f3f8f06818 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -312,10 +312,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-5.15/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-5.15/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..aa8762bb9b --- /dev/null +++ b/queue-5.15/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From 7652796845de9d17ec6c5eb5c7d4bb7f9e0a5a7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index cdc3c55fab6ac..0e44e616c6da1 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1763,13 +1763,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-5.15/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-5.15/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..be725cd18d --- /dev/null +++ b/queue-5.15/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From 2ac9b69e21a1ad49e9604272ffa8c8aea9a43aba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index d62c188c87480..89234613ef806 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -566,6 +566,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-5.15/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-5.15/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..4ef0d0ff6f --- /dev/null +++ b/queue-5.15/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From e6ffa252ffed59bea6cb26e85694aba8c4d49d93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 6e7c94fa02bd9..d1ad069271f8b 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3147,6 +3147,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-5.15/net-macb-use-the-current-queue-number-for-stats.patch b/queue-5.15/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..60cc91a1fc --- /dev/null +++ b/queue-5.15/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From 68d8b62a2e726dcb94db0f1aee74294c8813e65f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 6a3e9082bda8c..a0beb6eb505da 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -2977,7 +2977,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-5.15/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-5.15/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..3755b003b9 --- /dev/null +++ b/queue-5.15/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From 19627eff0bc7f7bde823e0da4d659df4a1dc3ae1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 3beec619283a9..10e30a85d5c5c 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -145,11 +145,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -168,6 +172,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-5.15/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-5.15/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..a2239244fd --- /dev/null +++ b/queue-5.15/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From 34e612564f9a44dd2c16456930769c108edaaa46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index 81cf611eae750..3468c58bbeebe 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -130,9 +130,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-5.15/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-5.15/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..97ffb65dae --- /dev/null +++ b/queue-5.15/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 8b4d7f6d7649849d73618e8ee86096aaa2507f0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 055bff0a04da9..5087ab9b137f2 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -872,8 +872,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -887,17 +887,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2642,7 +2636,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index f33e6aea7f4da..10bd7f604ebbc 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1325,9 +1325,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1354,10 +1354,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-5.15/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-5.15/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..b15397568d --- /dev/null +++ b/queue-5.15/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From d622225d0c1770ad91305b4696f63692f6b241b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-5.15/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-5.15/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..f71628fa4d --- /dev/null +++ b/queue-5.15/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From c16b7514cdbda2899d4e9faa849ed394f1dd0748 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 6d056ebba57c6..10d4dfbdde226 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-5.15/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-5.15/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..a62f416678 --- /dev/null +++ b/queue-5.15/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From ae1c44c585425406ecff5115bf189a19fbea7226 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 5db17768ec2ad..dcb0a5e592775 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-5.15/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-5.15/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..217dc5c593 --- /dev/null +++ b/queue-5.15/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From 019bce638da79964a915207041b2c2cc6e33ae0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 09fe6cf358ec7..6484d08223dbc 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -636,15 +636,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-5.15/netfilter-nft_payload-reject-out-of-range-attributes.patch b/queue-5.15/netfilter-nft_payload-reject-out-of-range-attributes.patch new file mode 100644 index 0000000000..941a8442c3 --- /dev/null +++ b/queue-5.15/netfilter-nft_payload-reject-out-of-range-attributes.patch @@ -0,0 +1,45 @@ +From cfe44e18058e92ebd132cd386c3c2a7786ef7d10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:09:37 +0200 +Subject: netfilter: nft_payload: reject out-of-range attributes via policy + +From: Florian Westphal + +[ Upstream commit e7af210e6dd0de633d3f4850383310cf57473bc8 ] + +Now that nla_policy allows range checks for bigendian data make use of +this to reject such attributes. At this time, reject happens later +from the init or select_ops callbacks, but its prone to errors. + +In the future, new attributes can be handled via NLA_POLICY_MAX_BE +and exiting ones can be converted one by one. + +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_payload.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 49a1cf53064fe..cb6ee00bbc09b 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -176,10 +176,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { + [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, ++ [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), + [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, ++ [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), + [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, + }; + +-- +2.51.0 + diff --git a/queue-5.15/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch b/queue-5.15/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch new file mode 100644 index 0000000000..970ed9ac09 --- /dev/null +++ b/queue-5.15/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch @@ -0,0 +1,85 @@ +From 778a46ab513b8bb83d48869536933c8f4cda4db4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jul 2023 09:52:29 +0200 +Subject: netlink: allow be16 and be32 types in all uint policy checks + +From: Florian Westphal + +[ Upstream commit 5fac9b7c16c50c6c7699517f582b56e3743f453a ] + +__NLA_IS_BEINT_TYPE(tp) isn't useful. NLA_BE16/32 are identical to +NLA_U16/32, the only difference is that it tells the netlink validation +functions that byteorder conversion might be needed before comparing +the value to the policy min/max ones. + +After this change all policy macros that can be used with UINT types, +such as NLA_POLICY_MASK() can also be used with NLA_BE16/32. + +This will be used to validate nf_tables flag attributes which +are in bigendian byte order. + +Signed-off-by: Florian Westphal +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 10 +++------- + lib/nlattr.c | 6 ++++++ + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 356b805f50151..8536301842c97 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -374,12 +374,11 @@ struct nla_policy { + #define NLA_POLICY_BITFIELD32(valid) \ + { .type = NLA_BITFIELD32, .bitfield32_valid = valid } + +-#define __NLA_IS_UINT_TYPE(tp) \ +- (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) ++#define __NLA_IS_UINT_TYPE(tp) \ ++ (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || \ ++ tp == NLA_U64 || tp == NLA_BE16 || tp == NLA_BE32) + #define __NLA_IS_SINT_TYPE(tp) \ + (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) +-#define __NLA_IS_BEINT_TYPE(tp) \ +- (tp == NLA_BE16 || tp == NLA_BE32) + + #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) + #define NLA_ENSURE_UINT_TYPE(tp) \ +@@ -393,7 +392,6 @@ struct nla_policy { + #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ + (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ + __NLA_IS_SINT_TYPE(tp) || \ +- __NLA_IS_BEINT_TYPE(tp) || \ + tp == NLA_MSECS || \ + tp == NLA_BINARY) + tp) + #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ +@@ -401,8 +399,6 @@ struct nla_policy { + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) +-#define NLA_ENSURE_BEINT_TYPE(tp) \ +- (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) + + #define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index dffd60e4065fd..a98e7191adaf6 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -355,6 +355,12 @@ static int nla_validate_mask(const struct nla_policy *pt, + case NLA_U64: + value = nla_get_u64(nla); + break; ++ case NLA_BE16: ++ value = ntohs(nla_get_be16(nla)); ++ break; ++ case NLA_BE32: ++ value = ntohl(nla_get_be32(nla)); ++ break; + default: + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-5.15/netlink-hide-validation-union-fields-from-kdoc.patch b/queue-5.15/netlink-hide-validation-union-fields-from-kdoc.patch new file mode 100644 index 0000000000..28b8e5c148 --- /dev/null +++ b/queue-5.15/netlink-hide-validation-union-fields-from-kdoc.patch @@ -0,0 +1,77 @@ +From fa210c661487fe0597c43e1c3781342629f65ffe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 14:21:07 -0700 +Subject: netlink: hide validation union fields from kdoc + +From: Jakub Kicinski + +[ Upstream commit 7354c9024f2835f6122ed9612e21ab379df050f9 ] + +Mark the validation fields as private, users shouldn't set +them directly and they are too complicated to explain in +a more succinct way (there's already a long explanation +in the comment above). + +The strict_start_type field is set directly and has a dedicated +comment so move that above the "private" section. + +Link: https://lore.kernel.org/r/20221027212107.2639255-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 6eb4593983319..8c67db47556e2 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -317,19 +317,10 @@ struct nla_policy { + u8 validation_type; + u16 len; + union { +- const u32 bitfield32_valid; +- const u32 mask; +- const char *reject_message; +- const struct nla_policy *nested_policy; +- struct netlink_range_validation *range; +- struct netlink_range_validation_signed *range_signed; +- struct { +- s16 min, max; +- u8 network_byte_order:1; +- }; +- int (*validate)(const struct nlattr *attr, +- struct netlink_ext_ack *extack); +- /* This entry is special, and used for the attribute at index 0 ++ /** ++ * @strict_start_type: first attribute to validate strictly ++ * ++ * This entry is special, and used for the attribute at index 0 + * only, and specifies special data about the policy, namely it + * specifies the "boundary type" where strict length validation + * starts for any attribute types >= this value, also, strict +@@ -348,6 +339,20 @@ struct nla_policy { + * was added to enforce strict validation from thereon. + */ + u16 strict_start_type; ++ ++ /* private: use NLA_POLICY_*() to set */ ++ const u32 bitfield32_valid; ++ const u32 mask; ++ const char *reject_message; ++ const struct nla_policy *nested_policy; ++ struct netlink_range_validation *range; ++ struct netlink_range_validation_signed *range_signed; ++ struct { ++ s16 min, max; ++ u8 network_byte_order:1; ++ }; ++ int (*validate)(const struct nlattr *attr, ++ struct netlink_ext_ack *extack); + }; + }; + +-- +2.51.0 + diff --git a/queue-5.15/netlink-introduce-bigendian-integer-types.patch b/queue-5.15/netlink-introduce-bigendian-integer-types.patch new file mode 100644 index 0000000000..79533da7f5 --- /dev/null +++ b/queue-5.15/netlink-introduce-bigendian-integer-types.patch @@ -0,0 +1,220 @@ +From 88f53b95a3c87114b65a274be0c54da3cf3f8879 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 13:34:07 +0100 +Subject: netlink: introduce bigendian integer types + +From: Florian Westphal + +[ Upstream commit ecaf75ffd5f5db320d8b1da0198eef5a5ce64a3f ] + +Jakub reported that the addition of the "network_byte_order" +member in struct nla_policy increases size of 32bit platforms. + +Instead of scraping the bit from elsewhere Johannes suggested +to add explicit NLA_BE types instead, so do this here. + +NLA_POLICY_MAX_BE() macro is removed again, there is no need +for it: NLA_POLICY_MAX(NLA_BE.., ..) will do the right thing. + +NLA_BE64 can be added later. + +Fixes: 08724ef69907 ("netlink: introduce NLA_POLICY_MAX_BE") +Reported-by: Jakub Kicinski +Suggested-by: Johannes Berg +Signed-off-by: Florian Westphal +Link: https://lore.kernel.org/r/20221031123407.9158-1-fw@strlen.de +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 19 +++++++++-------- + lib/nlattr.c | 41 ++++++++++++++----------------------- + net/netfilter/nft_payload.c | 6 +++--- + 3 files changed, 28 insertions(+), 38 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 8c67db47556e2..356b805f50151 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -181,6 +181,8 @@ enum { + NLA_S64, + NLA_BITFIELD32, + NLA_REJECT, ++ NLA_BE16, ++ NLA_BE32, + __NLA_TYPE_MAX, + }; + +@@ -231,6 +233,7 @@ enum nla_policy_validation { + * NLA_U32, NLA_U64, + * NLA_S8, NLA_S16, + * NLA_S32, NLA_S64, ++ * NLA_BE16, NLA_BE32, + * NLA_MSECS Leaving the length field zero will verify the + * given type fits, using it verifies minimum length + * just like "All other" +@@ -261,6 +264,8 @@ enum nla_policy_validation { + * NLA_U16, + * NLA_U32, + * NLA_U64, ++ * NLA_BE16, ++ * NLA_BE32, + * NLA_S8, + * NLA_S16, + * NLA_S32, +@@ -349,7 +354,6 @@ struct nla_policy { + struct netlink_range_validation_signed *range_signed; + struct { + s16 min, max; +- u8 network_byte_order:1; + }; + int (*validate)(const struct nlattr *attr, + struct netlink_ext_ack *extack); +@@ -374,6 +378,8 @@ struct nla_policy { + (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) + #define __NLA_IS_SINT_TYPE(tp) \ + (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) ++#define __NLA_IS_BEINT_TYPE(tp) \ ++ (tp == NLA_BE16 || tp == NLA_BE32) + + #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) + #define NLA_ENSURE_UINT_TYPE(tp) \ +@@ -387,6 +393,7 @@ struct nla_policy { + #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ + (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ + __NLA_IS_SINT_TYPE(tp) || \ ++ __NLA_IS_BEINT_TYPE(tp) || \ + tp == NLA_MSECS || \ + tp == NLA_BINARY) + tp) + #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ +@@ -394,6 +401,8 @@ struct nla_policy { + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) ++#define NLA_ENSURE_BEINT_TYPE(tp) \ ++ (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) + + #define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ +@@ -424,14 +433,6 @@ struct nla_policy { + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MAX, \ + .max = _max, \ +- .network_byte_order = 0, \ +-} +- +-#define NLA_POLICY_MAX_BE(tp, _max) { \ +- .type = NLA_ENSURE_UINT_TYPE(tp), \ +- .validation_type = NLA_VALIDATE_MAX, \ +- .max = _max, \ +- .network_byte_order = 1, \ + } + + #define NLA_POLICY_MASK(tp, _mask) { \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index a0c80fbf71895..dffd60e4065fd 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -125,10 +125,12 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + range->max = U8_MAX; + break; + case NLA_U16: ++ case NLA_BE16: + case NLA_BINARY: + range->max = U16_MAX; + break; + case NLA_U32: ++ case NLA_BE32: + range->max = U32_MAX; + break; + case NLA_U64: +@@ -160,31 +162,6 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + } + } + +-static u64 nla_get_attr_bo(const struct nla_policy *pt, +- const struct nlattr *nla) +-{ +- switch (pt->type) { +- case NLA_U16: +- if (pt->network_byte_order) +- return ntohs(nla_get_be16(nla)); +- +- return nla_get_u16(nla); +- case NLA_U32: +- if (pt->network_byte_order) +- return ntohl(nla_get_be32(nla)); +- +- return nla_get_u32(nla); +- case NLA_U64: +- if (pt->network_byte_order) +- return be64_to_cpu(nla_get_be64(nla)); +- +- return nla_get_u64(nla); +- } +- +- WARN_ON_ONCE(1); +- return 0; +-} +- + static int nla_validate_range_unsigned(const struct nla_policy *pt, + const struct nlattr *nla, + struct netlink_ext_ack *extack, +@@ -198,9 +175,13 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + value = nla_get_u8(nla); + break; + case NLA_U16: ++ value = nla_get_u16(nla); ++ break; + case NLA_U32: ++ value = nla_get_u32(nla); ++ break; + case NLA_U64: +- value = nla_get_attr_bo(pt, nla); ++ value = nla_get_u64(nla); + break; + case NLA_MSECS: + value = nla_get_u64(nla); +@@ -208,6 +189,12 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + case NLA_BINARY: + value = nla_len(nla); + break; ++ case NLA_BE16: ++ value = ntohs(nla_get_be16(nla)); ++ break; ++ case NLA_BE32: ++ value = ntohl(nla_get_be32(nla)); ++ break; + default: + return -EINVAL; + } +@@ -335,6 +322,8 @@ static int nla_validate_int_range(const struct nla_policy *pt, + case NLA_U64: + case NLA_MSECS: + case NLA_BINARY: ++ case NLA_BE16: ++ case NLA_BE32: + return nla_validate_range_unsigned(pt, nla, extack, validate); + case NLA_S8: + case NLA_S16: +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index cb6ee00bbc09b..dbafb964bd706 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -176,10 +176,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { + [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), +- [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), ++ [NFTA_PAYLOAD_LEN] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, +- [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX_BE(NLA_U32, 255), ++ [NFTA_PAYLOAD_CSUM_OFFSET] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, + }; + +-- +2.51.0 + diff --git a/queue-5.15/netlink-introduce-nla_policy_max_be.patch b/queue-5.15/netlink-introduce-nla_policy_max_be.patch new file mode 100644 index 0000000000..1739096c38 --- /dev/null +++ b/queue-5.15/netlink-introduce-nla_policy_max_be.patch @@ -0,0 +1,109 @@ +From c3d0841362e3bfc6301a81319be2f1bc34ab74df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:09:36 +0200 +Subject: netlink: introduce NLA_POLICY_MAX_BE + +From: Florian Westphal + +[ Upstream commit 08724ef69907214ce622344fe4945412e38368f0 ] + +netlink allows to specify allowed ranges for integer types. +Unfortunately, nfnetlink passes integers in big endian, so the existing +NLA_POLICY_MAX() cannot be used. + +At the moment, nfnetlink users, such as nf_tables, need to resort to +programmatic checking via helpers such as nft_parse_u32_check(). + +This is both cumbersome and error prone. This adds NLA_POLICY_MAX_BE +which adds range check support for BE16, BE32 and BE64 integers. + +Signed-off-by: Florian Westphal +Signed-off-by: David S. Miller +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 9 +++++++++ + lib/nlattr.c | 31 +++++++++++++++++++++++++++---- + 2 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 7a2a9d3144ba6..6eb4593983319 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -325,6 +325,7 @@ struct nla_policy { + struct netlink_range_validation_signed *range_signed; + struct { + s16 min, max; ++ u8 network_byte_order:1; + }; + int (*validate)(const struct nlattr *attr, + struct netlink_ext_ack *extack); +@@ -418,6 +419,14 @@ struct nla_policy { + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MAX, \ + .max = _max, \ ++ .network_byte_order = 0, \ ++} ++ ++#define NLA_POLICY_MAX_BE(tp, _max) { \ ++ .type = NLA_ENSURE_UINT_TYPE(tp), \ ++ .validation_type = NLA_VALIDATE_MAX, \ ++ .max = _max, \ ++ .network_byte_order = 1, \ + } + + #define NLA_POLICY_MASK(tp, _mask) { \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index 73635bdb00620..a0c80fbf71895 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -160,6 +160,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt, + } + } + ++static u64 nla_get_attr_bo(const struct nla_policy *pt, ++ const struct nlattr *nla) ++{ ++ switch (pt->type) { ++ case NLA_U16: ++ if (pt->network_byte_order) ++ return ntohs(nla_get_be16(nla)); ++ ++ return nla_get_u16(nla); ++ case NLA_U32: ++ if (pt->network_byte_order) ++ return ntohl(nla_get_be32(nla)); ++ ++ return nla_get_u32(nla); ++ case NLA_U64: ++ if (pt->network_byte_order) ++ return be64_to_cpu(nla_get_be64(nla)); ++ ++ return nla_get_u64(nla); ++ } ++ ++ WARN_ON_ONCE(1); ++ return 0; ++} ++ + static int nla_validate_range_unsigned(const struct nla_policy *pt, + const struct nlattr *nla, + struct netlink_ext_ack *extack, +@@ -173,12 +198,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, + value = nla_get_u8(nla); + break; + case NLA_U16: +- value = nla_get_u16(nla); +- break; + case NLA_U32: +- value = nla_get_u32(nla); +- break; + case NLA_U64: ++ value = nla_get_attr_bo(pt, nla); ++ break; + case NLA_MSECS: + value = nla_get_u64(nla); + break; +-- +2.51.0 + diff --git a/queue-5.15/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-5.15/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..d3ef290630 --- /dev/null +++ b/queue-5.15/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From 64518b308139f72c7796841b0c295e33f976fe12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index ca9543be400c4..992bd13649cb4 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -574,8 +574,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -587,13 +586,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); +@@ -603,6 +602,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-5.15/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-5.15/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..d09bafab8c --- /dev/null +++ b/queue-5.15/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From 4f3098dc3bb1a60b8e161b19b79a169a4fb54e99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index a7a9e4df3f600..1b2941e9c6d14 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2908,6 +2908,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-5.15/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-5.15/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..419516b603 --- /dev/null +++ b/queue-5.15/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From d5f24aeef4603acd4ecb8eadef40655a9a1596d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index 334cb85855a93..a3f1ff77e0646 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1110,9 +1110,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-5.15/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-5.15/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..71f0e809d2 --- /dev/null +++ b/queue-5.15/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From 5951539a29f683749d7835fcc09ca34b7c2f3c25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index 0d46706afd2da..d8a9a215a14cd 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-5.15/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-5.15/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..f5c1f0a817 --- /dev/null +++ b/queue-5.15/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From 42cf42a94d5a8740d72af9211bf809f43dd55cb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 674f33bae66e2..89c22b66886d4 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -532,11 +532,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 2129a358dd..331395156b 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -309,3 +309,36 @@ asoc-fsl_easrc-fix-event-generation-in-fsl_easrc_iec.patch asoc-fsl_easrc-fix-event-generation-in-fsl_easrc_iec.patch-32526 dma-buf-include-ioctl.h-in-uapi-header.patch alsa-hda-realtek-add-headset-jack-quirk-for-thinkpad.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +xfrm-fix-the-usage-of-skb-sk.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +af_key-validate-families-in-pfkey_send_migrate.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netlink-introduce-nla_policy_max_be.patch +netfilter-nft_payload-reject-out-of-range-attributes.patch +netlink-hide-validation-union-fields-from-kdoc.patch +netlink-introduce-bigendian-integer-types.patch +netlink-allow-be16-and-be32-types-in-all-uint-policy.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-5.15/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-5.15/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..532a82ed82 --- /dev/null +++ b/queue-5.15/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From fd5ee6d863f09fece6eea4a512acff6127814927 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 54ae99f69f25f..f7f568bfb93a8 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -1770,6 +1770,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-5.15/xfrm-fix-the-usage-of-skb-sk.patch b/queue-5.15/xfrm-fix-the-usage-of-skb-sk.patch new file mode 100644 index 0000000000..ca32ffa577 --- /dev/null +++ b/queue-5.15/xfrm-fix-the-usage-of-skb-sk.patch @@ -0,0 +1,135 @@ +From 4706e19e96bb09298c7dc75118a2d68081258821 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 11:46:03 +0100 +Subject: xfrm: Fix the usage of skb->sk + +From: Steffen Klassert + +[ Upstream commit 1620c88887b16940e00dbe57dd38c74eda9bad9e ] + +xfrm assumed to always have a full socket at skb->sk. +This is not always true, so fix it by converting to a +full socket before it is used. + +Signed-off-by: Steffen Klassert +Reviewed-by: Eric Dumazet +Stable-dep-of: 0c0eef8ccd24 ("esp: fix skb leak with espintcp and async crypto") +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 2 +- + net/ipv6/esp6.c | 2 +- + net/ipv6/xfrm6_output.c | 4 ++-- + net/xfrm/xfrm_interface_core.c | 2 +- + net/xfrm/xfrm_output.c | 7 ++++--- + net/xfrm/xfrm_policy.c | 2 +- + 6 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 53170ecb2de08..272b64fd09eed 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -278,7 +278,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index cbe575ade34d6..57e48dd905a48 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -315,7 +315,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c +index ad07904642cad..ff183bd76c998 100644 +--- a/net/ipv6/xfrm6_output.c ++++ b/net/ipv6/xfrm6_output.c +@@ -82,14 +82,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + toobig = skb->len > mtu && !skb_is_gso(skb); + +- if (toobig && xfrm6_local_dontfrag(skb->sk)) { ++ if (toobig && xfrm6_local_dontfrag(sk)) { + xfrm6_local_rxpmtu(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; + } else if (toobig && xfrm6_noneed_fragment(skb)) { + skb->ignore_df = 1; + goto skip_frag; +- } else if (!skb->ignore_df && toobig && skb->sk) { ++ } else if (!skb->ignore_df && toobig && sk) { + xfrm_local_error(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; +diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c +index 9bd69887e16d2..4baa7a61df0e6 100644 +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -369,7 +369,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + skb_dst_set(skb, dst); + skb->dev = tdev; + +- err = dst_output(xi->net, skb->sk, skb); ++ err = dst_output(xi->net, skb_to_full_sk(skb), skb); + if (net_xmit_eval(err) == 0) { + dev_sw_netstats_tx_add(dev, 1, length); + } else { +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 29ce7f6f16a09..3e27daceebfe4 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -781,7 +781,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) + !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { + skb->protocol = htons(ETH_P_IP); + +- if (skb->sk) ++ if (skb->sk && sk_fullsock(skb->sk)) + xfrm_local_error(skb, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, +@@ -817,6 +817,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + { + int mtu, ret = 0; + struct dst_entry *dst = skb_dst(skb); ++ struct sock *sk = skb_to_full_sk(skb); + + if (skb->ignore_df) + goto out; +@@ -831,9 +832,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + skb->dev = dst->dev; + skb->protocol = htons(ETH_P_IPV6); + +- if (xfrm6_local_dontfrag(skb->sk)) ++ if (xfrm6_local_dontfrag(sk)) + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); +- else if (skb->sk) ++ else if (sk) + xfrm_local_error(skb, mtu); + else + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 16958656b6d43..851029a5383a2 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2856,7 +2856,7 @@ static void xfrm_policy_queue_process(struct timer_list *t) + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- dst_output(net, skb->sk, skb); ++ dst_output(net, skb_to_full_sk(skb), skb); + } + + out: +-- +2.51.0 + diff --git a/queue-6.1/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-6.1/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..51ed5aafaf --- /dev/null +++ b/queue-6.1/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From e5f1cb3013a98dc4b2be1d8c781546406a98acac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 0fcd348c249fb..169045f595633 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-6.1/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..843077bd8c --- /dev/null +++ b/queue-6.1/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From fc8ecda34a1ff52747f0f1821841c07fbf04ee10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index cc5ce7a984f6c..25d713856a103 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2096,8 +2096,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-6.1/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..0c20690a64 --- /dev/null +++ b/queue-6.1/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From 9a5baa0c9d9caf1914a39126c982901f3450e7ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 5abc01a2acf72..a5ef57b27bf28 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-6.1/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..307583184d --- /dev/null +++ b/queue-6.1/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From 2699feac84a36f5b53c38c4ca6efaa460a71c14b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 35cac683d4f02..8a2d36f5cf33b 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2565,6 +2565,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4539,14 +4542,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-6.1/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..87f54c735b --- /dev/null +++ b/queue-6.1/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From 1d45a52c0b0edad2e53f50dc8780aac8b688265d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index fbad035279058..a054cc2d05b69 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1701,6 +1701,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch b/queue-6.1/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch new file mode 100644 index 0000000000..2a13b0f495 --- /dev/null +++ b/queue-6.1/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch @@ -0,0 +1,50 @@ +From 8de06eedaab744f4d89159de1fd4afb45255aca6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 17:32:11 +0800 +Subject: Bluetooth: L2CAP: Fix send LE flow credits in ACL link + +From: Zhang Chen + +[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ] + +When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, +l2cap_publish_rx_avail will be called and le flow credits will be sent in +l2cap_chan_rx_avail, even though the link type is ACL. + +The logs in question as follows: +> ACL Data RX: Handle 129 flags 0x02 dlen 12 + L2CAP: Unknown (0x16) ident 4 len 4 + 40 00 ed 05 +< ACL Data TX: Handle 129 flags 0x00 dlen 10 + L2CAP: Command Reject (0x01) ident 4 len 2 + Reason: Command not understood (0x0000) + +Bluetooth: Unknown BR/EDR signaling command 0x16 +Bluetooth: Wrong link type (-22) + +Fixes: ce60b9231b66 ("Bluetooth: compute LE flow credits based on recvbuf space") +Signed-off-by: Zhang Chen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 38e46f5175dad..35cac683d4f02 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7625,6 +7625,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + struct l2cap_le_credits pkt; + u16 return_credits = l2cap_le_rx_credits(chan); + ++ if (chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ + if (chan->rx_credits >= return_credits) + return; + +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-6.1/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..2e0d5622af --- /dev/null +++ b/queue-6.1/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 753613c53c2fa19dbd6d794331c2e2733d187a9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 3dfaf7044eddc..38e46f5175dad 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7708,6 +7708,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-6.1/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..5b65d923ae --- /dev/null +++ b/queue-6.1/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From bae6c9dc023f9c90ee341ef1bf74b4f664a404ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index cf53d483dd071..94c90d472f317 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -339,7 +339,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -348,11 +348,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-6.1/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-6.1/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..bf2757d701 --- /dev/null +++ b/queue-6.1/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From 07030897ae52f7d3cfb6190421a5e04b9416daad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index bbd8e959137d9..851d2c90901c5 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -468,7 +468,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -572,7 +572,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 25fdf060e30d0..2f78ea8ac30b0 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-6.1/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-6.1/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..57570d5041 --- /dev/null +++ b/queue-6.1/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 5d7d3a0deb301beefdd06b12f3ede3bbc0cfddd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index af3f39ecc1b87..5846e43779dc9 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -219,8 +219,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-6.1/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch b/queue-6.1/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch new file mode 100644 index 0000000000..a7d50140eb --- /dev/null +++ b/queue-6.1/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch @@ -0,0 +1,83 @@ +From 6a33dd2066e5ad62cdce76aeea516708dcf15e3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 17:27:49 +0900 +Subject: dma: swiotlb: add KMSAN annotations to swiotlb_bounce() + +From: Shigeru Yoshida + +[ Upstream commit 6f770b73d0311a5b099277653199bb6421c4fed2 ] + +When a device performs DMA to a bounce buffer, KMSAN is unaware of +the write and does not mark the data as initialized. When +swiotlb_bounce() later copies the bounce buffer back to the original +buffer, memcpy propagates the uninitialized shadow to the original +buffer, causing false positive uninit-value reports. + +Fix this by calling kmsan_unpoison_memory() on the bounce buffer +before copying it back in the DMA_FROM_DEVICE path, so that memcpy +naturally propagates initialized shadow to the destination. + +Suggested-by: Alexander Potapenko +Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/ +Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") +Signed-off-by: Shigeru Yoshida +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index db89ac94e7db4..b5c8ba23ff625 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -600,10 +601,19 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + + local_irq_save(flags); + page = pfn_to_page(pfn); +- if (dir == DMA_TO_DEVICE) ++ if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_highmem_page() ++ * could be used here to detect infoleaks, ++ * but callers may map uninitialized buffers ++ * that will be written by the device, ++ * causing false positives. ++ */ + memcpy_from_page(vaddr, page, offset, sz); +- else ++ } else { ++ kmsan_unpoison_memory(vaddr, sz); + memcpy_to_page(page, offset, vaddr, sz); ++ } + local_irq_restore(flags); + + size -= sz; +@@ -612,8 +622,15 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + offset = 0; + } + } else if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_memory() could be used here to detect ++ * infoleaks (uninitialized data being sent to device), but ++ * callers may map uninitialized buffers that will be written ++ * by the device, causing false positives. ++ */ + memcpy(vaddr, phys_to_virt(orig_addr), size); + } else { ++ kmsan_unpoison_memory(vaddr, size); + memcpy(phys_to_virt(orig_addr), vaddr, size); + } + } +-- +2.51.0 + diff --git a/queue-6.1/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-6.1/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..3b5645ffaa --- /dev/null +++ b/queue-6.1/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 674f49910718e71eba799bb0b04aa982158d9cd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 70ad42826c3db..95575bf78d5c1 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -233,10 +233,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index a7cc96fc7c247..76699ec883702 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -269,10 +269,13 @@ static void esp_output_done(struct crypto_async_request *base, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-6.1/ice-use-ice_update_eth_stats-for-representor-stats.patch b/queue-6.1/ice-use-ice_update_eth_stats-for-representor-stats.patch new file mode 100644 index 0000000000..1b8e0344f8 --- /dev/null +++ b/queue-6.1/ice-use-ice_update_eth_stats-for-representor-stats.patch @@ -0,0 +1,100 @@ +From 96d5fc4aaab42dd497d30192f1831f76ba8f6a89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:11 +0100 +Subject: ice: use ice_update_eth_stats() for representor stats + +From: Petr Oros + +[ Upstream commit 2526e440df2725e7328d59b835a164826f179b93 ] + +ice_repr_get_stats64() and __ice_get_ethtool_stats() call +ice_update_vsi_stats() on the VF's src_vsi. This always returns early +because ICE_VSI_DOWN is permanently set for VF VSIs - ice_up() is never +called on them since queues are managed by iavf through virtchnl. + +In __ice_get_ethtool_stats() the original code called +ice_update_vsi_stats() for all VSIs including representors, iterated +over ice_gstrings_vsi_stats[] to populate the data, and then bailed out +with an early return before the per-queue ring stats section. That early +return was necessary because representor VSIs have no rings on the PF +side - the rings belong to the VF driver (iavf), so accessing per-queue +stats would be invalid. + +Move the representor handling to the top of __ice_get_ethtool_stats() +and call ice_update_eth_stats() directly to read the hardware GLV_* +counters. This matches ice_get_vf_stats() which already uses +ice_update_eth_stats() for the same VF VSI in legacy mode. Apply the +same fix to ice_repr_get_stats64(). + +Note that ice_gstrings_vsi_stats[] contains five software ring counters +(rx_buf_failed, rx_page_failed, tx_linearize, tx_busy, tx_restart) that +are always zero for representors since the PF never processes packets on +VF rings. This is pre-existing behavior unchanged by this patch. + +Fixes: 7aae80cef7ba ("ice: add port representor ethtool ops and stats") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 14 +++++++++++--- + drivers/net/ethernet/intel/ice/ice_repr.c | 3 ++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index bcaa2f66dd825..49c524304a412 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1358,6 +1358,17 @@ __ice_get_ethtool_stats(struct net_device *netdev, + int i = 0; + char *p; + ++ if (ice_is_port_repr_netdev(netdev)) { ++ ice_update_eth_stats(vsi); ++ ++ for (j = 0; j < ICE_VSI_STATS_LEN; j++) { ++ p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; ++ data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ return; ++ } ++ + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + +@@ -1367,9 +1378,6 @@ __ice_get_ethtool_stats(struct net_device *netdev, + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + +- if (ice_is_port_repr_netdev(netdev)) +- return; +- + /* populate per queue stats */ + rcu_read_lock(); + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index bd31748aae1b4..d442b386a664d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2019-2021, Intel Corporation. */ + + #include "ice.h" ++#include "ice_lib.h" + #include "ice_eswitch.h" + #include "ice_devlink.h" + #include "ice_sriov.h" +@@ -56,7 +57,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) + return; + vsi = np->repr->src_vsi; + +- ice_update_vsi_stats(vsi); ++ ice_update_eth_stats(vsi); + eth_stats = &vsi->eth_stats; + + stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast + +-- +2.51.0 + diff --git a/queue-6.1/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-6.1/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..7ef0e382fd --- /dev/null +++ b/queue-6.1/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From 994d85223d287d08bc08aa22f66c39107c87be34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 7ed77a8304e68..c15d7dfce21e5 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1665,13 +1665,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-6.1/net-add-new-helper-unregister_netdevice_many_notify.patch b/queue-6.1/net-add-new-helper-unregister_netdevice_many_notify.patch new file mode 100644 index 0000000000..1944321eff --- /dev/null +++ b/queue-6.1/net-add-new-helper-unregister_netdevice_many_notify.patch @@ -0,0 +1,103 @@ +From a72586765665cc73128f5c1e401e6c859a649bc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 04:42:22 -0400 +Subject: net: add new helper unregister_netdevice_many_notify + +From: Hangbin Liu + +[ Upstream commit 77f4aa9a2a1766a0b9343fd812b71f18d05178da ] + +Add new helper unregister_netdevice_many_notify(), pass netlink message +header and portid, which could be used to notify userspace when flag +NLM_F_ECHO is set. + +Make the unregister_netdevice_many() as a wrapper of new function +unregister_netdevice_many_notify(). + +Suggested-by: Guillaume Nault +Signed-off-by: Hangbin Liu +Reviewed-by: Guillaume Nault +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6931d21f87bc ("openvswitch: defer tunnel netdev_put to RCU release") +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 27 +++++++++++++++++---------- + net/core/dev.h | 3 +++ + 2 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 7c743a39747fa..332d3b73d45e7 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -10950,14 +10950,8 @@ void unregister_netdevice_queue(struct net_device *dev, struct list_head *head) + } + EXPORT_SYMBOL(unregister_netdevice_queue); + +-/** +- * unregister_netdevice_many - unregister many devices +- * @head: list of devices +- * +- * Note: As most callers use a stack allocated list_head, +- * we force a list_del() to make sure stack wont be corrupted later. +- */ +-void unregister_netdevice_many(struct list_head *head) ++void unregister_netdevice_many_notify(struct list_head *head, ++ u32 portid, const struct nlmsghdr *nlh) + { + struct net_device *dev, *tmp; + LIST_HEAD(close_head); +@@ -11019,7 +11013,8 @@ void unregister_netdevice_many(struct list_head *head) + if (!dev->rtnl_link_ops || + dev->rtnl_link_state == RTNL_LINK_INITIALIZED) + skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U, 0, +- GFP_KERNEL, NULL, 0, 0, 0); ++ GFP_KERNEL, NULL, 0, ++ portid, nlmsg_seq(nlh)); + + /* + * Flush the unicast and multicast chains +@@ -11034,7 +11029,7 @@ void unregister_netdevice_many(struct list_head *head) + dev->netdev_ops->ndo_uninit(dev); + + if (skb) +- rtmsg_ifinfo_send(skb, dev, GFP_KERNEL, 0, NULL); ++ rtmsg_ifinfo_send(skb, dev, GFP_KERNEL, portid, nlh); + + /* Notifier chain MUST detach us all upper devices. */ + WARN_ON(netdev_has_any_upper_dev(dev)); +@@ -11057,6 +11052,18 @@ void unregister_netdevice_many(struct list_head *head) + + list_del(head); + } ++ ++/** ++ * unregister_netdevice_many - unregister many devices ++ * @head: list of devices ++ * ++ * Note: As most callers use a stack allocated list_head, ++ * we force a list_del() to make sure stack wont be corrupted later. ++ */ ++void unregister_netdevice_many(struct list_head *head) ++{ ++ unregister_netdevice_many_notify(head, 0, NULL); ++} + EXPORT_SYMBOL(unregister_netdevice_many); + + /** +diff --git a/net/core/dev.h b/net/core/dev.h +index 8d1afb9887dec..c1e4a39c40787 100644 +--- a/net/core/dev.h ++++ b/net/core/dev.h +@@ -98,6 +98,9 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags, + unsigned int gchanges, u32 portid, + const struct nlmsghdr *nlh); + ++void unregister_netdevice_many_notify(struct list_head *head, ++ u32 portid, const struct nlmsghdr *nlh); ++ + static inline void netif_set_gso_max_size(struct net_device *dev, + unsigned int size) + { +-- +2.51.0 + diff --git a/queue-6.1/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-6.1/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..c354d8ff26 --- /dev/null +++ b/queue-6.1/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From 540fee2b49bd03a73af29b67b9d9a761b0bcb7dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index c8369e3752b0e..d4623a41f0137 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -677,6 +677,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-6.1/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-6.1/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..9affef1397 --- /dev/null +++ b/queue-6.1/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From 25293f656f782908fefea64aa512a65ce6510953 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 8c06e3e6b52b5..502d2f6de18a2 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3185,6 +3185,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-6.1/net-macb-use-the-current-queue-number-for-stats.patch b/queue-6.1/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..3ea24f063a --- /dev/null +++ b/queue-6.1/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From 85798e4753c4bb07ecb3d9a2b894e153582a7719 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 412a821148d7b..59586db1d1fd2 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3170,7 +3170,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-6.1/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-6.1/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..11f2431950 --- /dev/null +++ b/queue-6.1/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From 76a0b19fdae7da23a0158d9c4b2e05477dc69ef0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 7126ff1045503..5bae7ca4abbc0 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -144,11 +144,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -167,6 +171,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-6.1/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-6.1/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..7dd13a1667 --- /dev/null +++ b/queue-6.1/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From ccb793c906c9b8c2253d4db61e95a4b9aafbfdfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index e57002d2ac372..8f838ddeaafe8 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -131,9 +131,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-6.1/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-6.1/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..8aa544d463 --- /dev/null +++ b/queue-6.1/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 8937d08ce40b0e5215523875782b56124ab6eebe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 30f332bcdc39d..6190a1d062402 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -883,8 +883,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -898,17 +898,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2626,7 +2620,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 9480e638e5d15..8bce2191873a2 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1393,9 +1393,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1422,10 +1422,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-6.1/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-6.1/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..585aabbbbb --- /dev/null +++ b/queue-6.1/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From f416c67af0f49ce92085a64f87a12b28390abff2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-6.1/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-6.1/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..17d88e5300 --- /dev/null +++ b/queue-6.1/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From 5077c4cc9717b9ed785a1ccdd1a666e108ef7f4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 81ca348915c98..7bc64eb89bac4 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-6.1/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-6.1/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..6067899c8f --- /dev/null +++ b/queue-6.1/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From a90690ac01d70f5dee74822beaad67d695be46c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 657839a58782a..84334537c6067 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-6.1/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-6.1/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..9f0cd9dd66 --- /dev/null +++ b/queue-6.1/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From 8bcc050b043e5a7da5a4da2429eb87ebf5172eb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 200a82a8f943d..4fcdd9ec8de9b 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -639,15 +639,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-6.1/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch b/queue-6.1/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch new file mode 100644 index 0000000000..453fbe5f0b --- /dev/null +++ b/queue-6.1/netlink-allow-be16-and-be32-types-in-all-uint-policy.patch @@ -0,0 +1,85 @@ +From bd77ea78b758a09b08fc068f6fa242ddb57e5637 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jul 2023 09:52:29 +0200 +Subject: netlink: allow be16 and be32 types in all uint policy checks + +From: Florian Westphal + +[ Upstream commit 5fac9b7c16c50c6c7699517f582b56e3743f453a ] + +__NLA_IS_BEINT_TYPE(tp) isn't useful. NLA_BE16/32 are identical to +NLA_U16/32, the only difference is that it tells the netlink validation +functions that byteorder conversion might be needed before comparing +the value to the policy min/max ones. + +After this change all policy macros that can be used with UINT types, +such as NLA_POLICY_MASK() can also be used with NLA_BE16/32. + +This will be used to validate nf_tables flag attributes which +are in bigendian byte order. + +Signed-off-by: Florian Westphal +Stable-dep-of: 8f15b5071b45 ("netfilter: ctnetlink: use netlink policy range checks") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 10 +++------- + lib/nlattr.c | 6 ++++++ + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 6e1e670e06bc4..df8012ef85f1d 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -374,12 +374,11 @@ struct nla_policy { + #define NLA_POLICY_BITFIELD32(valid) \ + { .type = NLA_BITFIELD32, .bitfield32_valid = valid } + +-#define __NLA_IS_UINT_TYPE(tp) \ +- (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64) ++#define __NLA_IS_UINT_TYPE(tp) \ ++ (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || \ ++ tp == NLA_U64 || tp == NLA_BE16 || tp == NLA_BE32) + #define __NLA_IS_SINT_TYPE(tp) \ + (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64) +-#define __NLA_IS_BEINT_TYPE(tp) \ +- (tp == NLA_BE16 || tp == NLA_BE32) + + #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition)) + #define NLA_ENSURE_UINT_TYPE(tp) \ +@@ -393,7 +392,6 @@ struct nla_policy { + #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp) \ + (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) || \ + __NLA_IS_SINT_TYPE(tp) || \ +- __NLA_IS_BEINT_TYPE(tp) || \ + tp == NLA_MSECS || \ + tp == NLA_BINARY) + tp) + #define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ +@@ -401,8 +399,6 @@ struct nla_policy { + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) +-#define NLA_ENSURE_BEINT_TYPE(tp) \ +- (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp) + + #define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ +diff --git a/lib/nlattr.c b/lib/nlattr.c +index 86344df0ccf7b..cf5f0dc3e47d6 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -359,6 +359,12 @@ static int nla_validate_mask(const struct nla_policy *pt, + case NLA_U64: + value = nla_get_u64(nla); + break; ++ case NLA_BE16: ++ value = ntohs(nla_get_be16(nla)); ++ break; ++ case NLA_BE32: ++ value = ntohl(nla_get_be32(nla)); ++ break; + default: + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-6.1/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-6.1/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..9b6f675a9c --- /dev/null +++ b/queue-6.1/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From b4613bbc2cde376555f3f60f8ecccbce3410b10e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index cdc1aa8662544..ed629c6880b75 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -574,8 +574,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -587,13 +586,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); +@@ -603,6 +602,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.1/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch b/queue-6.1/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch new file mode 100644 index 0000000000..d49972b00b --- /dev/null +++ b/queue-6.1/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch @@ -0,0 +1,50 @@ +From 044e5593738e698c5b8aebbcd9f18bdbaf26737a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 07:42:41 +0000 +Subject: openvswitch: defer tunnel netdev_put to RCU release + +From: Yang Yang + +[ Upstream commit 6931d21f87bc6d657f145798fad0bf077b82486c ] + +ovs_netdev_tunnel_destroy() may run after NETDEV_UNREGISTER already +detached the device. Dropping the netdev reference in destroy can race +with concurrent readers that still observe vport->dev. + +Do not release vport->dev in ovs_netdev_tunnel_destroy(). Instead, let +vport_netdev_free() drop the reference from the RCU callback, matching +the non-tunnel destroy path and avoiding additional synchronization +under RTNL. + +Fixes: a9020fde67a6 ("openvswitch: Move tunnel destroy function to oppenvswitch module.") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319074241.3405262-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 18376e10aeedc..68d38c12427c1 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -189,8 +189,6 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + */ + if (vport->dev->reg_state == NETREG_REGISTERED) + rtnl_delete_link(vport->dev, 0, NULL); +- netdev_put(vport->dev, &vport->dev_tracker); +- vport->dev = NULL; + rtnl_unlock(); + + call_rcu(&vport->rcu, vport_netdev_free); +-- +2.51.0 + diff --git a/queue-6.1/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-6.1/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..95614f7506 --- /dev/null +++ b/queue-6.1/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From cb1be444ee6b68afdd1600b5ad46f48040decb9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index d4c8b4aa98b19..d85432d977f2f 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2937,6 +2937,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-6.1/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-6.1/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..d9bc843f36 --- /dev/null +++ b/queue-6.1/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From 75b0b3fd7f41b36da3958e82cb3212f211494e07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index f25b3e09386bc..096213d618839 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1127,9 +1127,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-6.1/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-6.1/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..d42ff181be --- /dev/null +++ b/queue-6.1/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From ddc7429457d6362d030cf3ee69b3d8c922b4be24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index 4823bd2819f64..8ecb7048bcc4c 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-6.1/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-6.1/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..8573c11c78 --- /dev/null +++ b/queue-6.1/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From 3920fc07a66817810421c7b371905bcd290ce9ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 78e39543e408b..e5bfa3cbfcc41 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -567,11 +567,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-6.1/rtnetlink-honour-nlm_f_echo-flag-in-rtnl_delete_link.patch b/queue-6.1/rtnetlink-honour-nlm_f_echo-flag-in-rtnl_delete_link.patch new file mode 100644 index 0000000000..e3d1113f9b --- /dev/null +++ b/queue-6.1/rtnetlink-honour-nlm_f_echo-flag-in-rtnl_delete_link.patch @@ -0,0 +1,138 @@ +From b852a854a1912a042d94e816a017b11f242bb2c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 04:42:24 -0400 +Subject: rtnetlink: Honour NLM_F_ECHO flag in rtnl_delete_link + +From: Hangbin Liu + +[ Upstream commit f3a63cce1b4fbde7738395c5a2dea83f05de3407 ] + +This patch use the new helper unregister_netdevice_many_notify() for +rtnl_delete_link(), so that the kernel could reply unicast when userspace + set NLM_F_ECHO flag to request the new created interface info. + +At the same time, the parameters of rtnl_delete_link() need to be updated +since we need nlmsghdr and portid info. + +Suggested-by: Guillaume Nault +Signed-off-by: Hangbin Liu +Reviewed-by: Guillaume Nault +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6931d21f87bc ("openvswitch: defer tunnel netdev_put to RCU release") +Signed-off-by: Sasha Levin +--- + include/net/rtnetlink.h | 2 +- + net/core/rtnetlink.c | 7 ++++--- + net/openvswitch/vport-geneve.c | 2 +- + net/openvswitch/vport-gre.c | 2 +- + net/openvswitch/vport-netdev.c | 2 +- + net/openvswitch/vport-vxlan.c | 2 +- + 6 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h +index ad8786c9777c9..0bd400be3f8d9 100644 +--- a/include/net/rtnetlink.h ++++ b/include/net/rtnetlink.h +@@ -203,7 +203,7 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname, + const struct rtnl_link_ops *ops, + struct nlattr *tb[], + struct netlink_ext_ack *extack); +-int rtnl_delete_link(struct net_device *dev); ++int rtnl_delete_link(struct net_device *dev, u32 portid, const struct nlmsghdr *nlh); + int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm, + u32 portid, const struct nlmsghdr *nlh); + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 73453a92ea492..78e39543e408b 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3162,7 +3162,7 @@ static int rtnl_group_dellink(const struct net *net, int group) + return 0; + } + +-int rtnl_delete_link(struct net_device *dev) ++int rtnl_delete_link(struct net_device *dev, u32 portid, const struct nlmsghdr *nlh) + { + const struct rtnl_link_ops *ops; + LIST_HEAD(list_kill); +@@ -3172,7 +3172,7 @@ int rtnl_delete_link(struct net_device *dev) + return -EOPNOTSUPP; + + ops->dellink(dev, &list_kill); +- unregister_netdevice_many(&list_kill); ++ unregister_netdevice_many_notify(&list_kill, portid, nlh); + + return 0; + } +@@ -3182,6 +3182,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack) + { + struct net *net = sock_net(skb->sk); ++ u32 portid = NETLINK_CB(skb).portid; + struct net *tgt_net = net; + struct net_device *dev = NULL; + struct ifinfomsg *ifm; +@@ -3223,7 +3224,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, + goto out; + } + +- err = rtnl_delete_link(dev); ++ err = rtnl_delete_link(dev, portid, nlh); + + out: + if (netnsid >= 0) +diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c +index 89a8e1501809f..b10e1602c6b14 100644 +--- a/net/openvswitch/vport-geneve.c ++++ b/net/openvswitch/vport-geneve.c +@@ -91,7 +91,7 @@ static struct vport *geneve_tnl_create(const struct vport_parms *parms) + + err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); + if (err < 0) { +- rtnl_delete_link(dev); ++ rtnl_delete_link(dev, 0, NULL); + rtnl_unlock(); + ovs_vport_free(vport); + goto error; +diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c +index e6b5e76a962a6..4014c9b5eb798 100644 +--- a/net/openvswitch/vport-gre.c ++++ b/net/openvswitch/vport-gre.c +@@ -57,7 +57,7 @@ static struct vport *gre_tnl_create(const struct vport_parms *parms) + + err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); + if (err < 0) { +- rtnl_delete_link(dev); ++ rtnl_delete_link(dev, 0, NULL); + rtnl_unlock(); + ovs_vport_free(vport); + return ERR_PTR(err); +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 5bae7ca4abbc0..18376e10aeedc 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -188,7 +188,7 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + * if it's not already shutting down. + */ + if (vport->dev->reg_state == NETREG_REGISTERED) +- rtnl_delete_link(vport->dev); ++ rtnl_delete_link(vport->dev, 0, NULL); + netdev_put(vport->dev, &vport->dev_tracker); + vport->dev = NULL; + rtnl_unlock(); +diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c +index 188e9c1360a12..0b881b043bcf4 100644 +--- a/net/openvswitch/vport-vxlan.c ++++ b/net/openvswitch/vport-vxlan.c +@@ -120,7 +120,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) + + err = dev_change_flags(dev, dev->flags | IFF_UP, NULL); + if (err < 0) { +- rtnl_delete_link(dev); ++ rtnl_delete_link(dev, 0, NULL); + rtnl_unlock(); + ovs_vport_free(vport); + goto error; +-- +2.51.0 + diff --git a/queue-6.1/rtnetlink-pass-netlink-message-header-and-portid-to-.patch b/queue-6.1/rtnetlink-pass-netlink-message-header-and-portid-to-.patch new file mode 100644 index 0000000000..44b4ed8403 --- /dev/null +++ b/queue-6.1/rtnetlink-pass-netlink-message-header-and-portid-to-.patch @@ -0,0 +1,465 @@ +From 80b10529e61ec06352ba77e40b1c0d1a4f05efaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 04:42:21 -0400 +Subject: rtnetlink: pass netlink message header and portid to + rtnl_configure_link() + +From: Hangbin Liu + +[ Upstream commit 1d997f1013079c05b642c739901e3584a3ae558d ] + +This patch pass netlink message header and portid to rtnl_configure_link() +All the functions in this call chain need to add the parameters so we can +use them in the last call rtnl_notify(), and notify the userspace about +the new link info if NLM_F_ECHO flag is set. + +- rtnl_configure_link() + - __dev_notify_flags() + - rtmsg_ifinfo() + - rtmsg_ifinfo_event() + - rtmsg_ifinfo_build_skb() + - rtmsg_ifinfo_send() + - rtnl_notify() + +Also move __dev_notify_flags() declaration to net/core/dev.h, as Jakub +suggested. + +Signed-off-by: Hangbin Liu +Reviewed-by: Guillaume Nault +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6931d21f87bc ("openvswitch: defer tunnel netdev_put to RCU release") +Signed-off-by: Sasha Levin +--- + drivers/net/can/vxcan.c | 2 +- + drivers/net/geneve.c | 2 +- + drivers/net/veth.c | 2 +- + drivers/net/vxlan/vxlan_core.c | 4 ++-- + drivers/net/wwan/wwan_core.c | 2 +- + include/linux/netdevice.h | 2 -- + include/linux/rtnetlink.h | 9 +++++---- + include/net/netlink.h | 11 +++++++++++ + include/net/rtnetlink.h | 3 ++- + net/core/dev.c | 25 ++++++++++++------------ + net/core/dev.h | 4 ++++ + net/core/rtnetlink.c | 35 ++++++++++++++++++---------------- + net/ipv4/ip_gre.c | 2 +- + 13 files changed, 61 insertions(+), 42 deletions(-) + +diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c +index 6d549dbdb4674..98c669ad51414 100644 +--- a/drivers/net/can/vxcan.c ++++ b/drivers/net/can/vxcan.c +@@ -231,7 +231,7 @@ static int vxcan_newlink(struct net *net, struct net_device *dev, + + netif_carrier_off(peer); + +- err = rtnl_configure_link(peer, ifmp); ++ err = rtnl_configure_link(peer, ifmp, 0, NULL); + if (err < 0) + goto unregister_network_device; + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index 6234a3c711c53..8ebdf39771878 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -1924,7 +1924,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, + if (err) + goto err; + +- err = rtnl_configure_link(dev, NULL); ++ err = rtnl_configure_link(dev, NULL, 0, NULL); + if (err < 0) + goto err; + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index ce90b093bb45c..e1e8c825483aa 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -1734,7 +1734,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, + veth_disable_gro(peer); + netif_carrier_off(peer); + +- err = rtnl_configure_link(peer, ifmp); ++ err = rtnl_configure_link(peer, ifmp, 0, NULL); + if (err < 0) + goto err_configure_peer; + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 9c3a12feb25d2..acee0efd4c200 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -3880,7 +3880,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, + goto errout; + } + +- err = rtnl_configure_link(dev, NULL); ++ err = rtnl_configure_link(dev, NULL, 0, NULL); + if (err < 0) + goto unlink; + +@@ -4516,7 +4516,7 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name, + return ERR_PTR(err); + } + +- err = rtnl_configure_link(dev, NULL); ++ err = rtnl_configure_link(dev, NULL, 0, NULL); + if (err < 0) { + LIST_HEAD(list_kill); + +diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c +index 7089cb103885d..2b01fc351747b 100644 +--- a/drivers/net/wwan/wwan_core.c ++++ b/drivers/net/wwan/wwan_core.c +@@ -1058,7 +1058,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, + goto unlock; + } + +- rtnl_configure_link(dev, NULL); /* Link initialized, notify new link */ ++ rtnl_configure_link(dev, NULL, 0, NULL); /* Link initialized, notify new link */ + + unlock: + rtnl_unlock(); +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 1c47ab59a2c7f..e0df5fc672790 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3911,8 +3911,6 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags, + struct netlink_ext_ack *extack); + int dev_change_flags(struct net_device *dev, unsigned int flags, + struct netlink_ext_ack *extack); +-void __dev_notify_flags(struct net_device *, unsigned int old_flags, +- unsigned int gchanges); + int dev_set_alias(struct net_device *, const char *, size_t); + int dev_get_alias(const struct net_device *, char *, size_t); + int __dev_change_net_namespace(struct net_device *dev, struct net *net, +diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h +index f532d1eda761c..9494b7647e812 100644 +--- a/include/linux/rtnetlink.h ++++ b/include/linux/rtnetlink.h +@@ -12,21 +12,22 @@ + extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo); + extern int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid); + extern void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, +- u32 group, struct nlmsghdr *nlh, gfp_t flags); ++ u32 group, const struct nlmsghdr *nlh, gfp_t flags); + extern void rtnl_set_sk_err(struct net *net, u32 group, int error); + extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); + extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, + u32 id, long expires, u32 error); + +-void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change, gfp_t flags); ++void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, gfp_t flags, ++ u32 portid, const struct nlmsghdr *nlh); + void rtmsg_ifinfo_newnet(int type, struct net_device *dev, unsigned int change, + gfp_t flags, int *new_nsid, int new_ifindex); + struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, + unsigned change, u32 event, + gfp_t flags, int *new_nsid, +- int new_ifindex); ++ int new_ifindex, u32 portid, u32 seq); + void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, +- gfp_t flags); ++ gfp_t flags, u32 portid, const struct nlmsghdr *nlh); + + + /* RTNL is used as a global lock for all changes to network configuration */ +diff --git a/include/net/netlink.h b/include/net/netlink.h +index a686c9041ddc0..6e1e670e06bc4 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -905,6 +905,17 @@ static inline int nlmsg_report(const struct nlmsghdr *nlh) + return nlh ? !!(nlh->nlmsg_flags & NLM_F_ECHO) : 0; + } + ++/** ++ * nlmsg_seq - return the seq number of netlink message ++ * @nlh: netlink message header ++ * ++ * Returns 0 if netlink message is NULL ++ */ ++static inline u32 nlmsg_seq(const struct nlmsghdr *nlh) ++{ ++ return nlh ? nlh->nlmsg_seq : 0; ++} ++ + /** + * nlmsg_for_each_attr - iterate over a stream of attributes + * @pos: loop counter, set to current attribute +diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h +index fdc7b4ce0ef7b..ad8786c9777c9 100644 +--- a/include/net/rtnetlink.h ++++ b/include/net/rtnetlink.h +@@ -204,7 +204,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname, + struct nlattr *tb[], + struct netlink_ext_ack *extack); + int rtnl_delete_link(struct net_device *dev); +-int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm); ++int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm, ++ u32 portid, const struct nlmsghdr *nlh); + + int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer, + struct netlink_ext_ack *exterr); +diff --git a/net/core/dev.c b/net/core/dev.c +index a97239cd1b3a5..7c743a39747fa 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1402,7 +1402,7 @@ void netdev_state_change(struct net_device *dev) + + call_netdevice_notifiers_info(NETDEV_CHANGE, + &change_info.info); +- rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL, 0, NULL); + } + } + EXPORT_SYMBOL(netdev_state_change); +@@ -1538,7 +1538,7 @@ int dev_open(struct net_device *dev, struct netlink_ext_ack *extack) + if (ret < 0) + return ret; + +- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP | IFF_RUNNING, GFP_KERNEL, 0, NULL); + call_netdevice_notifiers(NETDEV_UP, dev); + + return ret; +@@ -1610,7 +1610,7 @@ void dev_close_many(struct list_head *head, bool unlink) + __dev_close_many(head); + + list_for_each_entry_safe(dev, tmp, head, close_list) { +- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP | IFF_RUNNING, GFP_KERNEL, 0, NULL); + call_netdevice_notifiers(NETDEV_DOWN, dev); + if (unlink) + list_del_init(&dev->close_list); +@@ -8472,7 +8472,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify) + dev_change_rx_flags(dev, IFF_PROMISC); + } + if (notify) +- __dev_notify_flags(dev, old_flags, IFF_PROMISC); ++ __dev_notify_flags(dev, old_flags, IFF_PROMISC, 0, NULL); + return 0; + } + +@@ -8527,7 +8527,7 @@ static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify) + dev_set_rx_mode(dev); + if (notify) + __dev_notify_flags(dev, old_flags, +- dev->gflags ^ old_gflags); ++ dev->gflags ^ old_gflags, 0, NULL); + } + return 0; + } +@@ -8690,12 +8690,13 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags, + } + + void __dev_notify_flags(struct net_device *dev, unsigned int old_flags, +- unsigned int gchanges) ++ unsigned int gchanges, u32 portid, ++ const struct nlmsghdr *nlh) + { + unsigned int changes = dev->flags ^ old_flags; + + if (gchanges) +- rtmsg_ifinfo(RTM_NEWLINK, dev, gchanges, GFP_ATOMIC); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, gchanges, GFP_ATOMIC, portid, nlh); + + if (changes & IFF_UP) { + if (dev->flags & IFF_UP) +@@ -8737,7 +8738,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags, + return ret; + + changes = (old_flags ^ dev->flags) | (old_gflags ^ dev->gflags); +- __dev_notify_flags(dev, old_flags, changes); ++ __dev_notify_flags(dev, old_flags, changes, 0, NULL); + return ret; + } + EXPORT_SYMBOL(dev_change_flags); +@@ -10274,7 +10275,7 @@ int register_netdevice(struct net_device *dev) + */ + if (!dev->rtnl_link_ops || + dev->rtnl_link_state == RTNL_LINK_INITIALIZED) +- rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL, 0, NULL); + + out: + return ret; +@@ -11018,7 +11019,7 @@ void unregister_netdevice_many(struct list_head *head) + if (!dev->rtnl_link_ops || + dev->rtnl_link_state == RTNL_LINK_INITIALIZED) + skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U, 0, +- GFP_KERNEL, NULL, 0); ++ GFP_KERNEL, NULL, 0, 0, 0); + + /* + * Flush the unicast and multicast chains +@@ -11033,7 +11034,7 @@ void unregister_netdevice_many(struct list_head *head) + dev->netdev_ops->ndo_uninit(dev); + + if (skb) +- rtmsg_ifinfo_send(skb, dev, GFP_KERNEL); ++ rtmsg_ifinfo_send(skb, dev, GFP_KERNEL, 0, NULL); + + /* Notifier chain MUST detach us all upper devices. */ + WARN_ON(netdev_has_any_upper_dev(dev)); +@@ -11221,7 +11222,7 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net, + * Prevent userspace races by waiting until the network + * device is fully setup before sending notifications. + */ +- rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL); ++ rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL, 0, NULL); + + synchronize_net(); + err = 0; +diff --git a/net/core/dev.h b/net/core/dev.h +index db9ff8cd8d46d..8d1afb9887dec 100644 +--- a/net/core/dev.h ++++ b/net/core/dev.h +@@ -94,6 +94,10 @@ int dev_change_carrier(struct net_device *dev, bool new_carrier); + + void __dev_set_rx_mode(struct net_device *dev); + ++void __dev_notify_flags(struct net_device *dev, unsigned int old_flags, ++ unsigned int gchanges, u32 portid, ++ const struct nlmsghdr *nlh); ++ + static inline void netif_set_gso_max_size(struct net_device *dev, + unsigned int size) + { +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 6fd6c717d1e39..73453a92ea492 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -789,7 +789,7 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) + EXPORT_SYMBOL(rtnl_unicast); + + void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, +- struct nlmsghdr *nlh, gfp_t flags) ++ const struct nlmsghdr *nlh, gfp_t flags) + { + struct sock *rtnl = net->rtnl; + +@@ -3232,7 +3232,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, + return err; + } + +-int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) ++int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm, ++ u32 portid, const struct nlmsghdr *nlh) + { + unsigned int old_flags; + int err; +@@ -3246,10 +3247,10 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) + } + + if (dev->rtnl_link_state == RTNL_LINK_INITIALIZED) { +- __dev_notify_flags(dev, old_flags, (old_flags ^ dev->flags)); ++ __dev_notify_flags(dev, old_flags, (old_flags ^ dev->flags), portid, nlh); + } else { + dev->rtnl_link_state = RTNL_LINK_INITIALIZED; +- __dev_notify_flags(dev, old_flags, ~0U); ++ __dev_notify_flags(dev, old_flags, ~0U, portid, nlh); + } + return 0; + } +@@ -3427,7 +3428,7 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, + goto out; + } + +- err = rtnl_configure_link(dev, ifm); ++ err = rtnl_configure_link(dev, ifm, 0, NULL); + if (err < 0) + goto out_unregister; + if (link_net) { +@@ -3957,7 +3958,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) + struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, + unsigned int change, + u32 event, gfp_t flags, int *new_nsid, +- int new_ifindex) ++ int new_ifindex, u32 portid, u32 seq) + { + struct net *net = dev_net(dev); + struct sk_buff *skb; +@@ -3968,7 +3969,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, + goto errout; + + err = rtnl_fill_ifinfo(skb, dev, dev_net(dev), +- type, 0, 0, change, 0, 0, event, ++ type, portid, seq, change, 0, 0, event, + new_nsid, new_ifindex, -1, flags); + if (err < 0) { + /* -EMSGSIZE implies BUG in if_nlmsg_size() */ +@@ -3983,16 +3984,18 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, + return NULL; + } + +-void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags) ++void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags, ++ u32 portid, const struct nlmsghdr *nlh) + { + struct net *net = dev_net(dev); + +- rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags); ++ rtnl_notify(skb, net, portid, RTNLGRP_LINK, nlh, flags); + } + + static void rtmsg_ifinfo_event(int type, struct net_device *dev, + unsigned int change, u32 event, +- gfp_t flags, int *new_nsid, int new_ifindex) ++ gfp_t flags, int *new_nsid, int new_ifindex, ++ u32 portid, const struct nlmsghdr *nlh) + { + struct sk_buff *skb; + +@@ -4000,23 +4003,23 @@ static void rtmsg_ifinfo_event(int type, struct net_device *dev, + return; + + skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags, new_nsid, +- new_ifindex); ++ new_ifindex, portid, nlmsg_seq(nlh)); + if (skb) +- rtmsg_ifinfo_send(skb, dev, flags); ++ rtmsg_ifinfo_send(skb, dev, flags, portid, nlh); + } + + void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change, +- gfp_t flags) ++ gfp_t flags, u32 portid, const struct nlmsghdr *nlh) + { + rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags, +- NULL, 0); ++ NULL, 0, portid, nlh); + } + + void rtmsg_ifinfo_newnet(int type, struct net_device *dev, unsigned int change, + gfp_t flags, int *new_nsid, int new_ifindex) + { + rtmsg_ifinfo_event(type, dev, change, rtnl_get_event(0), flags, +- new_nsid, new_ifindex); ++ new_nsid, new_ifindex, 0, NULL); + } + + static int nlmsg_populate_fdb_fill(struct sk_buff *skb, +@@ -6199,7 +6202,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi + case NETDEV_CHANGELOWERSTATE: + case NETDEV_CHANGE_TX_QUEUE_LEN: + rtmsg_ifinfo_event(RTM_NEWLINK, dev, 0, rtnl_get_event(event), +- GFP_KERNEL, NULL, 0); ++ GFP_KERNEL, NULL, 0, 0, NULL); + break; + default: + break; +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index b90241aff93c3..2c1228ddaa22f 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -1690,7 +1690,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, + if (err) + goto out; + +- err = rtnl_configure_link(dev, NULL); ++ err = rtnl_configure_link(dev, NULL, 0, NULL); + if (err < 0) + goto out; + +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 5cc87b85ce..3b54c695ec 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -20,3 +20,44 @@ btrfs-set-btrfs_root_orphan_cleanup-during-subvol-cr.patch alsa-hda-realtek-add-hp-laptop-14s-dr5xxx-mute-led-q.patch alsa-hda-realtek-add-headset-jack-quirk-for-thinkpad.patch usb-core-new-quirk-to-handle-devices-with-zero-confi.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +xfrm-fix-the-usage-of-skb-sk.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +af_key-validate-families-in-pfkey_send_migrate.patch +dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +rtnetlink-pass-netlink-message-header-and-portid-to-.patch +net-add-new-helper-unregister_netdevice_many_notify.patch +rtnetlink-honour-nlm_f_echo-flag-in-rtnl_delete_link.patch +openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +ice-use-ice_update_eth_stats-for-representor-stats.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch +tcp-rearrange-tests-in-inet_csk_bind_conflict.patch +tcp-optimize-inet_use_bhash2_on_bind.patch +udp-fix-wildcard-bind-conflict-check-when-using-hash.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +tls-purge-async_hold-in-tls_decrypt_async_wait.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netlink-allow-be16-and-be32-types-in-all-uint-policy.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-6.1/tcp-optimize-inet_use_bhash2_on_bind.patch b/queue-6.1/tcp-optimize-inet_use_bhash2_on_bind.patch new file mode 100644 index 0000000000..7c536154de --- /dev/null +++ b/queue-6.1/tcp-optimize-inet_use_bhash2_on_bind.patch @@ -0,0 +1,46 @@ +From 8b795a82736d95675d65aa144722591b465223d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 12:42:35 +0000 +Subject: tcp: optimize inet_use_bhash2_on_bind() + +From: Eric Dumazet + +[ Upstream commit ca79d80b0b9f42362a893f06413a9fe91811158a ] + +There is no reason to call ipv6_addr_type(). + +Instead, use highly optimized ipv6_addr_any() and ipv6_addr_v4mapped(). + +Signed-off-by: Eric Dumazet +Reviewed-by: Jason Xing +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250302124237.3913746-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index abec5206a8d17..fd3bbcffce5e6 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -155,12 +155,10 @@ static bool inet_use_bhash2_on_bind(const struct sock *sk) + { + #if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { +- int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); +- +- if (addr_type == IPV6_ADDR_ANY) ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + return false; + +- if (addr_type != IPV6_ADDR_MAPPED) ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) + return true; + } + #endif +-- +2.51.0 + diff --git a/queue-6.1/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch b/queue-6.1/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch new file mode 100644 index 0000000000..0528e54dc5 --- /dev/null +++ b/queue-6.1/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch @@ -0,0 +1,93 @@ +From 4cd2cc71787d12a4265088cde7b04b6bd3f86e9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 09:18:28 +0900 +Subject: tcp: Rearrange tests in inet_csk_bind_conflict(). + +From: Kuniyuki Iwashima + +[ Upstream commit 58655bc0ad7ccdd5b53319bcc091cb81b6aee7c3 ] + +The following patch adds code in the !inet_use_bhash2_on_bind(sk) +case in inet_csk_bind_conflict(). + +To avoid adding nest and make the change cleaner, this patch +rearranges tests in inet_csk_bind_conflict(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 40 ++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 21 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index c7e4ceefe0269..abec5206a8d17 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -240,9 +240,10 @@ static int inet_csk_bind_conflict(const struct sock *sk, + const struct inet_bind2_bucket *tb2, /* may be null */ + bool relax, bool reuseport_ok) + { +- bool reuseport_cb_ok; +- struct sock_reuseport *reuseport_cb; + kuid_t uid = sock_i_uid((struct sock *)sk); ++ struct sock_reuseport *reuseport_cb; ++ bool reuseport_cb_ok; ++ struct sock *sk2; + + rcu_read_lock(); + reuseport_cb = rcu_dereference(sk->sk_reuseport_cb); +@@ -250,32 +251,29 @@ static int inet_csk_bind_conflict(const struct sock *sk, + reuseport_cb_ok = !reuseport_cb || READ_ONCE(reuseport_cb->num_closed_socks); + rcu_read_unlock(); + +- /* +- * Unlike other sk lookup places we do not check ++ /* Conflicts with an existing IPV6_ADDR_ANY (if ipv6) or INADDR_ANY (if ++ * ipv4) should have been checked already. We need to do these two ++ * checks separately because their spinlocks have to be acquired/released ++ * independently of each other, to prevent possible deadlocks ++ */ ++ if (inet_use_bhash2_on_bind(sk)) ++ return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, ++ reuseport_cb_ok, reuseport_ok); ++ ++ /* Unlike other sk lookup places we do not check + * for sk_net here, since _all_ the socks listed + * in tb->owners and tb2->owners list belong + * to the same net - the one this bucket belongs to. + */ ++ sk_for_each_bound(sk2, &tb->owners) { ++ if (!inet_bind_conflict(sk, sk2, uid, relax, reuseport_cb_ok, reuseport_ok)) ++ continue; + +- if (!inet_use_bhash2_on_bind(sk)) { +- struct sock *sk2; +- +- sk_for_each_bound(sk2, &tb->owners) +- if (inet_bind_conflict(sk, sk2, uid, relax, +- reuseport_cb_ok, reuseport_ok) && +- inet_rcv_saddr_equal(sk, sk2, true)) +- return true; +- +- return false; ++ if (inet_rcv_saddr_equal(sk, sk2, true)) ++ return true; + } + +- /* Conflicts with an existing IPV6_ADDR_ANY (if ipv6) or INADDR_ANY (if +- * ipv4) should have been checked already. We need to do these two +- * checks separately because their spinlocks have to be acquired/released +- * independently of each other, to prevent possible deadlocks +- */ +- return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok, +- reuseport_ok); ++ return false; + } + + /* Determine if there is a bind conflict with an existing IPV6_ADDR_ANY (if ipv6) or +-- +2.51.0 + diff --git a/queue-6.1/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch b/queue-6.1/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch new file mode 100644 index 0000000000..c448af6ba9 --- /dev/null +++ b/queue-6.1/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch @@ -0,0 +1,65 @@ +From 49ace5e8b690e1d2c19ff46492c58c7aaaa2dbf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 09:18:22 +0900 +Subject: tcp: Use bhash2 for v4-mapped-v6 non-wildcard address. + +From: Kuniyuki Iwashima + +[ Upstream commit 5e07e672412bed473122813ab35d4f7d42fd9635 ] + +While checking port availability in bind() or listen(), we used only +bhash for all v4-mapped-v6 addresses. But there is no good reason not +to use bhash2 for v4-mapped-v6 non-wildcard addresses. + +Let's do it by returning true in inet_use_bhash2_on_bind(). Then, we +also need to add a test in inet_bind2_bucket_match_addr_any() so that +::ffff:X.X.X.X will match with 0.0.0.0. + +Note that sk->sk_rcv_saddr is initialised for v4-mapped-v6 sk in +__inet6_bind(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 7 +++++-- + net/ipv4/inet_hashtables.c | 3 ++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 8fa56a17f03a6..c7e4ceefe0269 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -157,8 +157,11 @@ static bool inet_use_bhash2_on_bind(const struct sock *sk) + if (sk->sk_family == AF_INET6) { + int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); + +- return addr_type != IPV6_ADDR_ANY && +- addr_type != IPV6_ADDR_MAPPED; ++ if (addr_type == IPV6_ADDR_ANY) ++ return false; ++ ++ if (addr_type != IPV6_ADDR_MAPPED) ++ return true; + } + #endif + return sk->sk_rcv_saddr != htonl(INADDR_ANY); +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 24e4bec52bb2f..de0f16ae35b31 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -832,7 +832,8 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const + return ipv6_addr_any(&tb->v6_rcv_saddr) || + ipv6_addr_v4mapped_any(&tb->v6_rcv_saddr); + +- return false; ++ return ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr) && ++ tb->rcv_saddr == 0; + } + + if (sk->sk_family == AF_INET6) +-- +2.51.0 + diff --git a/queue-6.1/tls-purge-async_hold-in-tls_decrypt_async_wait.patch b/queue-6.1/tls-purge-async_hold-in-tls_decrypt_async_wait.patch new file mode 100644 index 0000000000..df0b1e2df6 --- /dev/null +++ b/queue-6.1/tls-purge-async_hold-in-tls_decrypt_async_wait.patch @@ -0,0 +1,66 @@ +From f0771e22f0123671c20f1bb6a099d81cfc2901fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 08:53:23 -0400 +Subject: tls: Purge async_hold in tls_decrypt_async_wait() + +From: Chuck Lever + +[ Upstream commit 84a8335d8300576f1b377ae24abca1d9f197807f ] + +The async_hold queue pins encrypted input skbs while +the AEAD engine references their scatterlist data. Once +tls_decrypt_async_wait() returns, every AEAD operation +has completed and the engine no longer references those +skbs, so they can be freed unconditionally. + +A subsequent patch adds batch async decryption to +tls_sw_read_sock(), introducing a new call site that +must drain pending AEAD operations and release held +skbs. Move __skb_queue_purge(&ctx->async_hold) into +tls_decrypt_async_wait() so the purge is centralized +and every caller -- recvmsg's drain path, the -EBUSY +fallback in tls_do_decryption(), and the new read_sock +batch path -- releases held skbs on synchronization +without each site managing the purge independently. + +This fixes a leak when tls_strp_msg_hold() fails part-way through, +after having added some cloned skbs to the async_hold +queue. tls_decrypt_sg() will then call tls_decrypt_async_wait() to +process all pending decrypts, and drop back to synchronous mode, but +tls_sw_recvmsg() only flushes the async_hold queue when one record has +been processed in "fully-async" mode, which may not be the case here. + +Signed-off-by: Chuck Lever +Reported-by: Yiming Qian +Fixes: b8a6ff84abbc ("tls: wait for pending async decryptions if tls_strp_msg_hold fails") +Link: https://patch.msgid.link/20260324-tls-read-sock-v5-1-5408befe5774@oracle.com +[pabeni@redhat.com: added leak comment] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_sw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index e7f151c98eb93..4948af3bad13f 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -245,6 +245,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + atomic_inc(&ctx->decrypt_pending); + ++ __skb_queue_purge(&ctx->async_hold); + return ctx->async_wait.err; + } + +@@ -2278,7 +2279,6 @@ int tls_sw_recvmsg(struct sock *sk, + + /* Wait for all previously submitted records to be decrypted */ + ret = tls_decrypt_async_wait(ctx); +- __skb_queue_purge(&ctx->async_hold); + + if (ret) { + if (err >= 0 || err == -EINPROGRESS) +-- +2.51.0 + diff --git a/queue-6.1/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch b/queue-6.1/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch new file mode 100644 index 0000000000..91d819ff35 --- /dev/null +++ b/queue-6.1/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch @@ -0,0 +1,160 @@ +From 56c741f08383cde7a87a708836a57db153a112e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 11:18:17 -0700 +Subject: udp: Fix wildcard bind conflict check when using hash2 + +From: Martin KaFai Lau + +[ Upstream commit e537dd15d0d4ad989d56a1021290f0c674dd8b28 ] + +When binding a udp_sock to a local address and port, UDP uses +two hashes (udptable->hash and udptable->hash2) for collision +detection. The current code switches to "hash2" when +hslot->count > 10. + +"hash2" is keyed by local address and local port. +"hash" is keyed by local port only. + +The issue can be shown in the following bind sequence (pseudo code): + +bind(fd1, "[fd00::1]:8888") +bind(fd2, "[fd00::2]:8888") +bind(fd3, "[fd00::3]:8888") +bind(fd4, "[fd00::4]:8888") +bind(fd5, "[fd00::5]:8888") +bind(fd6, "[fd00::6]:8888") +bind(fd7, "[fd00::7]:8888") +bind(fd8, "[fd00::8]:8888") +bind(fd9, "[fd00::9]:8888") +bind(fd10, "[fd00::10]:8888") + +/* Correctly return -EADDRINUSE because "hash" is used + * instead of "hash2". udp_lib_lport_inuse() detects the + * conflict. + */ +bind(fail_fd, "[::]:8888") + +/* After one more socket is bound to "[fd00::11]:8888", + * hslot->count exceeds 10 and "hash2" is used instead. + */ +bind(fd11, "[fd00::11]:8888") +bind(fail_fd, "[::]:8888") /* succeeds unexpectedly */ + +The same issue applies to the IPv4 wildcard address "0.0.0.0" +and the IPv4-mapped wildcard address "::ffff:0.0.0.0". For +example, if there are existing sockets bound to +"192.168.1.[1-11]:8888", then binding "0.0.0.0:8888" or +"[::ffff:0.0.0.0]:8888" can also miss the conflict when +hslot->count > 10. + +TCP inet_csk_get_port() already has the correct check in +inet_use_bhash2_on_bind(). Rename it to +inet_use_hash2_on_bind() and move it to inet_hashtables.h +so udp.c can reuse it in this fix. + +Fixes: 30fff9231fad ("udp: bind() optimisation") +Reported-by: Andrew Onyshchuk +Signed-off-by: Martin KaFai Lau +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260319181817.1901357-1-martin.lau@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_hashtables.h | 14 ++++++++++++++ + net/ipv4/inet_connection_sock.c | 20 +++----------------- + net/ipv4/udp.c | 2 +- + 3 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index ddfa2e67fdb51..ce58cf10ecb43 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -278,6 +278,20 @@ inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk, + return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)]; + } + ++static inline bool inet_use_hash2_on_bind(const struct sock *sk) ++{ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) { ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ return false; ++ ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ return true; ++ } ++#endif ++ return sk->sk_rcv_saddr != htonl(INADDR_ANY); ++} ++ + struct inet_bind_hashbucket * + inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port); + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index fd3bbcffce5e6..dfa27273fa755 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -151,20 +151,6 @@ void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) + } + EXPORT_SYMBOL(inet_sk_get_local_port_range); + +-static bool inet_use_bhash2_on_bind(const struct sock *sk) +-{ +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) { +- if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) +- return false; +- +- if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) +- return true; +- } +-#endif +- return sk->sk_rcv_saddr != htonl(INADDR_ANY); +-} +- + static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, + kuid_t sk_uid, bool relax, + bool reuseport_cb_ok, bool reuseport_ok) +@@ -254,7 +240,7 @@ static int inet_csk_bind_conflict(const struct sock *sk, + * checks separately because their spinlocks have to be acquired/released + * independently of each other, to prevent possible deadlocks + */ +- if (inet_use_bhash2_on_bind(sk)) ++ if (inet_use_hash2_on_bind(sk)) + return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, + reuseport_cb_ok, reuseport_ok); + +@@ -371,7 +357,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); +- if (inet_use_bhash2_on_bind(sk)) { ++ if (inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false)) + goto next_port; + } +@@ -556,7 +542,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + check_bind_conflict = false; + } + +- if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) { ++ if (check_bind_conflict && inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true)) + goto fail_unlock; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index da96252dd8a16..d50c2b67c08d7 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -280,7 +280,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + } else { + hslot = udp_hashslot(udptable, net, snum); + spin_lock_bh(&hslot->lock); +- if (hslot->count > 10) { ++ if (inet_use_hash2_on_bind(sk) && hslot->count > 10) { + int exist; + unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; + +-- +2.51.0 + diff --git a/queue-6.1/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-6.1/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..e2b6015333 --- /dev/null +++ b/queue-6.1/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From e73368fc3b584c03917d4bf3dbad060870e210ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 38d9b0b5cc5db..7dd536d5f43f3 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -1768,6 +1768,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-6.1/xfrm-fix-the-usage-of-skb-sk.patch b/queue-6.1/xfrm-fix-the-usage-of-skb-sk.patch new file mode 100644 index 0000000000..285e85f893 --- /dev/null +++ b/queue-6.1/xfrm-fix-the-usage-of-skb-sk.patch @@ -0,0 +1,135 @@ +From b93b6ffcf7e99d37f260f5b09e88dab4bd43766f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 11:46:03 +0100 +Subject: xfrm: Fix the usage of skb->sk + +From: Steffen Klassert + +[ Upstream commit 1620c88887b16940e00dbe57dd38c74eda9bad9e ] + +xfrm assumed to always have a full socket at skb->sk. +This is not always true, so fix it by converting to a +full socket before it is used. + +Signed-off-by: Steffen Klassert +Reviewed-by: Eric Dumazet +Stable-dep-of: 0c0eef8ccd24 ("esp: fix skb leak with espintcp and async crypto") +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 2 +- + net/ipv6/esp6.c | 2 +- + net/ipv6/xfrm6_output.c | 4 ++-- + net/xfrm/xfrm_interface_core.c | 2 +- + net/xfrm/xfrm_output.c | 7 ++++--- + net/xfrm/xfrm_policy.c | 2 +- + 6 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index a40f78a6474c6..70ad42826c3db 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -236,7 +236,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 48963fc9057bc..a7cc96fc7c247 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -272,7 +272,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c +index ad07904642cad..ff183bd76c998 100644 +--- a/net/ipv6/xfrm6_output.c ++++ b/net/ipv6/xfrm6_output.c +@@ -82,14 +82,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + toobig = skb->len > mtu && !skb_is_gso(skb); + +- if (toobig && xfrm6_local_dontfrag(skb->sk)) { ++ if (toobig && xfrm6_local_dontfrag(sk)) { + xfrm6_local_rxpmtu(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; + } else if (toobig && xfrm6_noneed_fragment(skb)) { + skb->ignore_df = 1; + goto skip_frag; +- } else if (!skb->ignore_df && toobig && skb->sk) { ++ } else if (!skb->ignore_df && toobig && sk) { + xfrm_local_error(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; +diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c +index 45466fa4ace43..87983f963f4f6 100644 +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -498,7 +498,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + skb_dst_set(skb, dst); + skb->dev = tdev; + +- err = dst_output(xi->net, skb->sk, skb); ++ err = dst_output(xi->net, skb_to_full_sk(skb), skb); + if (net_xmit_eval(err) == 0) { + dev_sw_netstats_tx_add(dev, 1, length); + } else { +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index c59c548d8fc10..290059d9e08e0 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -782,7 +782,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) + !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { + skb->protocol = htons(ETH_P_IP); + +- if (skb->sk) ++ if (skb->sk && sk_fullsock(skb->sk)) + xfrm_local_error(skb, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, +@@ -818,6 +818,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + { + int mtu, ret = 0; + struct dst_entry *dst = skb_dst(skb); ++ struct sock *sk = skb_to_full_sk(skb); + + if (skb->ignore_df) + goto out; +@@ -832,9 +833,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + skb->dev = dst->dev; + skb->protocol = htons(ETH_P_IPV6); + +- if (xfrm6_local_dontfrag(skb->sk)) ++ if (xfrm6_local_dontfrag(sk)) + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); +- else if (skb->sk) ++ else if (sk) + xfrm_local_error(skb, mtu); + else + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index e015ff225b27a..cd534803a0e42 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2858,7 +2858,7 @@ static void xfrm_policy_queue_process(struct timer_list *t) + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- dst_output(net, skb->sk, skb); ++ dst_output(net, skb_to_full_sk(skb), skb); + } + + out: +-- +2.51.0 + diff --git a/queue-6.12/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-6.12/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..7c4ac6e3c0 --- /dev/null +++ b/queue-6.12/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From ae557652b00a22e08c2588d12890da2603b2140b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 9dea2b26e5069..6d7848b824d9b 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch b/queue-6.12/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch new file mode 100644 index 0000000000..4ffa4f64af --- /dev/null +++ b/queue-6.12/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch @@ -0,0 +1,101 @@ +From 349e0b59ee1427c33c7553548ae885cc85085a44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 20:54:03 +0800 +Subject: Bluetooth: btintel: serialize btintel_hw_error() with + hci_req_sync_lock + +From: Cen Zhang + +[ Upstream commit 94d8e6fe5d0818e9300e514e095a200bd5ff93ae ] + +btintel_hw_error() issues two __hci_cmd_sync() calls (HCI_OP_RESET +and Intel exception-info retrieval) without holding +hci_req_sync_lock(). This lets it race against +hci_dev_do_close() -> btintel_shutdown_combined(), which also runs +__hci_cmd_sync() under the same lock. When both paths manipulate +hdev->req_status/req_rsp concurrently, the close path may free the +response skb first, and the still-running hw_error path hits a +slab-use-after-free in kfree_skb(). + +Wrap the whole recovery sequence in hci_req_sync_lock/unlock so it +is serialized with every other synchronous HCI command issuer. + +Below is the data race report and the kasan report: + + BUG: data-race in __hci_cmd_sync_sk / btintel_shutdown_combined + + read of hdev->req_rsp at net/bluetooth/hci_sync.c:199 + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x114/0x670 drivers/bluetooth/btintel.c:254 + hci_error_reset+0x348/0xa30 net/bluetooth/hci_core.c:1030 + + write/free by task ioctl/22580: + btintel_shutdown_combined+0xd0/0x360 + drivers/bluetooth/btintel.c:3648 + hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246 + hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526 + + BUG: KASAN: slab-use-after-free in + sk_skb_reason_drop+0x43/0x380 net/core/skbuff.c:1202 + Read of size 4 at addr ffff888144a738dc + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x186/0x670 drivers/bluetooth/btintel.c:260 + +Fixes: 973bb97e5aee ("Bluetooth: btintel: Add generic function for handling hardware errors") +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 3a4db68fc2e63..6e3e4a817e727 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -245,11 +245,13 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + + bt_dev_err(hdev, "Hardware error 0x%2.2x", code); + ++ hci_req_sync_lock(hdev); ++ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reset after hardware error failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + kfree_skb(skb); + +@@ -257,18 +259,21 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + + if (skb->len != 13) { + bt_dev_err(hdev, "Exception info size mismatch"); + kfree_skb(skb); +- return; ++ goto unlock; + } + + bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); + + kfree_skb(skb); ++ ++unlock: ++ hci_req_sync_unlock(hdev); + } + EXPORT_SYMBOL_GPL(btintel_hw_error); + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-6.12/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..0ca71f551d --- /dev/null +++ b/queue-6.12/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From 4fb2280c415ea997e881b0b1185cb0e57078950a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 9d3236321056b..b8bf4dfea11c2 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2350,8 +2350,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-6.12/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..87061a13c4 --- /dev/null +++ b/queue-6.12/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From 384704864c94396ab799d36a00df74eca8486d49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 4a0b5c3160c2b..4d987dece2d0c 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-6.12/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..78d9c07f32 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From de430916c17b9a21ab9fb92a4ee54a580be52f80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 58679045093a9..128f5701efb46 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2383,6 +2383,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4283,14 +4286,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-6.12/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..0f26315b63 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From 82c26e865943f5ebc3061f07f60fd26a13f79844 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index ef1b8a44420ed..697b997f3fb65 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1668,6 +1668,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch b/queue-6.12/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch new file mode 100644 index 0000000000..98c3225ed0 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch @@ -0,0 +1,50 @@ +From 4b7e7a96ce4ae3cf02a02518018b4a02a09ad46b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 17:32:11 +0800 +Subject: Bluetooth: L2CAP: Fix send LE flow credits in ACL link + +From: Zhang Chen + +[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ] + +When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, +l2cap_publish_rx_avail will be called and le flow credits will be sent in +l2cap_chan_rx_avail, even though the link type is ACL. + +The logs in question as follows: +> ACL Data RX: Handle 129 flags 0x02 dlen 12 + L2CAP: Unknown (0x16) ident 4 len 4 + 40 00 ed 05 +< ACL Data TX: Handle 129 flags 0x00 dlen 10 + L2CAP: Command Reject (0x01) ident 4 len 2 + Reason: Command not understood (0x0000) + +Bluetooth: Unknown BR/EDR signaling command 0x16 +Bluetooth: Wrong link type (-22) + +Fixes: ce60b9231b66 ("Bluetooth: compute LE flow credits based on recvbuf space") +Signed-off-by: Zhang Chen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index c65724d19fcfe..58679045093a9 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6554,6 +6554,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + struct l2cap_le_credits pkt; + u16 return_credits = l2cap_le_rx_credits(chan); + ++ if (chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ + if (chan->rx_credits >= return_credits) + return; + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch b/queue-6.12/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch new file mode 100644 index 0000000000..e6f4d7bb64 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch @@ -0,0 +1,67 @@ +From 7f29ae01328259385e42ea96a308a800692654bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 22:14:37 +0900 +Subject: Bluetooth: L2CAP: Fix stack-out-of-bounds read in + l2cap_ecred_conn_req + +From: Minseo Park + +[ Upstream commit 9d87cb22195b2c67405f5485d525190747ad5493 ] + +Syzbot reported a KASAN stack-out-of-bounds read in l2cap_build_cmd() +that is triggered by a malformed Enhanced Credit Based Connection Request. + +The vulnerability stems from l2cap_ecred_conn_req(). The function allocates +a local stack buffer (`pdu`) designed to hold a maximum of 5 Source Channel +IDs (SCIDs), totaling 18 bytes. When an attacker sends a request with more +than 5 SCIDs, the function calculates `rsp_len` based on this unvalidated +`cmd_len` before checking if the number of SCIDs exceeds +L2CAP_ECRED_MAX_CID. + +If the SCID count is too high, the function correctly jumps to the +`response` label to reject the packet, but `rsp_len` retains the +attacker's oversized value. Consequently, l2cap_send_cmd() is instructed +to read past the end of the 18-byte `pdu` buffer, triggering a +KASAN panic. + +Fix this by moving the assignment of `rsp_len` to after the `num_scid` +boundary check. If the packet is rejected, `rsp_len` will safely +remain 0, and the error response will only read the 8-byte base header +from the stack. + +Fixes: c28d2bff7044 ("Bluetooth: L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short") +Reported-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b7f3e7d9a596bf6a63e3 +Tested-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Signed-off-by: Minseo Park +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 7c131e4640b75..13f124cc4b6b1 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -5030,14 +5030,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, + cmd_len -= sizeof(*req); + num_scid = cmd_len / sizeof(u16); + +- /* Always respond with the same number of scids as in the request */ +- rsp_len = cmd_len; +- + if (num_scid > L2CAP_ECRED_MAX_CID) { + result = L2CAP_CR_LE_INVALID_PARAMS; + goto response; + } + ++ /* Always respond with the same number of scids as in the request */ ++ rsp_len = cmd_len; ++ + mtu = __le16_to_cpu(req->mtu); + mps = __le16_to_cpu(req->mps); + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-6.12/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..dd3165c1c9 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 746e7413e8f9dca8953275a2f07d3bc62585d1f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 13f124cc4b6b1..c65724d19fcfe 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6637,6 +6637,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch b/queue-6.12/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch new file mode 100644 index 0000000000..48ed0d3ae2 --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch @@ -0,0 +1,42 @@ +From 47653414054f9cff8c1eb3b3a53e0215e2133c0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:03:27 -0400 +Subject: Bluetooth: MGMT: Fix dangling pointer on + mgmt_add_adv_patterns_monitor_complete + +From: Luiz Augusto von Dentz + +[ Upstream commit 5f5fa4cd35f707344f65ce9e225b6528691dbbaa ] + +This fixes the condition checking so mgmt_pending_valid is executed +whenever status != -ECANCELED otherwise calling mgmt_pending_free(cmd) +would kfree(cmd) without unlinking it from the list first, leaving a +dangling pointer. Any subsequent list traversal (e.g., +mgmt_pending_foreach during __mgmt_power_off, or another +mgmt_pending_valid call) would dereference freed memory. + +Link: https://lore.kernel.org/linux-bluetooth/20260315132013.75ab40c5@kernel.org/T/#m1418f9c82eeff8510c1beaa21cf53af20db96c06 +Fixes: 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs") +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index b1df591a53805..ba6651f23d5d0 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -5332,7 +5332,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, + * hci_adv_monitors_clear is about to be called which will take care of + * freeing the adv_monitor instances. + */ +- if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd)) ++ if (status == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) + return; + + monitor = cmd->user_data; +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-6.12/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..6f853442dd --- /dev/null +++ b/queue-6.12/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From 1bde0078a6bed30d5765ff0977580c27e45d1ec2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 202d75ad0dc39..ad3439bd4d51a 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -339,7 +339,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -348,11 +348,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-6.12/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-6.12/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..60c9e3990a --- /dev/null +++ b/queue-6.12/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From bc4ee5f9230e5d4acaf9e490a9e51afd47919e72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index 65230e81fa08c..c86cbb3ed9c54 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -467,7 +467,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -571,7 +571,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 25fdf060e30d0..2f78ea8ac30b0 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-6.12/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-6.12/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..8d0c8a0ff4 --- /dev/null +++ b/queue-6.12/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From ca1a6f5c4973e9600883d4448a242c340b92fb90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index 22b9099927fad..ac7803e3fa613 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -195,8 +195,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-6.12/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch b/queue-6.12/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch new file mode 100644 index 0000000000..00daf00d3f --- /dev/null +++ b/queue-6.12/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch @@ -0,0 +1,83 @@ +From b5c4cb062ba58637b69e9eec30d2d20e5c12db2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 17:27:49 +0900 +Subject: dma: swiotlb: add KMSAN annotations to swiotlb_bounce() + +From: Shigeru Yoshida + +[ Upstream commit 6f770b73d0311a5b099277653199bb6421c4fed2 ] + +When a device performs DMA to a bounce buffer, KMSAN is unaware of +the write and does not mark the data as initialized. When +swiotlb_bounce() later copies the bounce buffer back to the original +buffer, memcpy propagates the uninitialized shadow to the original +buffer, causing false positive uninit-value reports. + +Fix this by calling kmsan_unpoison_memory() on the bounce buffer +before copying it back in the DMA_FROM_DEVICE path, so that memcpy +naturally propagates initialized shadow to the destination. + +Suggested-by: Alexander Potapenko +Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/ +Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") +Signed-off-by: Shigeru Yoshida +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index abcf3fa63a569..e2445b3af7468 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -903,10 +904,19 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + + local_irq_save(flags); + page = pfn_to_page(pfn); +- if (dir == DMA_TO_DEVICE) ++ if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_highmem_page() ++ * could be used here to detect infoleaks, ++ * but callers may map uninitialized buffers ++ * that will be written by the device, ++ * causing false positives. ++ */ + memcpy_from_page(vaddr, page, offset, sz); +- else ++ } else { ++ kmsan_unpoison_memory(vaddr, sz); + memcpy_to_page(page, offset, vaddr, sz); ++ } + local_irq_restore(flags); + + size -= sz; +@@ -915,8 +925,15 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + offset = 0; + } + } else if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_memory() could be used here to detect ++ * infoleaks (uninitialized data being sent to device), but ++ * callers may map uninitialized buffers that will be written ++ * by the device, causing false positives. ++ */ + memcpy(vaddr, phys_to_virt(orig_addr), size); + } else { ++ kmsan_unpoison_memory(vaddr, size); + memcpy(phys_to_virt(orig_addr), vaddr, size); + } + } +-- +2.51.0 + diff --git a/queue-6.12/erofs-set-fileio-bio-failed-in-short-read-case.patch b/queue-6.12/erofs-set-fileio-bio-failed-in-short-read-case.patch new file mode 100644 index 0000000000..7ce3a5cbba --- /dev/null +++ b/queue-6.12/erofs-set-fileio-bio-failed-in-short-read-case.patch @@ -0,0 +1,60 @@ +From 336deeb0d33dace496eb162be0235c91bf4742f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Feb 2026 10:30:08 +0800 +Subject: erofs: set fileio bio failed in short read case + +From: Sheng Yong + +[ Upstream commit eade54040384f54b7fb330e4b0975c5734850b3c ] + +For file-backed mount, IO requests are handled by vfs_iocb_iter_read(). +However, it can be interrupted by SIGKILL, returning the number of +bytes actually copied. Unused folios in bio are unexpectedly marked +as uptodate. + + vfs_read + filemap_read + filemap_get_pages + filemap_readahead + erofs_fileio_readahead + erofs_fileio_rq_submit + vfs_iocb_iter_read + filemap_read + filemap_get_pages <= detect signal + erofs_fileio_ki_complete <= set all folios uptodate + +This patch addresses this by setting short read bio with an error +directly. + +Fixes: bc804a8d7e86 ("erofs: handle end of filesystem properly for file-backed mounts") +Reported-by: chenguanyou +Signed-off-by: Yunlei He +Signed-off-by: Sheng Yong +Reviewed-by: Gao Xiang +Reviewed-by: Chao Yu +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/fileio.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c +index 2c7f066daacdd..2c46c69f43295 100644 +--- a/fs/erofs/fileio.c ++++ b/fs/erofs/fileio.c +@@ -25,10 +25,8 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret) + container_of(iocb, struct erofs_fileio_rq, iocb); + struct folio_iter fi; + +- if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) { +- bio_advance(&rq->bio, ret); +- zero_fill_bio(&rq->bio); +- } ++ if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) ++ ret = -EIO; + if (!rq->bio.bi_end_io) { + bio_for_each_folio_all(fi, &rq->bio) { + DBG_BUGON(folio_test_uptodate(fi.folio)); +-- +2.51.0 + diff --git a/queue-6.12/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-6.12/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..8363488c2a --- /dev/null +++ b/queue-6.12/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 922139bfd89fc5d3e59ef031bfbb0e150adbecd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index b8c7c8b42c0a0..deea0b934d910 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -235,10 +235,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 9c4c7b1f29550..20c1149f0f0a3 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -271,10 +271,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-6.12/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch b/queue-6.12/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch new file mode 100644 index 0000000000..4ec4e62996 --- /dev/null +++ b/queue-6.12/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch @@ -0,0 +1,158 @@ +From ff26ef2da92b0b2bbe75c903649b9635cf0b38c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Feb 2026 19:14:25 +0000 +Subject: iavf: fix out-of-bounds writes in iavf_get_ethtool_stats() + +From: Kohei Enju + +[ Upstream commit fecacfc95f195b99c71c579a472120d0b4ed65fa ] + +iavf incorrectly uses real_num_tx_queues for ETH_SS_STATS. Since the +value could change in runtime, we should use num_tx_queues instead. + +Moreover iavf_get_ethtool_stats() uses num_active_queues while +iavf_get_sset_count() and iavf_get_stat_strings() use +real_num_tx_queues, which triggers out-of-bounds writes when we do +"ethtool -L" and "ethtool -S" simultaneously [1]. + +For example when we change channels from 1 to 8, Thread 3 could be +scheduled before Thread 2, and out-of-bounds writes could be triggered +in Thread 3: + +Thread 1 (ethtool -L) Thread 2 (work) Thread 3 (ethtool -S) +iavf_set_channels() +... +iavf_alloc_queues() +-> num_active_queues = 8 +iavf_schedule_finish_config() + iavf_get_sset_count() + real_num_tx_queues: 1 + -> buffer for 1 queue + iavf_get_ethtool_stats() + num_active_queues: 8 + -> out-of-bounds! + iavf_finish_config() + -> real_num_tx_queues = 8 + +Use immutable num_tx_queues in all related functions to avoid the issue. + +[1] + BUG: KASAN: vmalloc-out-of-bounds in iavf_add_one_ethtool_stat+0x200/0x270 + Write of size 8 at addr ffffc900031c9080 by task ethtool/5800 + + CPU: 1 UID: 0 PID: 5800 Comm: ethtool Not tainted 6.19.0-enjuk-08403-g8137e3db7f1c #241 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + Call Trace: + + dump_stack_lvl+0x6f/0xb0 + print_report+0x170/0x4f3 + kasan_report+0xe1/0x180 + iavf_add_one_ethtool_stat+0x200/0x270 + iavf_get_ethtool_stats+0x14c/0x2e0 + __dev_ethtool+0x3d0c/0x5830 + dev_ethtool+0x12d/0x270 + dev_ioctl+0x53c/0xe30 + sock_do_ioctl+0x1a9/0x270 + sock_ioctl+0x3d4/0x5e0 + __x64_sys_ioctl+0x137/0x1c0 + do_syscall_64+0xf3/0x690 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + RIP: 0033:0x7f7da0e6e36d + ... + + + The buggy address belongs to a 1-page vmalloc region starting at 0xffffc900031c9000 allocated at __dev_ethtool+0x3cc9/0x5830 + The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff88813a013de0 pfn:0x13a013 + flags: 0x200000000000000(node=0|zone=2) + raw: 0200000000000000 0000000000000000 dead000000000122 0000000000000000 + raw: ffff88813a013de0 0000000000000000 00000001ffffffff 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffffc900031c8f80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ffffc900031c9080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffffc900031c9100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9180: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + +Fixes: 64430f70ba6f ("iavf: Fix displaying queue statistics shown by ethtool") +Signed-off-by: Kohei Enju +Reviewed-by: Simon Horman +Reviewed-by: Przemek Kitszel +Reviewed-by: Paul Menzel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../net/ethernet/intel/iavf/iavf_ethtool.c | 31 +++++++++---------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +index 74a1e9fe18212..53e5a3bd9b956 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +@@ -311,14 +311,13 @@ static int iavf_get_sset_count(struct net_device *netdev, int sset) + { + /* Report the maximum number queues, even if not every queue is + * currently configured. Since allocation of queues is in pairs, +- * use netdev->real_num_tx_queues * 2. The real_num_tx_queues is set +- * at device creation and never changes. ++ * use netdev->num_tx_queues * 2. The num_tx_queues is set at ++ * device creation and never changes. + */ + + if (sset == ETH_SS_STATS) + return IAVF_STATS_LEN + +- (IAVF_QUEUE_STATS_LEN * 2 * +- netdev->real_num_tx_queues); ++ (IAVF_QUEUE_STATS_LEN * 2 * netdev->num_tx_queues); + else + return -EINVAL; + } +@@ -343,19 +342,19 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, + iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats); + + rcu_read_lock(); +- /* As num_active_queues describe both tx and rx queues, we can use +- * it to iterate over rings' stats. ++ /* Use num_tx_queues to report stats for the maximum number of queues. ++ * Queues beyond num_active_queues will report zero. + */ +- for (i = 0; i < adapter->num_active_queues; i++) { +- struct iavf_ring *ring; ++ for (i = 0; i < netdev->num_tx_queues; i++) { ++ struct iavf_ring *tx_ring = NULL, *rx_ring = NULL; + +- /* Tx rings stats */ +- ring = &adapter->tx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ if (i < adapter->num_active_queues) { ++ tx_ring = &adapter->tx_rings[i]; ++ rx_ring = &adapter->rx_rings[i]; ++ } + +- /* Rx rings stats */ +- ring = &adapter->rx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ iavf_add_queue_stats(&data, tx_ring); ++ iavf_add_queue_stats(&data, rx_ring); + } + rcu_read_unlock(); + } +@@ -374,9 +373,9 @@ static void iavf_get_stat_strings(struct net_device *netdev, u8 *data) + iavf_add_stat_strings(&data, iavf_gstrings_stats); + + /* Queues are always allocated in pairs, so we just use +- * real_num_tx_queues for both Tx and Rx queues. ++ * num_tx_queues for both Tx and Rx queues. + */ +- for (i = 0; i < netdev->real_num_tx_queues; i++) { ++ for (i = 0; i < netdev->num_tx_queues; i++) { + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, + "tx", i); + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, +-- +2.51.0 + diff --git a/queue-6.12/ice-fix-inverted-ready-check-for-vf-representors.patch b/queue-6.12/ice-fix-inverted-ready-check-for-vf-representors.patch new file mode 100644 index 0000000000..8ee6823a76 --- /dev/null +++ b/queue-6.12/ice-fix-inverted-ready-check-for-vf-representors.patch @@ -0,0 +1,50 @@ +From 85c285184af3b2ab1ce151ae7b99aaf44a5f45a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:10 +0100 +Subject: ice: fix inverted ready check for VF representors + +From: Petr Oros + +[ Upstream commit ad85de0fc09eb3236e73df5acb2bc257625103f5 ] + +Commit 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +refactored the VF readiness check into a generic repr->ops.ready() +callback but implemented ice_repr_ready_vf() with inverted logic: + + return !ice_check_vf_ready_for_cfg(repr->vf); + +ice_check_vf_ready_for_cfg() returns 0 on success, so the negation +makes ready() return non-zero when the VF is ready. All callers treat +non-zero as "not ready, skip", causing ndo_get_stats64, get_drvinfo, +get_strings and get_ethtool_stats to always bail out in switchdev mode. + +Remove the erroneous negation. The SF variant ice_repr_ready_sf() is +already correct (returns !active, i.e. non-zero when not active). + +Fixes: 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Michal Swiatkowski +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_repr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index 970a99a52bf18..1b1288d243248 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -314,7 +314,7 @@ ice_repr_reg_netdev(struct net_device *netdev, const struct net_device_ops *ops) + + static int ice_repr_ready_vf(struct ice_repr *repr) + { +- return !ice_check_vf_ready_for_cfg(repr->vf); ++ return ice_check_vf_ready_for_cfg(repr->vf); + } + + static int ice_repr_ready_sf(struct ice_repr *repr) +-- +2.51.0 + diff --git a/queue-6.12/ice-use-ice_update_eth_stats-for-representor-stats.patch b/queue-6.12/ice-use-ice_update_eth_stats-for-representor-stats.patch new file mode 100644 index 0000000000..b2e9d64862 --- /dev/null +++ b/queue-6.12/ice-use-ice_update_eth_stats-for-representor-stats.patch @@ -0,0 +1,100 @@ +From 501c5ef90bacbb42ab25bdf58b7cfa9f69dbe49e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:11 +0100 +Subject: ice: use ice_update_eth_stats() for representor stats + +From: Petr Oros + +[ Upstream commit 2526e440df2725e7328d59b835a164826f179b93 ] + +ice_repr_get_stats64() and __ice_get_ethtool_stats() call +ice_update_vsi_stats() on the VF's src_vsi. This always returns early +because ICE_VSI_DOWN is permanently set for VF VSIs - ice_up() is never +called on them since queues are managed by iavf through virtchnl. + +In __ice_get_ethtool_stats() the original code called +ice_update_vsi_stats() for all VSIs including representors, iterated +over ice_gstrings_vsi_stats[] to populate the data, and then bailed out +with an early return before the per-queue ring stats section. That early +return was necessary because representor VSIs have no rings on the PF +side - the rings belong to the VF driver (iavf), so accessing per-queue +stats would be invalid. + +Move the representor handling to the top of __ice_get_ethtool_stats() +and call ice_update_eth_stats() directly to read the hardware GLV_* +counters. This matches ice_get_vf_stats() which already uses +ice_update_eth_stats() for the same VF VSI in legacy mode. Apply the +same fix to ice_repr_get_stats64(). + +Note that ice_gstrings_vsi_stats[] contains five software ring counters +(rx_buf_failed, rx_page_failed, tx_linearize, tx_busy, tx_restart) that +are always zero for representors since the PF never processes packets on +VF rings. This is pre-existing behavior unchanged by this patch. + +Fixes: 7aae80cef7ba ("ice: add port representor ethtool ops and stats") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 14 +++++++++++--- + drivers/net/ethernet/intel/ice/ice_repr.c | 3 ++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index b2183d5670b8c..606994fa99da9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1930,6 +1930,17 @@ __ice_get_ethtool_stats(struct net_device *netdev, + int i = 0; + char *p; + ++ if (ice_is_port_repr_netdev(netdev)) { ++ ice_update_eth_stats(vsi); ++ ++ for (j = 0; j < ICE_VSI_STATS_LEN; j++) { ++ p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; ++ data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ return; ++ } ++ + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + +@@ -1939,9 +1950,6 @@ __ice_get_ethtool_stats(struct net_device *netdev, + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + +- if (ice_is_port_repr_netdev(netdev)) +- return; +- + /* populate per queue stats */ + rcu_read_lock(); + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index 1b1288d243248..e8a9b6a5dd7ab 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2019-2021, Intel Corporation. */ + + #include "ice.h" ++#include "ice_lib.h" + #include "ice_eswitch.h" + #include "devlink/devlink.h" + #include "devlink/devlink_port.h" +@@ -67,7 +68,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) + return; + vsi = repr->src_vsi; + +- ice_update_vsi_stats(vsi); ++ ice_update_eth_stats(vsi); + eth_stats = &vsi->eth_stats; + + stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast + +-- +2.51.0 + diff --git a/queue-6.12/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-6.12/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..cd18cab836 --- /dev/null +++ b/queue-6.12/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From 2eea02e3f9e96512f34addd849c215e087b1bd82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index d6bea71528057..8119281b26d07 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1718,13 +1718,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-6.12/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch b/queue-6.12/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch new file mode 100644 index 0000000000..dd9a29347f --- /dev/null +++ b/queue-6.12/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch @@ -0,0 +1,144 @@ +From 8470275354d0df193f6b6885b943c9173f7468c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:23:00 +0000 +Subject: ipv6: Don't remove permanent routes with exceptions from + tb6_gc_hlist. + +From: Kuniyuki Iwashima + +[ Upstream commit 4be7b99c253f0c85a255cc1db7127ba3232dfa30 ] + +The cited commit mechanically put fib6_remove_gc_list() +just after every fib6_clean_expires() call. + +When a temporary route is promoted to a permanent route, +there may already be exception routes tied to it. + +If fib6_remove_gc_list() removes the route from tb6_gc_hlist, +such exception routes will no longer be aged. + +Let's replace fib6_remove_gc_list() with a new helper +fib6_may_remove_gc_list() and use fib6_age_exceptions() there. + +Note that net->ipv6 is only compiled when CONFIG_IPV6 is +enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded. + +Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/ip6_fib.h | 21 ++++++++++++++++++++- + net/ipv6/addrconf.c | 4 ++-- + net/ipv6/ip6_fib.c | 6 +++--- + net/ipv6/route.c | 2 +- + 4 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 6cb867ce48784..74b78c80af71d 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -506,12 +506,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt, + void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + unsigned int flags); + ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now); + void fib6_run_gc(unsigned long expires, struct net *net, bool force); +- + void fib6_gc_cleanup(void); + + int fib6_init(void); + ++#if IS_ENABLED(CONFIG_IPV6) + /* Add the route to the gc list if it is not already there + * + * The callers should hold f6i->fib6_table->tb6_lock. +@@ -544,6 +546,23 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i) + hlist_del_init(&f6i->gc_link); + } + ++static inline void fib6_may_remove_gc_list(struct net *net, ++ struct fib6_info *f6i) ++{ ++ struct fib6_gc_args gc_args; ++ ++ if (hlist_unhashed(&f6i->gc_link)) ++ return; ++ ++ gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval); ++ gc_args.more = 0; ++ ++ rcu_read_lock(); ++ fib6_age_exceptions(f6i, &gc_args, jiffies); ++ rcu_read_unlock(); ++} ++#endif ++ + struct ipv6_route_iter { + struct seq_net_private p; + struct fib6_walker w; +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index e57a2b1841616..63ada312061c6 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2860,7 +2860,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) + fib6_add_gc_list(rt); + } else { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } + + spin_unlock_bh(&table->tb6_lock); +@@ -4850,7 +4850,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp, + + if (!(flags & RTF_EXPIRES)) { + fib6_clean_expires(f6i); +- fib6_remove_gc_list(f6i); ++ fib6_may_remove_gc_list(net, f6i); + } else { + fib6_set_expires(f6i, expires); + fib6_add_gc_list(f6i); +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index fca68fb1b74c2..2072c788c912a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + return -EEXIST; + if (!(rt->fib6_flags & RTF_EXPIRES)) { + fib6_clean_expires(iter); +- fib6_remove_gc_list(iter); ++ fib6_may_remove_gc_list(info->nl_net, iter); + } else { + fib6_set_expires(iter, rt->expires); + fib6_add_gc_list(iter); +@@ -2314,8 +2314,8 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ +-static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, +- unsigned long now) ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) + { + bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; + int old_more = gc_args->more; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 36324d1905f81..31c9e3b73f2da 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1034,7 +1034,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + + if (!addrconf_finite_timeout(lifetime)) { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } else { + fib6_set_expires(rt, jiffies + HZ * lifetime); + fib6_add_gc_list(rt); +-- +2.51.0 + diff --git a/queue-6.12/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch b/queue-6.12/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch new file mode 100644 index 0000000000..4a3204a624 --- /dev/null +++ b/queue-6.12/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch @@ -0,0 +1,76 @@ +From 8c7c1ae66a4ccffbe6653de078fdf1eaad49ee9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:22:59 +0000 +Subject: ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions + expire. + +From: Kuniyuki Iwashima + +[ Upstream commit 6af51e9f31336632263c4680b2a3712295103e1f ] + +Commit 5eb902b8e719 ("net/ipv6: Remove expired routes with a +separated list of routes.") introduced a per-table GC list and +changed GC to iterate over that list instead of traversing +the entire route table. + +However, it forgot to add permanent routes to tb6_gc_hlist +when exception routes are added. + +Commit cfe82469a00f ("ipv6: add exception routes to GC list +in rt6_insert_exception") fixed that issue but introduced +another one. + +Even after all exception routes expire, the permanent routes +remain in tb6_gc_hlist, potentially negating the performance +benefits intended by the initial change. + +Let's count gc_args->more before and after rt6_age_exceptions() +and remove the permanent route when the delta is 0. + +Note that the next patch will reuse fib6_age_exceptions(). + +Fixes: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Xin Long +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 01c953a39211a..fca68fb1b74c2 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -2314,6 +2314,17 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ ++static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) ++{ ++ bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; ++ int old_more = gc_args->more; ++ ++ rt6_age_exceptions(rt, gc_args, now); ++ ++ if (!may_expire && old_more == gc_args->more) ++ fib6_remove_gc_list(rt); ++} + + static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + { +@@ -2336,7 +2347,7 @@ static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + * Note, that clones are aged out + * only if they are not in use now. + */ +- rt6_age_exceptions(rt, gc_args, now); ++ fib6_age_exceptions(rt, gc_args, now); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.12/net-bcm-asp2-convert-to-phylib-managed-eee.patch b/queue-6.12/net-bcm-asp2-convert-to-phylib-managed-eee.patch new file mode 100644 index 0000000000..486dcb1e1b --- /dev/null +++ b/queue-6.12/net-bcm-asp2-convert-to-phylib-managed-eee.patch @@ -0,0 +1,156 @@ +From 94016a0611154b734b7771f0472216a21713c830 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:50:57 +0000 +Subject: net: bcm: asp2: convert to phylib managed EEE + +From: Russell King (Oracle) + +[ Upstream commit 21f56ad1b21131eb2c9c16e11ccb28f77b5addc4 ] + +Convert the Broadcom ASP2 driver to use phylib managed EEE support. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Link: https://patch.msgid.link/E1tXk81-000r4x-TS@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.h | 3 -- + .../ethernet/broadcom/asp2/bcmasp_ethtool.c | 31 ------------------- + .../net/ethernet/broadcom/asp2/bcmasp_intf.c | 19 ++++++------ + 3 files changed, 10 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +index f93cb3da44b0c..8fc75bcedb70f 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +@@ -348,8 +348,6 @@ struct bcmasp_intf { + /* Used if per intf wol irq */ + int wol_irq; + unsigned int wol_irq_enabled:1; +- +- struct ethtool_keee eee; + }; + + #define NUM_NET_FILTERS 32 +@@ -601,5 +599,4 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + + void bcmasp_netfilt_suspend(struct bcmasp_intf *intf); + +-void bcmasp_eee_enable_set(struct bcmasp_intf *intf, bool enable); + #endif +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +index 73334ab526136..c24107baefcfd 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +@@ -348,20 +348,6 @@ static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + return err; + } + +-void bcmasp_eee_enable_set(struct bcmasp_intf *intf, bool enable) +-{ +- u32 reg; +- +- reg = umac_rl(intf, UMC_EEE_CTRL); +- if (enable) +- reg |= EEE_EN; +- else +- reg &= ~EEE_EN; +- umac_wl(intf, reg, UMC_EEE_CTRL); +- +- intf->eee.eee_enabled = enable; +-} +- + static int bcmasp_get_eee(struct net_device *dev, struct ethtool_keee *e) + { + if (!dev->phydev) +@@ -372,26 +358,9 @@ static int bcmasp_get_eee(struct net_device *dev, struct ethtool_keee *e) + + static int bcmasp_set_eee(struct net_device *dev, struct ethtool_keee *e) + { +- struct bcmasp_intf *intf = netdev_priv(dev); +- struct ethtool_keee *p = &intf->eee; +- int ret; +- + if (!dev->phydev) + return -ENODEV; + +- if (!p->eee_enabled) { +- bcmasp_eee_enable_set(intf, false); +- } else { +- ret = phy_init_eee(dev->phydev, 0); +- if (ret) { +- netif_err(intf, hw, dev, +- "EEE initialization failed: %d\n", ret); +- return ret; +- } +- +- bcmasp_eee_enable_set(intf, true); +- } +- + return phy_ethtool_set_eee(dev->phydev, e); + } + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index 73e704352d820..acf45789d4493 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -616,7 +616,6 @@ static void bcmasp_adj_link(struct net_device *dev) + struct phy_device *phydev = dev->phydev; + u32 cmd_bits = 0, reg; + int changed = 0; +- bool active; + + if (intf->old_link != phydev->link) { + changed = 1; +@@ -675,9 +674,12 @@ static void bcmasp_adj_link(struct net_device *dev) + umac_wl(intf, reg, UMC_CMD); + + umac_wl(intf, phydev->eee_cfg.tx_lpi_timer, UMC_EEE_LPI_TIMER); +- +- active = phy_init_eee(phydev, 0) >= 0; +- bcmasp_eee_enable_set(intf, active); ++ reg = umac_rl(intf, UMC_EEE_CTRL); ++ if (phydev->enable_tx_lpi) ++ reg |= EEE_EN; ++ else ++ reg &= ~EEE_EN; ++ umac_wl(intf, reg, UMC_EEE_CTRL); + } + + reg = rgmii_rl(intf, RGMII_OOB_CNTRL); +@@ -1336,7 +1338,8 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf) + ASP_WAKEUP_INTR2_MASK_CLEAR); + } + +- if (intf->eee.eee_enabled && intf->parent->eee_fixup) ++ if (ndev->phydev && ndev->phydev->eee_cfg.eee_enabled && ++ intf->parent->eee_fixup) + intf->parent->eee_fixup(intf, true); + + netif_dbg(intf, wol, ndev, "entered WOL mode\n"); +@@ -1378,7 +1381,8 @@ static void bcmasp_resume_from_wol(struct bcmasp_intf *intf) + { + u32 reg; + +- if (intf->eee.eee_enabled && intf->parent->eee_fixup) ++ if (intf->ndev->phydev && intf->ndev->phydev->eee_cfg.eee_enabled && ++ intf->parent->eee_fixup) + intf->parent->eee_fixup(intf, false); + + reg = umac_rl(intf, UMC_MPD_CTRL); +@@ -1409,9 +1413,6 @@ int bcmasp_interface_resume(struct bcmasp_intf *intf) + + bcmasp_resume_from_wol(intf); + +- if (intf->eee.eee_enabled) +- bcmasp_eee_enable_set(intf, true); +- + netif_device_attach(dev); + + return 0; +-- +2.51.0 + diff --git a/queue-6.12/net-bcm-asp2-fix-lpi-timer-handling.patch b/queue-6.12/net-bcm-asp2-fix-lpi-timer-handling.patch new file mode 100644 index 0000000000..5933b84164 --- /dev/null +++ b/queue-6.12/net-bcm-asp2-fix-lpi-timer-handling.patch @@ -0,0 +1,70 @@ +From d4e90ad5b23d950ba9036ca69e7274ac152e9e82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:50:47 +0000 +Subject: net: bcm: asp2: fix LPI timer handling + +From: Russell King (Oracle) + +[ Upstream commit 54033f5512191fa355422d009f32923c1cf24aab ] + +Fix the LPI timer handling in Broadcom ASP2 driver after the phylib +managed EEE patches were merged. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Link: https://patch.msgid.link/E1tXk7r-000r4l-Li@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 2 -- + drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 5 +++++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +index ca163c8e37297..256577f0f2170 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +@@ -371,7 +371,6 @@ static int bcmasp_get_eee(struct net_device *dev, struct ethtool_keee *e) + return -ENODEV; + + e->tx_lpi_enabled = p->tx_lpi_enabled; +- e->tx_lpi_timer = umac_rl(intf, UMC_EEE_LPI_TIMER); + + return phy_ethtool_get_eee(dev->phydev, e); + } +@@ -395,7 +394,6 @@ static int bcmasp_set_eee(struct net_device *dev, struct ethtool_keee *e) + return ret; + } + +- umac_wl(intf, e->tx_lpi_timer, UMC_EEE_LPI_TIMER); + intf->eee.tx_lpi_enabled = e->tx_lpi_enabled; + bcmasp_eee_enable_set(intf, true); + } +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index 79185bafaf4b3..73e704352d820 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -674,6 +674,8 @@ static void bcmasp_adj_link(struct net_device *dev) + } + umac_wl(intf, reg, UMC_CMD); + ++ umac_wl(intf, phydev->eee_cfg.tx_lpi_timer, UMC_EEE_LPI_TIMER); ++ + active = phy_init_eee(phydev, 0) >= 0; + bcmasp_eee_enable_set(intf, active); + } +@@ -1052,6 +1054,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) + + /* Indicate that the MAC is responsible for PHY PM */ + phydev->mac_managed_pm = true; ++ ++ /* Set phylib's copy of the LPI timer */ ++ phydev->eee_cfg.tx_lpi_timer = umac_rl(intf, UMC_EEE_LPI_TIMER); + } + + umac_reset(intf); +-- +2.51.0 + diff --git a/queue-6.12/net-bcm-asp2-remove-tx_lpi_enabled.patch b/queue-6.12/net-bcm-asp2-remove-tx_lpi_enabled.patch new file mode 100644 index 0000000000..9411bd07b7 --- /dev/null +++ b/queue-6.12/net-bcm-asp2-remove-tx_lpi_enabled.patch @@ -0,0 +1,56 @@ +From 8f03b42a8c7e0d4510a075b48ba6affe57fc35c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:50:52 +0000 +Subject: net: bcm: asp2: remove tx_lpi_enabled + +From: Russell King (Oracle) + +[ Upstream commit df8017e8a19d72b48abfe02b8611a5c8c7f89e22 ] + +Phylib maintains a copy of tx_lpi_enabled, which will be used to +populate the member when phy_ethtool_get_eee(). Therefore, writing to +this member before phy_ethtool_get_eee() will have no effect. Remove +it. Also remove setting our copy of info->eee.tx_lpi_enabled which +becomes write-only. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Link: https://patch.msgid.link/E1tXk7w-000r4r-Pq@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +index 256577f0f2170..73334ab526136 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +@@ -364,14 +364,9 @@ void bcmasp_eee_enable_set(struct bcmasp_intf *intf, bool enable) + + static int bcmasp_get_eee(struct net_device *dev, struct ethtool_keee *e) + { +- struct bcmasp_intf *intf = netdev_priv(dev); +- struct ethtool_keee *p = &intf->eee; +- + if (!dev->phydev) + return -ENODEV; + +- e->tx_lpi_enabled = p->tx_lpi_enabled; +- + return phy_ethtool_get_eee(dev->phydev, e); + } + +@@ -394,7 +389,6 @@ static int bcmasp_set_eee(struct net_device *dev, struct ethtool_keee *e) + return ret; + } + +- intf->eee.tx_lpi_enabled = e->tx_lpi_enabled; + bcmasp_eee_enable_set(intf, true); + } + +-- +2.51.0 + diff --git a/queue-6.12/net-bcmasp-add-support-for-asp-v3.0.patch b/queue-6.12/net-bcmasp-add-support-for-asp-v3.0.patch new file mode 100644 index 0000000000..56f2536f64 --- /dev/null +++ b/queue-6.12/net-bcmasp-add-support-for-asp-v3.0.patch @@ -0,0 +1,458 @@ +From 61a825c554846beb5585f8678b0e06f5f264082b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 16:36:44 -0700 +Subject: net: bcmasp: Add support for asp-v3.0 + +From: Justin Chen + +[ Upstream commit e9f31435ee7d1dd350f5efaf9de7b0db3ad4bbfe ] + +The asp-v3.0 is a major HW revision that reduced the number of +channels and filters. The goal was to save cost by reducing the +feature set. + +Changes for asp-v3.0 +- Number of network filters were reduced. +- Number of channels were reduced. +- EDPKT stats were removed. +- Fix a bug with csum offload. + +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250422233645.1931036-8-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 27dfe9030acb ("net: bcmasp: fix double disable of clk") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 79 +++++++++++++------ + drivers/net/ethernet/broadcom/asp2/bcmasp.h | 33 ++++++-- + .../ethernet/broadcom/asp2/bcmasp_ethtool.c | 15 +--- + .../net/ethernet/broadcom/asp2/bcmasp_intf.c | 13 ++- + 4 files changed, 92 insertions(+), 48 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 44f55eb72f174..9f2947d2d41f0 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -518,7 +518,7 @@ void bcmasp_netfilt_suspend(struct bcmasp_intf *intf) + int ret, i; + + /* Write all filters to HW */ +- for (i = 0; i < NUM_NET_FILTERS; i++) { ++ for (i = 0; i < priv->num_net_filters; i++) { + /* If the filter does not match the port, skip programming. */ + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) +@@ -551,7 +551,7 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + struct bcmasp_priv *priv = intf->parent; + int j = 0, i; + +- for (i = 0; i < NUM_NET_FILTERS; i++) { ++ for (i = 0; i < priv->num_net_filters; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; +@@ -577,7 +577,7 @@ int bcmasp_netfilt_get_active(struct bcmasp_intf *intf) + struct bcmasp_priv *priv = intf->parent; + int cnt = 0, i; + +- for (i = 0; i < NUM_NET_FILTERS; i++) { ++ for (i = 0; i < priv->num_net_filters; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; +@@ -602,7 +602,7 @@ bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf, + size_t fs_size = 0; + int i; + +- for (i = 0; i < NUM_NET_FILTERS; i++) { ++ for (i = 0; i < priv->num_net_filters; i++) { + if (!priv->net_filters[i].claimed || + priv->net_filters[i].port != intf->port) + continue; +@@ -670,7 +670,7 @@ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, + int i, open_index = -1; + + /* Check whether we exceed the filter table capacity */ +- if (loc != RX_CLS_LOC_ANY && loc >= NUM_NET_FILTERS) ++ if (loc != RX_CLS_LOC_ANY && loc >= priv->num_net_filters) + return ERR_PTR(-EINVAL); + + /* If the filter location is busy (already claimed) and we are initializing +@@ -686,7 +686,7 @@ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, + /* Initialize the loop index based on the desired location or from 0 */ + i = loc == RX_CLS_LOC_ANY ? 0 : loc; + +- for ( ; i < NUM_NET_FILTERS; i++) { ++ for ( ; i < priv->num_net_filters; i++) { + /* Found matching network filter */ + if (!init && + priv->net_filters[i].claimed && +@@ -779,7 +779,7 @@ static void bcmasp_en_mda_filter(struct bcmasp_intf *intf, bool en, + priv->mda_filters[i].en = en; + priv->mda_filters[i].port = intf->port; + +- rx_filter_core_wl(priv, ((intf->channel + 8) | ++ rx_filter_core_wl(priv, ((intf->channel + priv->tx_chan_offset) | + (en << ASP_RX_FILTER_MDA_CFG_EN_SHIFT) | + ASP_RX_FILTER_MDA_CFG_UMC_SEL(intf->port)), + ASP_RX_FILTER_MDA_CFG(i)); +@@ -865,7 +865,7 @@ void bcmasp_disable_all_filters(struct bcmasp_intf *intf) + res_count = bcmasp_total_res_mda_cnt(intf->parent); + + /* Disable all filters held by this port */ +- for (i = res_count; i < NUM_MDA_FILTERS; i++) { ++ for (i = res_count; i < priv->num_mda_filters; i++) { + if (priv->mda_filters[i].en && + priv->mda_filters[i].port == intf->port) + bcmasp_en_mda_filter(intf, 0, i); +@@ -909,7 +909,7 @@ int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr, + + res_count = bcmasp_total_res_mda_cnt(intf->parent); + +- for (i = res_count; i < NUM_MDA_FILTERS; i++) { ++ for (i = res_count; i < priv->num_mda_filters; i++) { + /* If filter not enabled or belongs to another port skip */ + if (!priv->mda_filters[i].en || + priv->mda_filters[i].port != intf->port) +@@ -924,7 +924,7 @@ int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr, + } + + /* Create new filter if possible */ +- for (i = res_count; i < NUM_MDA_FILTERS; i++) { ++ for (i = res_count; i < priv->num_mda_filters; i++) { + if (priv->mda_filters[i].en) + continue; + +@@ -944,12 +944,12 @@ static void bcmasp_core_init_filters(struct bcmasp_priv *priv) + /* Disable all filters and reset software view since the HW + * can lose context while in deep sleep suspend states + */ +- for (i = 0; i < NUM_MDA_FILTERS; i++) { ++ for (i = 0; i < priv->num_mda_filters; i++) { + rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_MDA_CFG(i)); + priv->mda_filters[i].en = 0; + } + +- for (i = 0; i < NUM_NET_FILTERS; i++) ++ for (i = 0; i < priv->num_net_filters; i++) + rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_NET_CFG(i)); + + /* Top level filter enable bit should be enabled at all times, set +@@ -966,18 +966,8 @@ static void bcmasp_core_init_filters(struct bcmasp_priv *priv) + /* ASP core initialization */ + static void bcmasp_core_init(struct bcmasp_priv *priv) + { +- tx_analytics_core_wl(priv, 0x0, ASP_TX_ANALYTICS_CTRL); +- rx_analytics_core_wl(priv, 0x4, ASP_RX_ANALYTICS_CTRL); +- +- rx_edpkt_core_wl(priv, (ASP_EDPKT_HDR_SZ_128 << ASP_EDPKT_HDR_SZ_SHIFT), +- ASP_EDPKT_HDR_CFG); +- rx_edpkt_core_wl(priv, +- (ASP_EDPKT_ENDI_BT_SWP_WD << ASP_EDPKT_ENDI_DESC_SHIFT), +- ASP_EDPKT_ENDI); +- + rx_edpkt_core_wl(priv, 0x1b, ASP_EDPKT_BURST_BUF_PSCAL_TOUT); + rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_WRITE_TOUT); +- rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_READ_TOUT); + + rx_edpkt_core_wl(priv, ASP_EDPKT_ENABLE_EN, ASP_EDPKT_ENABLE); + +@@ -1020,6 +1010,18 @@ static void bcmasp_core_clock_select_one(struct bcmasp_priv *priv, bool slow) + ctrl_core_wl(priv, reg, ASP_CTRL_CORE_CLOCK_SELECT); + } + ++static void bcmasp_core_clock_select_one_ctrl2(struct bcmasp_priv *priv, bool slow) ++{ ++ u32 reg; ++ ++ reg = ctrl2_core_rl(priv, ASP_CTRL2_CORE_CLOCK_SELECT); ++ if (slow) ++ reg &= ~ASP_CTRL2_CORE_CLOCK_SELECT_MAIN; ++ else ++ reg |= ASP_CTRL2_CORE_CLOCK_SELECT_MAIN; ++ ctrl2_core_wl(priv, reg, ASP_CTRL2_CORE_CLOCK_SELECT); ++} ++ + static void bcmasp_core_clock_set_ll(struct bcmasp_priv *priv, u32 clr, u32 set) + { + u32 reg; +@@ -1174,22 +1176,43 @@ static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + + static const struct bcmasp_plat_data v21_plat_data = { + .core_clock_select = bcmasp_core_clock_select_one, ++ .num_mda_filters = 32, ++ .num_net_filters = 32, ++ .tx_chan_offset = 8, ++ .rx_ctrl_offset = 0x0, + }; + + static const struct bcmasp_plat_data v22_plat_data = { + .core_clock_select = bcmasp_core_clock_select_many, + .eee_fixup = bcmasp_eee_fixup, ++ .num_mda_filters = 32, ++ .num_net_filters = 32, ++ .tx_chan_offset = 8, ++ .rx_ctrl_offset = 0x0, ++}; ++ ++static const struct bcmasp_plat_data v30_plat_data = { ++ .core_clock_select = bcmasp_core_clock_select_one_ctrl2, ++ .num_mda_filters = 20, ++ .num_net_filters = 16, ++ .tx_chan_offset = 0, ++ .rx_ctrl_offset = 0x10000, + }; + + static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata) + { + priv->core_clock_select = pdata->core_clock_select; + priv->eee_fixup = pdata->eee_fixup; ++ priv->num_mda_filters = pdata->num_mda_filters; ++ priv->num_net_filters = pdata->num_net_filters; ++ priv->tx_chan_offset = pdata->tx_chan_offset; ++ priv->rx_ctrl_offset = pdata->rx_ctrl_offset; + } + + static const struct of_device_id bcmasp_of_match[] = { + { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data }, + { .compatible = "brcm,asp-v2.2", .data = &v22_plat_data }, ++ { .compatible = "brcm,asp-v3.0", .data = &v30_plat_data }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, bcmasp_of_match); +@@ -1197,6 +1220,7 @@ MODULE_DEVICE_TABLE(of, bcmasp_of_match); + static const struct of_device_id bcmasp_mdio_of_match[] = { + { .compatible = "brcm,asp-v2.1-mdio", }, + { .compatible = "brcm,asp-v2.2-mdio", }, ++ { .compatible = "brcm,asp-v3.0-mdio", }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, bcmasp_mdio_of_match); +@@ -1278,6 +1302,17 @@ static int bcmasp_probe(struct platform_device *pdev) + * how many interfaces come up. + */ + bcmasp_core_init(priv); ++ ++ priv->mda_filters = devm_kcalloc(dev, priv->num_mda_filters, ++ sizeof(*priv->mda_filters), GFP_KERNEL); ++ if (!priv->mda_filters) ++ return -ENOMEM; ++ ++ priv->net_filters = devm_kcalloc(dev, priv->num_net_filters, ++ sizeof(*priv->net_filters), GFP_KERNEL); ++ if (!priv->net_filters) ++ return -ENOMEM; ++ + bcmasp_core_init_filters(priv); + + bcmasp_init_wol(priv); +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +index 6f49ebad4e99c..74adfdb50e11d 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +@@ -363,6 +363,10 @@ struct bcmasp_mda_filter { + struct bcmasp_plat_data { + void (*core_clock_select)(struct bcmasp_priv *priv, bool slow); + void (*eee_fixup)(struct bcmasp_intf *priv, bool en); ++ unsigned int num_mda_filters; ++ unsigned int num_net_filters; ++ unsigned int tx_chan_offset; ++ unsigned int rx_ctrl_offset; + }; + + struct bcmasp_priv { +@@ -379,12 +383,16 @@ struct bcmasp_priv { + + void (*core_clock_select)(struct bcmasp_priv *priv, bool slow); + void (*eee_fixup)(struct bcmasp_intf *intf, bool en); ++ unsigned int num_mda_filters; ++ unsigned int num_net_filters; ++ unsigned int tx_chan_offset; ++ unsigned int rx_ctrl_offset; + + void __iomem *base; + + struct list_head intfs; + +- struct bcmasp_mda_filter mda_filters[NUM_MDA_FILTERS]; ++ struct bcmasp_mda_filter *mda_filters; + + /* MAC destination address filters lock */ + spinlock_t mda_lock; +@@ -392,7 +400,7 @@ struct bcmasp_priv { + /* Protects accesses to ASP_CTRL_CLOCK_CTRL */ + spinlock_t clk_lock; + +- struct bcmasp_net_filter net_filters[NUM_NET_FILTERS]; ++ struct bcmasp_net_filter *net_filters; + + /* Network filter lock */ + struct mutex net_lock; +@@ -482,8 +490,8 @@ BCMASP_FP_IO_MACRO_Q(rx_edpkt_cfg); + #define PKT_OFFLOAD_EPKT_IP(x) ((x) << 21) + #define PKT_OFFLOAD_EPKT_TP(x) ((x) << 19) + #define PKT_OFFLOAD_EPKT_LEN(x) ((x) << 16) +-#define PKT_OFFLOAD_EPKT_CSUM_L3 BIT(15) +-#define PKT_OFFLOAD_EPKT_CSUM_L2 BIT(14) ++#define PKT_OFFLOAD_EPKT_CSUM_L4 BIT(15) ++#define PKT_OFFLOAD_EPKT_CSUM_L3 BIT(14) + #define PKT_OFFLOAD_EPKT_ID(x) ((x) << 12) + #define PKT_OFFLOAD_EPKT_SEQ(x) ((x) << 10) + #define PKT_OFFLOAD_EPKT_TS(x) ((x) << 8) +@@ -515,12 +523,27 @@ BCMASP_CORE_IO_MACRO(intr2, ASP_INTR2_OFFSET); + BCMASP_CORE_IO_MACRO(wakeup_intr2, ASP_WAKEUP_INTR2_OFFSET); + BCMASP_CORE_IO_MACRO(tx_analytics, ASP_TX_ANALYTICS_OFFSET); + BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET); +-BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET); + BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET); + BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET); + BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL_OFFSET); + BCMASP_CORE_IO_MACRO(ctrl2, ASP_CTRL2_OFFSET); + ++#define BCMASP_CORE_IO_MACRO_OFFSET(name, offset) \ ++static inline u32 name##_core_rl(struct bcmasp_priv *priv, \ ++ u32 off) \ ++{ \ ++ u32 reg = readl_relaxed(priv->base + priv->name##_offset + \ ++ (offset) + off); \ ++ return reg; \ ++} \ ++static inline void name##_core_wl(struct bcmasp_priv *priv, \ ++ u32 val, u32 off) \ ++{ \ ++ writel_relaxed(val, priv->base + priv->name##_offset + \ ++ (offset) + off); \ ++} ++BCMASP_CORE_IO_MACRO_OFFSET(rx_ctrl, ASP_RX_CTRL_OFFSET); ++ + struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + struct device_node *ndev_dn, int i); + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +index 6d537fe461cc9..b489406221e43 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +@@ -10,7 +10,6 @@ + #include "bcmasp_intf_defs.h" + + enum bcmasp_stat_type { +- BCMASP_STAT_RX_EDPKT, + BCMASP_STAT_RX_CTRL, + BCMASP_STAT_RX_CTRL_PER_INTF, + BCMASP_STAT_SOFT, +@@ -33,8 +32,6 @@ struct bcmasp_stats { + .reg_offset = offset, \ + } + +-#define STAT_BCMASP_RX_EDPKT(str, offset) \ +- STAT_BCMASP_OFFSET(str, BCMASP_STAT_RX_EDPKT, offset) + #define STAT_BCMASP_RX_CTRL(str, offset) \ + STAT_BCMASP_OFFSET(str, BCMASP_STAT_RX_CTRL, offset) + #define STAT_BCMASP_RX_CTRL_PER_INTF(str, offset) \ +@@ -42,11 +39,6 @@ struct bcmasp_stats { + + /* Must match the order of struct bcmasp_mib_counters */ + static const struct bcmasp_stats bcmasp_gstrings_stats[] = { +- /* EDPKT counters */ +- STAT_BCMASP_RX_EDPKT("RX Time Stamp", ASP_EDPKT_RX_TS_COUNTER), +- STAT_BCMASP_RX_EDPKT("RX PKT Count", ASP_EDPKT_RX_PKT_CNT), +- STAT_BCMASP_RX_EDPKT("RX PKT Buffered", ASP_EDPKT_HDR_EXTR_CNT), +- STAT_BCMASP_RX_EDPKT("RX PKT Pushed to DRAM", ASP_EDPKT_HDR_OUT_CNT), + /* ASP RX control */ + STAT_BCMASP_RX_CTRL_PER_INTF("Frames From Unimac", + ASP_RX_CTRL_UMAC_0_FRAME_COUNT), +@@ -113,9 +105,6 @@ static void bcmasp_update_mib_counters(struct bcmasp_intf *intf) + switch (s->type) { + case BCMASP_STAT_SOFT: + continue; +- case BCMASP_STAT_RX_EDPKT: +- val = rx_edpkt_core_rl(intf->parent, offset); +- break; + case BCMASP_STAT_RX_CTRL: + val = rx_ctrl_core_rl(intf->parent, offset); + break; +@@ -272,7 +261,7 @@ static int bcmasp_flow_get(struct bcmasp_intf *intf, struct ethtool_rxnfc *cmd) + + memcpy(&cmd->fs, &nfilter->fs, sizeof(nfilter->fs)); + +- cmd->data = NUM_NET_FILTERS; ++ cmd->data = intf->parent->num_net_filters; + + return 0; + } +@@ -319,7 +308,7 @@ static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + break; + case ETHTOOL_GRXCLSRLALL: + err = bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt); +- cmd->data = NUM_NET_FILTERS; ++ cmd->data = intf->parent->num_net_filters; + break; + default: + err = -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index 3836456fcb9cf..4998b9c0357ca 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -180,14 +180,14 @@ static struct sk_buff *bcmasp_csum_offload(struct net_device *dev, + case htons(ETH_P_IP): + header |= PKT_OFFLOAD_HDR_SIZE_2((ip_hdrlen(skb) >> 8) & 0xf); + header2 |= PKT_OFFLOAD_HDR2_SIZE_2(ip_hdrlen(skb) & 0xff); +- epkt |= PKT_OFFLOAD_EPKT_IP(0) | PKT_OFFLOAD_EPKT_CSUM_L2; ++ epkt |= PKT_OFFLOAD_EPKT_IP(0); + ip_proto = ip_hdr(skb)->protocol; + header_cnt += 2; + break; + case htons(ETH_P_IPV6): + header |= PKT_OFFLOAD_HDR_SIZE_2((IP6_HLEN >> 8) & 0xf); + header2 |= PKT_OFFLOAD_HDR2_SIZE_2(IP6_HLEN & 0xff); +- epkt |= PKT_OFFLOAD_EPKT_IP(1) | PKT_OFFLOAD_EPKT_CSUM_L2; ++ epkt |= PKT_OFFLOAD_EPKT_IP(1); + ip_proto = ipv6_hdr(skb)->nexthdr; + header_cnt += 2; + break; +@@ -198,12 +198,12 @@ static struct sk_buff *bcmasp_csum_offload(struct net_device *dev, + switch (ip_proto) { + case IPPROTO_TCP: + header2 |= PKT_OFFLOAD_HDR2_SIZE_3(tcp_hdrlen(skb)); +- epkt |= PKT_OFFLOAD_EPKT_TP(0) | PKT_OFFLOAD_EPKT_CSUM_L3; ++ epkt |= PKT_OFFLOAD_EPKT_TP(0) | PKT_OFFLOAD_EPKT_CSUM_L4; + header_cnt++; + break; + case IPPROTO_UDP: + header2 |= PKT_OFFLOAD_HDR2_SIZE_3(UDP_HLEN); +- epkt |= PKT_OFFLOAD_EPKT_TP(1) | PKT_OFFLOAD_EPKT_CSUM_L3; ++ epkt |= PKT_OFFLOAD_EPKT_TP(1) | PKT_OFFLOAD_EPKT_CSUM_L4; + header_cnt++; + break; + default: +@@ -815,9 +815,7 @@ static void bcmasp_init_tx(struct bcmasp_intf *intf) + /* Tx SPB */ + tx_spb_ctrl_wl(intf, ((intf->channel + 8) << TX_SPB_CTRL_XF_BID_SHIFT), + TX_SPB_CTRL_XF_CTRL2); +- tx_pause_ctrl_wl(intf, (1 << (intf->channel + 8)), TX_PAUSE_MAP_VECTOR); + tx_spb_top_wl(intf, 0x1e, TX_SPB_TOP_BLKOUT); +- tx_spb_top_wl(intf, 0x0, TX_SPB_TOP_SPRE_BW_CTRL); + + tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_READ); + tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_BASE); +@@ -1182,7 +1180,7 @@ static void bcmasp_map_res(struct bcmasp_priv *priv, struct bcmasp_intf *intf) + { + /* Per port */ + intf->res.umac = priv->base + UMC_OFFSET(intf); +- intf->res.umac2fb = priv->base + (UMAC2FB_OFFSET + ++ intf->res.umac2fb = priv->base + (UMAC2FB_OFFSET + priv->rx_ctrl_offset + + (intf->port * 0x4)); + intf->res.rgmii = priv->base + RGMII_OFFSET(intf); + +@@ -1197,7 +1195,6 @@ static void bcmasp_map_res(struct bcmasp_priv *priv, struct bcmasp_intf *intf) + intf->rx_edpkt_cfg = priv->base + RX_EDPKT_CFG_OFFSET(intf); + } + +-#define MAX_IRQ_STR_LEN 64 + struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, + struct device_node *ndev_dn, int i) + { +-- +2.51.0 + diff --git a/queue-6.12/net-bcmasp-fix-double-disable-of-clk.patch b/queue-6.12/net-bcmasp-fix-double-disable-of-clk.patch new file mode 100644 index 0000000000..10b6d31193 --- /dev/null +++ b/queue-6.12/net-bcmasp-fix-double-disable-of-clk.patch @@ -0,0 +1,122 @@ +From 4297766a19f6bc55fb7da20482f12c4975dcd0d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:13 -0700 +Subject: net: bcmasp: fix double disable of clk + +From: Justin Chen + +[ Upstream commit 27dfe9030acbc601c260b42ecdbb4e5858a97b53 ] + +Switch to devm_clk_get_optional() so we can manage the clock ourselves. +We dynamically control the clocks depending on the state of the interface +for power savings. The default state is clock disabled, so unbinding the +driver causes a double disable. + +Fixes: 490cb412007d ("net: bcmasp: Add support for ASP2.0 Ethernet controller") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 33 ++++++++++++++------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 9f2947d2d41f0..2ef5f49beab86 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1253,7 +1253,7 @@ static int bcmasp_probe(struct platform_device *pdev) + if (priv->irq <= 0) + return -EINVAL; + +- priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp"); ++ priv->clk = devm_clk_get_optional(dev, "sw_asp"); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to request clock\n"); +@@ -1281,6 +1281,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + bcmasp_set_pdata(priv, pdata); + ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to start clock\n"); ++ + /* Enable all clocks to ensure successful probing */ + bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); + +@@ -1292,8 +1296,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0, + pdev->name, priv); +- if (ret) +- return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret); ++ if (ret) { ++ dev_err(dev, "Failed to request ASP interrupt: %d", ret); ++ goto err_clock_disable; ++ } + + /* Register mdio child nodes */ + of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev); +@@ -1305,13 +1311,17 @@ static int bcmasp_probe(struct platform_device *pdev) + + priv->mda_filters = devm_kcalloc(dev, priv->num_mda_filters, + sizeof(*priv->mda_filters), GFP_KERNEL); +- if (!priv->mda_filters) +- return -ENOMEM; ++ if (!priv->mda_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + priv->net_filters = devm_kcalloc(dev, priv->num_net_filters, + sizeof(*priv->net_filters), GFP_KERNEL); +- if (!priv->net_filters) +- return -ENOMEM; ++ if (!priv->net_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + bcmasp_core_init_filters(priv); + +@@ -1320,7 +1330,8 @@ static int bcmasp_probe(struct platform_device *pdev) + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_clock_disable; + } + + i = 0; +@@ -1342,8 +1353,6 @@ static int bcmasp_probe(struct platform_device *pdev) + */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE); + +- clk_disable_unprepare(priv->clk); +- + /* Now do the registration of the network ports which will take care + * of managing the clock properly. + */ +@@ -1356,12 +1365,16 @@ static int bcmasp_probe(struct platform_device *pdev) + count++; + } + ++ clk_disable_unprepare(priv->clk); ++ + dev_info(dev, "Initialized %d port(s)\n", count); + + return ret; + + err_cleanup: + bcmasp_remove_intfs(priv); ++err_clock_disable: ++ clk_disable_unprepare(priv->clk); + + return ret; + } +-- +2.51.0 + diff --git a/queue-6.12/net-bcmasp-fix-double-free-of-wol-irq.patch b/queue-6.12/net-bcmasp-fix-double-free-of-wol-irq.patch new file mode 100644 index 0000000000..c1df949d62 --- /dev/null +++ b/queue-6.12/net-bcmasp-fix-double-free-of-wol-irq.patch @@ -0,0 +1,58 @@ +From a2a803c5511e6b0f34477d64f9cde88e35784d90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:12 -0700 +Subject: net: bcmasp: fix double free of WoL irq + +From: Justin Chen + +[ Upstream commit cbfa5be2bf64511d49b854a0f9fd6d0b5118621f ] + +We do not need to free wol_irq since it was instantiated with +devm_request_irq(). So devres will free for us. + +Fixes: a2f0751206b0 ("net: bcmasp: Add support for WoL magic packet") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-2-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 1e73595096c13..44f55eb72f174 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1154,12 +1154,6 @@ void bcmasp_enable_wol(struct bcmasp_intf *intf, bool en) + } + } + +-static void bcmasp_wol_irq_destroy(struct bcmasp_priv *priv) +-{ +- if (priv->wol_irq > 0) +- free_irq(priv->wol_irq, priv); +-} +- + static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + { + u32 reg, phy_lpi_overwrite; +@@ -1332,7 +1326,6 @@ static int bcmasp_probe(struct platform_device *pdev) + return ret; + + err_cleanup: +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + + return ret; +@@ -1345,7 +1338,6 @@ static void bcmasp_remove(struct platform_device *pdev) + if (!priv) + return; + +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + } + +-- +2.51.0 + diff --git a/queue-6.12/net-bcmasp-remove-support-for-asp-v2.0.patch b/queue-6.12/net-bcmasp-remove-support-for-asp-v2.0.patch new file mode 100644 index 0000000000..1134037cfc --- /dev/null +++ b/queue-6.12/net-bcmasp-remove-support-for-asp-v2.0.patch @@ -0,0 +1,379 @@ +From 2a844ed53edf3f1e02f474700df29772f23e0703 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 16:36:40 -0700 +Subject: net: bcmasp: Remove support for asp-v2.0 + +From: Justin Chen + +[ Upstream commit 4ad8cb76bd0d17827fd0c84707c0d72c8710b0e9 ] + +The SoC that supported asp-v2.0 never saw the light of day. asp-v2.0 has +quirks that makes the logic overly complicated. For example, asp-v2.0 is +the only revision that has a different wake up IRQ hook up. Remove asp-v2.0 +support to make supporting future HW revisions cleaner. + +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20250422233645.1931036-4-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 97 ++----------------- + drivers/net/ethernet/broadcom/asp2/bcmasp.h | 45 ++------- + .../ethernet/broadcom/asp2/bcmasp_ethtool.c | 21 +--- + .../net/ethernet/broadcom/asp2/bcmasp_intf.c | 2 +- + .../ethernet/broadcom/asp2/bcmasp_intf_defs.h | 3 +- + 5 files changed, 22 insertions(+), 146 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 297c2682a9cf9..57932e5c54e01 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -141,7 +141,7 @@ void bcmasp_flush_rx_port(struct bcmasp_intf *intf) + return; + } + +- rx_ctrl_core_wl(priv, mask, priv->hw_info->rx_ctrl_flush); ++ rx_ctrl_core_wl(priv, mask, ASP_RX_CTRL_FLUSH); + } + + static void bcmasp_netfilt_hw_en_wake(struct bcmasp_priv *priv, +@@ -1108,7 +1108,7 @@ static int bcmasp_get_and_request_irq(struct bcmasp_priv *priv, int i) + return irq; + } + +-static void bcmasp_init_wol_shared(struct bcmasp_priv *priv) ++static void bcmasp_init_wol(struct bcmasp_priv *priv) + { + struct platform_device *pdev = priv->pdev; + struct device *dev = &pdev->dev; +@@ -1125,7 +1125,7 @@ static void bcmasp_init_wol_shared(struct bcmasp_priv *priv) + device_set_wakeup_capable(&pdev->dev, 1); + } + +-static void bcmasp_enable_wol_shared(struct bcmasp_intf *intf, bool en) ++void bcmasp_enable_wol(struct bcmasp_intf *intf, bool en) + { + struct bcmasp_priv *priv = intf->parent; + struct device *dev = &priv->pdev->dev; +@@ -1154,54 +1154,12 @@ static void bcmasp_enable_wol_shared(struct bcmasp_intf *intf, bool en) + } + } + +-static void bcmasp_wol_irq_destroy_shared(struct bcmasp_priv *priv) ++static void bcmasp_wol_irq_destroy(struct bcmasp_priv *priv) + { + if (priv->wol_irq > 0) + free_irq(priv->wol_irq, priv); + } + +-static void bcmasp_init_wol_per_intf(struct bcmasp_priv *priv) +-{ +- struct platform_device *pdev = priv->pdev; +- struct device *dev = &pdev->dev; +- struct bcmasp_intf *intf; +- int irq; +- +- list_for_each_entry(intf, &priv->intfs, list) { +- irq = bcmasp_get_and_request_irq(priv, intf->port + 1); +- if (irq < 0) { +- dev_warn(dev, "Failed to init WoL irq(port %d): %d\n", +- intf->port, irq); +- continue; +- } +- +- intf->wol_irq = irq; +- intf->wol_irq_enabled = false; +- device_set_wakeup_capable(&pdev->dev, 1); +- } +-} +- +-static void bcmasp_enable_wol_per_intf(struct bcmasp_intf *intf, bool en) +-{ +- struct device *dev = &intf->parent->pdev->dev; +- +- if (en ^ intf->wol_irq_enabled) +- irq_set_irq_wake(intf->wol_irq, en); +- +- intf->wol_irq_enabled = en; +- device_set_wakeup_enable(dev, en); +-} +- +-static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv) +-{ +- struct bcmasp_intf *intf; +- +- list_for_each_entry(intf, &priv->intfs, list) { +- if (intf->wol_irq > 0) +- free_irq(intf->wol_irq, priv); +- } +-} +- + static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + { + u32 reg, phy_lpi_overwrite; +@@ -1220,60 +1178,22 @@ static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + usleep_range(50, 100); + } + +-static struct bcmasp_hw_info v20_hw_info = { +- .rx_ctrl_flush = ASP_RX_CTRL_FLUSH, +- .umac2fb = UMAC2FB_OFFSET, +- .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT, +- .rx_ctrl_fb_filt_out_frame_count = ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT, +- .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH, +-}; +- +-static const struct bcmasp_plat_data v20_plat_data = { +- .init_wol = bcmasp_init_wol_per_intf, +- .enable_wol = bcmasp_enable_wol_per_intf, +- .destroy_wol = bcmasp_wol_irq_destroy_per_intf, +- .core_clock_select = bcmasp_core_clock_select_one, +- .hw_info = &v20_hw_info, +-}; +- +-static struct bcmasp_hw_info v21_hw_info = { +- .rx_ctrl_flush = ASP_RX_CTRL_FLUSH_2_1, +- .umac2fb = UMAC2FB_OFFSET_2_1, +- .rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1, +- .rx_ctrl_fb_filt_out_frame_count = +- ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1, +- .rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1, +-}; +- + static const struct bcmasp_plat_data v21_plat_data = { +- .init_wol = bcmasp_init_wol_shared, +- .enable_wol = bcmasp_enable_wol_shared, +- .destroy_wol = bcmasp_wol_irq_destroy_shared, + .core_clock_select = bcmasp_core_clock_select_one, +- .hw_info = &v21_hw_info, + }; + + static const struct bcmasp_plat_data v22_plat_data = { +- .init_wol = bcmasp_init_wol_shared, +- .enable_wol = bcmasp_enable_wol_shared, +- .destroy_wol = bcmasp_wol_irq_destroy_shared, + .core_clock_select = bcmasp_core_clock_select_many, +- .hw_info = &v21_hw_info, + .eee_fixup = bcmasp_eee_fixup, + }; + + static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata) + { +- priv->init_wol = pdata->init_wol; +- priv->enable_wol = pdata->enable_wol; +- priv->destroy_wol = pdata->destroy_wol; + priv->core_clock_select = pdata->core_clock_select; + priv->eee_fixup = pdata->eee_fixup; +- priv->hw_info = pdata->hw_info; + } + + static const struct of_device_id bcmasp_of_match[] = { +- { .compatible = "brcm,asp-v2.0", .data = &v20_plat_data }, + { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data }, + { .compatible = "brcm,asp-v2.2", .data = &v22_plat_data }, + { /* sentinel */ }, +@@ -1281,9 +1201,8 @@ static const struct of_device_id bcmasp_of_match[] = { + MODULE_DEVICE_TABLE(of, bcmasp_of_match); + + static const struct of_device_id bcmasp_mdio_of_match[] = { +- { .compatible = "brcm,asp-v2.2-mdio", }, + { .compatible = "brcm,asp-v2.1-mdio", }, +- { .compatible = "brcm,asp-v2.0-mdio", }, ++ { .compatible = "brcm,asp-v2.2-mdio", }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, bcmasp_mdio_of_match); +@@ -1387,7 +1306,7 @@ static int bcmasp_probe(struct platform_device *pdev) + } + + /* Check and enable WoL */ +- priv->init_wol(priv); ++ bcmasp_init_wol(priv); + + /* Drop the clock reference count now and let ndo_open()/ndo_close() + * manage it for us from now on. +@@ -1404,7 +1323,7 @@ static int bcmasp_probe(struct platform_device *pdev) + if (ret) { + netdev_err(intf->ndev, + "failed to register net_device: %d\n", ret); +- priv->destroy_wol(priv); ++ bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + goto of_put_exit; + } +@@ -1425,7 +1344,7 @@ static void bcmasp_remove(struct platform_device *pdev) + if (!priv) + return; + +- priv->destroy_wol(priv); ++ bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + } + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.h b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +index 8fc75bcedb70f..6f49ebad4e99c 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.h ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.h +@@ -53,22 +53,15 @@ + #define ASP_RX_CTRL_FB_0_FRAME_COUNT 0x14 + #define ASP_RX_CTRL_FB_1_FRAME_COUNT 0x18 + #define ASP_RX_CTRL_FB_8_FRAME_COUNT 0x1c +-/* asp2.1 diverges offsets here */ +-/* ASP2.0 */ +-#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT 0x20 +-#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT 0x24 +-#define ASP_RX_CTRL_FLUSH 0x28 +-#define ASP_CTRL_UMAC0_FLUSH_MASK (BIT(0) | BIT(12)) +-#define ASP_CTRL_UMAC1_FLUSH_MASK (BIT(1) | BIT(13)) +-#define ASP_CTRL_SPB_FLUSH_MASK (BIT(8) | BIT(20)) +-#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH 0x30 +-/* ASP2.1 */ +-#define ASP_RX_CTRL_FB_9_FRAME_COUNT_2_1 0x20 +-#define ASP_RX_CTRL_FB_10_FRAME_COUNT_2_1 0x24 +-#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1 0x28 +-#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1 0x2c +-#define ASP_RX_CTRL_FLUSH_2_1 0x30 +-#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1 0x38 ++#define ASP_RX_CTRL_FB_9_FRAME_COUNT 0x20 ++#define ASP_RX_CTRL_FB_10_FRAME_COUNT 0x24 ++#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT 0x28 ++#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT 0x2c ++#define ASP_RX_CTRL_FLUSH 0x30 ++#define ASP_CTRL_UMAC0_FLUSH_MASK (BIT(0) | BIT(12)) ++#define ASP_CTRL_UMAC1_FLUSH_MASK (BIT(1) | BIT(13)) ++#define ASP_CTRL_SPB_FLUSH_MASK (BIT(8) | BIT(20)) ++#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH 0x38 + + #define ASP_RX_FILTER_OFFSET 0x80000 + #define ASP_RX_FILTER_BLK_CTRL 0x0 +@@ -345,9 +338,6 @@ struct bcmasp_intf { + + u32 wolopts; + u8 sopass[SOPASS_MAX]; +- /* Used if per intf wol irq */ +- int wol_irq; +- unsigned int wol_irq_enabled:1; + }; + + #define NUM_NET_FILTERS 32 +@@ -370,21 +360,9 @@ struct bcmasp_mda_filter { + u8 mask[ETH_ALEN]; + }; + +-struct bcmasp_hw_info { +- u32 rx_ctrl_flush; +- u32 umac2fb; +- u32 rx_ctrl_fb_out_frame_count; +- u32 rx_ctrl_fb_filt_out_frame_count; +- u32 rx_ctrl_fb_rx_fifo_depth; +-}; +- + struct bcmasp_plat_data { +- void (*init_wol)(struct bcmasp_priv *priv); +- void (*enable_wol)(struct bcmasp_intf *intf, bool en); +- void (*destroy_wol)(struct bcmasp_priv *priv); + void (*core_clock_select)(struct bcmasp_priv *priv, bool slow); + void (*eee_fixup)(struct bcmasp_intf *priv, bool en); +- struct bcmasp_hw_info *hw_info; + }; + + struct bcmasp_priv { +@@ -399,14 +377,10 @@ struct bcmasp_priv { + int wol_irq; + unsigned long wol_irq_enabled_mask; + +- void (*init_wol)(struct bcmasp_priv *priv); +- void (*enable_wol)(struct bcmasp_intf *intf, bool en); +- void (*destroy_wol)(struct bcmasp_priv *priv); + void (*core_clock_select)(struct bcmasp_priv *priv, bool slow); + void (*eee_fixup)(struct bcmasp_intf *intf, bool en); + + void __iomem *base; +- struct bcmasp_hw_info *hw_info; + + struct list_head intfs; + +@@ -599,4 +573,5 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs, + + void bcmasp_netfilt_suspend(struct bcmasp_intf *intf); + ++void bcmasp_enable_wol(struct bcmasp_intf *intf, bool en); + #endif +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +index c24107baefcfd..6d537fe461cc9 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c +@@ -71,23 +71,6 @@ static const struct bcmasp_stats bcmasp_gstrings_stats[] = { + + #define BCMASP_STATS_LEN ARRAY_SIZE(bcmasp_gstrings_stats) + +-static u16 bcmasp_stat_fixup_offset(struct bcmasp_intf *intf, +- const struct bcmasp_stats *s) +-{ +- struct bcmasp_priv *priv = intf->parent; +- +- if (!strcmp("Frames Out(Buffer)", s->stat_string)) +- return priv->hw_info->rx_ctrl_fb_out_frame_count; +- +- if (!strcmp("Frames Out(Filters)", s->stat_string)) +- return priv->hw_info->rx_ctrl_fb_filt_out_frame_count; +- +- if (!strcmp("RX Buffer FIFO Depth", s->stat_string)) +- return priv->hw_info->rx_ctrl_fb_rx_fifo_depth; +- +- return s->reg_offset; +-} +- + static int bcmasp_get_sset_count(struct net_device *dev, int string_set) + { + switch (string_set) { +@@ -126,7 +109,7 @@ static void bcmasp_update_mib_counters(struct bcmasp_intf *intf) + char *p; + + s = &bcmasp_gstrings_stats[i]; +- offset = bcmasp_stat_fixup_offset(intf, s); ++ offset = s->reg_offset; + switch (s->type) { + case BCMASP_STAT_SOFT: + continue; +@@ -215,7 +198,7 @@ static int bcmasp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + memcpy(intf->sopass, wol->sopass, sizeof(wol->sopass)); + + mutex_lock(&priv->wol_lock); +- priv->enable_wol(intf, !!intf->wolopts); ++ bcmasp_enable_wol(intf, !!intf->wolopts); + mutex_unlock(&priv->wol_lock); + + return 0; +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +index acf45789d4493..3836456fcb9cf 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +@@ -1182,7 +1182,7 @@ static void bcmasp_map_res(struct bcmasp_priv *priv, struct bcmasp_intf *intf) + { + /* Per port */ + intf->res.umac = priv->base + UMC_OFFSET(intf); +- intf->res.umac2fb = priv->base + (priv->hw_info->umac2fb + ++ intf->res.umac2fb = priv->base + (UMAC2FB_OFFSET + + (intf->port * 0x4)); + intf->res.rgmii = priv->base + RGMII_OFFSET(intf); + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h +index ad742612895fc..af7418348e815 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h +@@ -118,8 +118,7 @@ + #define UMC_PSW_MS 0x624 + #define UMC_PSW_LS 0x628 + +-#define UMAC2FB_OFFSET_2_1 0x9f044 +-#define UMAC2FB_OFFSET 0x9f03c ++#define UMAC2FB_OFFSET 0x9f044 + #define UMAC2FB_CFG 0x0 + #define UMAC2FB_CFG_OPUT_EN BIT(0) + #define UMAC2FB_CFG_VLAN_EN BIT(1) +-- +2.51.0 + diff --git a/queue-6.12/net-bcmasp-streamline-early-exit-in-probe.patch b/queue-6.12/net-bcmasp-streamline-early-exit-in-probe.patch new file mode 100644 index 0000000000..cfc2313750 --- /dev/null +++ b/queue-6.12/net-bcmasp-streamline-early-exit-in-probe.patch @@ -0,0 +1,88 @@ +From ac38eb7663d46dd4c1ceb508e3a884ffa528a409 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Jan 2026 11:49:49 -0800 +Subject: net: bcmasp: streamline early exit in probe + +From: Justin Chen + +[ Upstream commit 1fd1281250c38408d793863c8dcaa43c7de8932c ] + +Streamline the bcmasp_probe early exit. As support for other +functionality is added(i.e. ptp), it is easier to keep track of early +exit cleanup when it is all in one place. + +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260122194949.1145107-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 27 +++++++++++---------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 57932e5c54e01..1e73595096c13 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1286,6 +1286,8 @@ static int bcmasp_probe(struct platform_device *pdev) + bcmasp_core_init(priv); + bcmasp_core_init_filters(priv); + ++ bcmasp_init_wol(priv); ++ + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +@@ -1297,16 +1299,14 @@ static int bcmasp_probe(struct platform_device *pdev) + intf = bcmasp_interface_create(priv, intf_node, i); + if (!intf) { + dev_err(dev, "Cannot create eth interface %d\n", i); +- bcmasp_remove_intfs(priv); +- ret = -ENOMEM; +- goto of_put_exit; ++ of_node_put(ports_node); ++ ret = -EINVAL; ++ goto err_cleanup; + } + list_add_tail(&intf->list, &priv->intfs); + i++; + } +- +- /* Check and enable WoL */ +- bcmasp_init_wol(priv); ++ of_node_put(ports_node); + + /* Drop the clock reference count now and let ndo_open()/ndo_close() + * manage it for us from now on. +@@ -1321,19 +1321,20 @@ static int bcmasp_probe(struct platform_device *pdev) + list_for_each_entry(intf, &priv->intfs, list) { + ret = register_netdev(intf->ndev); + if (ret) { +- netdev_err(intf->ndev, +- "failed to register net_device: %d\n", ret); +- bcmasp_wol_irq_destroy(priv); +- bcmasp_remove_intfs(priv); +- goto of_put_exit; ++ dev_err(dev, "failed to register net_device: %d\n", ret); ++ goto err_cleanup; + } + count++; + } + + dev_info(dev, "Initialized %d port(s)\n", count); + +-of_put_exit: +- of_node_put(ports_node); ++ return ret; ++ ++err_cleanup: ++ bcmasp_wol_irq_destroy(priv); ++ bcmasp_remove_intfs(priv); ++ + return ret; + } + +-- +2.51.0 + diff --git a/queue-6.12/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-6.12/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..c88a6fcf57 --- /dev/null +++ b/queue-6.12/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From b5408220f7095e05e7582078bddf559203ce92e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index 6a24324703bf4..7ec6e4a54b8ec 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -750,6 +750,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-6.12/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-6.12/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..78dbfd47be --- /dev/null +++ b/queue-6.12/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From 7cdd0212d62954679c33b3002dab5c17ccfe3458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index e8589fede4d4c..10de44530362c 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3189,6 +3189,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-6.12/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch b/queue-6.12/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch new file mode 100644 index 0000000000..a84afe47c1 --- /dev/null +++ b/queue-6.12/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch @@ -0,0 +1,49 @@ +From f3ce17a33e1cf69d95ddedca987aa1161852bfb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 12:23:45 +0530 +Subject: net: lan743x: fix duplex configuration in mac_link_up + +From: Thangaraj Samynathan + +[ Upstream commit 71399707876b93240f236f48b8062f3423a5fe97 ] + +The driver does not explicitly configure the MAC duplex mode when +bringing the link up. As a result, the MAC may retain a stale duplex +setting from a previous link state, leading to duplex mismatches with +the link partner and degraded network performance. + +Update lan743x_phylink_mac_link_up() to set or clear the MAC_CR_DPX_ +bit according to the negotiated duplex mode. + +This ensures the MAC configuration is consistent with the phylink +resolved state. + +Fixes: a5f199a8d8a03 ("net: lan743x: Migrate phylib to phylink") +Signed-off-by: Thangaraj Samynathan +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/20260323065345.144915-1-thangaraj.s@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index 8c4c28a1d6575..b897d071fc452 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -3055,6 +3055,11 @@ static void lan743x_phylink_mac_link_up(struct phylink_config *config, + else if (speed == SPEED_100) + mac_cr |= MAC_CR_CFG_L_; + ++ if (duplex == DUPLEX_FULL) ++ mac_cr |= MAC_CR_DPX_; ++ else ++ mac_cr &= ~MAC_CR_DPX_; ++ + lan743x_csr_write(adapter, MAC_CR, mac_cr); + + lan743x_ptp_update_latency(adapter, speed); +-- +2.51.0 + diff --git a/queue-6.12/net-macb-use-the-current-queue-number-for-stats.patch b/queue-6.12/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..a7c7c97db7 --- /dev/null +++ b/queue-6.12/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From 34359d72f2bb5e419de350bc699ba34703f1e9f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 89aa50893d360..3fed07b452cc1 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3255,7 +3255,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-6.12/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-6.12/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..f8ade44cba --- /dev/null +++ b/queue-6.12/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From c5a720a346ec40220a89eb7d91fb177a752ee117 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 6574f9bcdc026..c688dee96503f 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -151,11 +151,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -174,6 +178,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-6.12/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-6.12/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..9c643447d0 --- /dev/null +++ b/queue-6.12/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From 57e0c4476f3bbc0f8e4de52df7a3116b51d11298 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index 79047721df511..e7a6c2602e786 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -135,9 +135,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-6.12/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-6.12/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..ae603b2530 --- /dev/null +++ b/queue-6.12/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 60bd68f13eb952ac39b6f2b3d35736464d4f5a62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 627790fcb6bb0..3fe37bdd625eb 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -885,8 +885,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -900,17 +900,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2628,7 +2622,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 0c1d086e96cb3..b67426c2189b2 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1385,9 +1385,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1414,10 +1414,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-6.12/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-6.12/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..c6862ad257 --- /dev/null +++ b/queue-6.12/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From 05b4dc82a9828abdcafd653a58d33a798bd6cb31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-6.12/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..a7fca32a19 --- /dev/null +++ b/queue-6.12/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From ad7b854c6a24642a9ca6b3e75492f90d5aed51a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 21fa550966f07..afbf3c5100f76 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-6.12/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..7a51e1e71b --- /dev/null +++ b/queue-6.12/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From 8e6cf26c9bf6c94a006d7cd593be681006ef2582 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 657839a58782a..84334537c6067 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-6.12/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-6.12/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..4119f2e743 --- /dev/null +++ b/queue-6.12/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From 521af857954ac7ab162120a2271bee0731037d6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 134e05d31061e..aa5fc9bffef0c 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -647,15 +647,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-6.12/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-6.12/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..0a2b887f20 --- /dev/null +++ b/queue-6.12/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From bb4db1e3a92a075153091af7c35f83434fb474c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 18ff1c23769ae..d10e2c81131ad 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -575,8 +575,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -588,13 +587,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); +@@ -604,6 +603,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.12/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch b/queue-6.12/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch new file mode 100644 index 0000000000..80cb8fb439 --- /dev/null +++ b/queue-6.12/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch @@ -0,0 +1,50 @@ +From 499e418b756301527be669f156968007031f5880 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 07:42:41 +0000 +Subject: openvswitch: defer tunnel netdev_put to RCU release + +From: Yang Yang + +[ Upstream commit 6931d21f87bc6d657f145798fad0bf077b82486c ] + +ovs_netdev_tunnel_destroy() may run after NETDEV_UNREGISTER already +detached the device. Dropping the netdev reference in destroy can race +with concurrent readers that still observe vport->dev. + +Do not release vport->dev in ovs_netdev_tunnel_destroy(). Instead, let +vport_netdev_free() drop the reference from the RCU callback, matching +the non-tunnel destroy path and avoiding additional synchronization +under RTNL. + +Fixes: a9020fde67a6 ("openvswitch: Move tunnel destroy function to oppenvswitch module.") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319074241.3405262-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index c688dee96503f..12055af832dc0 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -196,8 +196,6 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + */ + if (vport->dev->reg_state == NETREG_REGISTERED) + rtnl_delete_link(vport->dev, 0, NULL); +- netdev_put(vport->dev, &vport->dev_tracker); +- vport->dev = NULL; + rtnl_unlock(); + + call_rcu(&vport->rcu, vport_netdev_free); +-- +2.51.0 + diff --git a/queue-6.12/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-6.12/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..7c6512946f --- /dev/null +++ b/queue-6.12/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From 8b6aa1e55bb1f8509b4c66718ce8defb6d0fe9df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 7d5490ea23e1d..3d2dbe963813d 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2953,6 +2953,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-6.12/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-6.12/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..9ae51cc2dd --- /dev/null +++ b/queue-6.12/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From b52f93f607d4b5fb05700d886aba8e0ee0e35beb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index 91edb539925a4..e5d6dc6b0069f 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1124,9 +1124,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-6.12/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-6.12/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..ac11345455 --- /dev/null +++ b/queue-6.12/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From a0bc011e8f1b32e220e1b8cde651a4e41b4e898f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index fa7b3bda688a6..bee271a4fda1a 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-6.12/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch b/queue-6.12/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch new file mode 100644 index 0000000000..f17f9fa53d --- /dev/null +++ b/queue-6.12/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch @@ -0,0 +1,62 @@ +From 882f5d721b82060dfbfccc03c73269d3b5c944bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Feb 2026 19:16:24 -0400 +Subject: platform/x86: intel-hid: disable wakeup_mode during hibernation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David McFarland + +[ Upstream commit e02ea3ae8ee40d5835a845884c7b161a27c10bcb ] + +Add a freeze handler which clears wakeup_mode. This fixes aborted hibernation on +Dell Precision 3880. + + Wakeup event detected during hibernation, rolling back + +This system sends power button events during hibernation, even when triggered by +software. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218634 +Fixes: 0c4cae1bc00d ("PM: hibernate: Avoid missing wakeup events during hibernation") +Signed-off-by: David McFarland +Link: https://patch.msgid.link/20260205231629.1336348-1-corngood@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/hid.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index a51b65280bc40..0e81904548f36 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -423,6 +423,14 @@ static int intel_hid_pl_suspend_handler(struct device *device) + return 0; + } + ++static int intel_hid_pl_freeze_handler(struct device *device) ++{ ++ struct intel_hid_priv *priv = dev_get_drvdata(device); ++ ++ priv->wakeup_mode = false; ++ return intel_hid_pl_suspend_handler(device); ++} ++ + static int intel_hid_pl_resume_handler(struct device *device) + { + intel_hid_pm_complete(device); +@@ -437,7 +445,7 @@ static int intel_hid_pl_resume_handler(struct device *device) + static const struct dev_pm_ops intel_hid_pl_pm_ops = { + .prepare = intel_hid_pm_prepare, + .complete = intel_hid_pm_complete, +- .freeze = intel_hid_pl_suspend_handler, ++ .freeze = intel_hid_pl_freeze_handler, + .thaw = intel_hid_pl_resume_handler, + .restore = intel_hid_pl_resume_handler, + .suspend = intel_hid_pl_suspend_handler, +-- +2.51.0 + diff --git a/queue-6.12/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-6.12/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..3da849d6a0 --- /dev/null +++ b/queue-6.12/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From e0137c09f96dcf63661cda4150e3d124b2751b00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 650c3c20e79ff..24722671cbed9 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -557,11 +557,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-6.12/series b/queue-6.12/series index 252f801e62..3defca1f83 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -44,3 +44,61 @@ usb-core-new-quirk-to-handle-devices-with-zero-confi.patch spi-intel-pci-add-support-for-nova-lake-mobile-spi-f.patch alsa-hda-realtek-add-quirk-for-asus-um6702rc.patch i3c-master-dw-i3c-fix-missing-of_node-for-virtual-i2.patch +xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch +xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +xfrm-fix-the-usage-of-skb-sk.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch +xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch +af_key-validate-families-in-pfkey_send_migrate.patch +dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch +erofs-set-fileio-bio-failed-in-short-read-case.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +net-bcm-asp2-fix-lpi-timer-handling.patch +net-bcm-asp2-remove-tx_lpi_enabled.patch +net-bcm-asp2-convert-to-phylib-managed-eee.patch +net-bcmasp-remove-support-for-asp-v2.0.patch +net-bcmasp-streamline-early-exit-in-probe.patch +net-bcmasp-fix-double-free-of-wol-irq.patch +net-bcmasp-add-support-for-asp-v3.0.patch +net-bcmasp-fix-double-disable-of-clk.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch +ice-fix-inverted-ready-check-for-vf-representors.patch +ice-use-ice_update_eth_stats-for-representor-stats.patch +iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch +ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch +ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +tcp-optimize-inet_use_bhash2_on_bind.patch +udp-fix-wildcard-bind-conflict-check-when-using-hash.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +team-fix-header_ops-type-confusion-with-non-ethernet.patch +net-lan743x-fix-duplex-configuration-in-mac_link_up.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch +bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +tls-purge-async_hold-in-tls_decrypt_async_wait.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-6.12/tcp-optimize-inet_use_bhash2_on_bind.patch b/queue-6.12/tcp-optimize-inet_use_bhash2_on_bind.patch new file mode 100644 index 0000000000..903d9d4c8b --- /dev/null +++ b/queue-6.12/tcp-optimize-inet_use_bhash2_on_bind.patch @@ -0,0 +1,46 @@ +From 49c4c1de78b44a3d81e899f9cc2f7b6d2f57d290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 12:42:35 +0000 +Subject: tcp: optimize inet_use_bhash2_on_bind() + +From: Eric Dumazet + +[ Upstream commit ca79d80b0b9f42362a893f06413a9fe91811158a ] + +There is no reason to call ipv6_addr_type(). + +Instead, use highly optimized ipv6_addr_any() and ipv6_addr_v4mapped(). + +Signed-off-by: Eric Dumazet +Reviewed-by: Jason Xing +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250302124237.3913746-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index fe7947f774062..72049d04a2b7d 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -157,12 +157,10 @@ static bool inet_use_bhash2_on_bind(const struct sock *sk) + { + #if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { +- int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); +- +- if (addr_type == IPV6_ADDR_ANY) ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + return false; + +- if (addr_type != IPV6_ADDR_MAPPED) ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) + return true; + } + #endif +-- +2.51.0 + diff --git a/queue-6.12/team-fix-header_ops-type-confusion-with-non-ethernet.patch b/queue-6.12/team-fix-header_ops-type-confusion-with-non-ethernet.patch new file mode 100644 index 0000000000..9d242f1c49 --- /dev/null +++ b/queue-6.12/team-fix-header_ops-type-confusion-with-non-ethernet.patch @@ -0,0 +1,132 @@ +From b7cb112d6bff571388354096965652eaf886c25f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 15:21:26 +0800 +Subject: team: fix header_ops type confusion with non-Ethernet ports + +From: Jiayuan Chen + +[ Upstream commit 425000dbf17373a4ab8be9428f5dc055ef870a56 ] + +Similar to commit 950803f72547 ("bonding: fix type confusion in +bond_setup_by_slave()") team has the same class of header_ops type +confusion. + +For non-Ethernet ports, team_setup_by_port() copies port_dev->header_ops +directly. When the team device later calls dev_hard_header() or +dev_parse_header(), these callbacks can run with the team net_device +instead of the real lower device, so netdev_priv(dev) is interpreted as +the wrong private type and can crash. + +The syzbot report shows a crash in bond_header_create(), but the root +cause is in team: the topology is gre -> bond -> team, and team calls +the inherited header_ops with its own net_device instead of the lower +device, so bond_header_create() receives a team device and interprets +netdev_priv() as bonding private data, causing a type confusion crash. + +Fix this by introducing team header_ops wrappers for create/parse, +selecting a team port under RCU, and calling the lower device callbacks +with port->dev, so each callback always sees the correct net_device +context. + +Also pass the selected lower device to the lower parse callback, so +recursion is bounded in stacked non-Ethernet topologies and parse +callbacks always run with the correct device context. + +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Reported-by: syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69b46af7.050a0220.36eb34.000e.GAE@google.com/T/ +Cc: Jiayuan Chen +Signed-off-by: Jiayuan Chen +Link: https://patch.msgid.link/20260320072139.134249-2-jiayuan.chen@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/team/team_core.c | 65 +++++++++++++++++++++++++++++++++++- + 1 file changed, 64 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c +index 50732f9699eea..3cbaee3ff5fd7 100644 +--- a/drivers/net/team/team_core.c ++++ b/drivers/net/team/team_core.c +@@ -2133,6 +2133,68 @@ static const struct ethtool_ops team_ethtool_ops = { + * rt netlink interface + ***********************/ + ++/* For tx path we need a linkup && enabled port and for parse any port ++ * suffices. ++ */ ++static struct team_port *team_header_port_get_rcu(struct team *team, ++ bool txable) ++{ ++ struct team_port *port; ++ ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ if (!txable || team_port_txable(port)) ++ return port; ++ } ++ ++ return NULL; ++} ++ ++static int team_header_create(struct sk_buff *skb, struct net_device *team_dev, ++ unsigned short type, const void *daddr, ++ const void *saddr, unsigned int len) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, true); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->create) ++ ret = port_ops->create(skb, port->dev, ++ type, daddr, saddr, len); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static int team_header_parse(const struct sk_buff *skb, ++ const struct net_device *team_dev, ++ unsigned char *haddr) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, false); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->parse) ++ ret = port_ops->parse(skb, port->dev, haddr); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static const struct header_ops team_header_ops = { ++ .create = team_header_create, ++ .parse = team_header_parse, ++}; ++ + static void team_setup_by_port(struct net_device *dev, + struct net_device *port_dev) + { +@@ -2141,7 +2203,8 @@ static void team_setup_by_port(struct net_device *dev, + if (port_dev->type == ARPHRD_ETHER) + dev->header_ops = team->header_ops_cache; + else +- dev->header_ops = port_dev->header_ops; ++ dev->header_ops = port_dev->header_ops ? ++ &team_header_ops : NULL; + dev->type = port_dev->type; + dev->hard_header_len = port_dev->hard_header_len; + dev->needed_headroom = port_dev->needed_headroom; +-- +2.51.0 + diff --git a/queue-6.12/tls-purge-async_hold-in-tls_decrypt_async_wait.patch b/queue-6.12/tls-purge-async_hold-in-tls_decrypt_async_wait.patch new file mode 100644 index 0000000000..6a52ea253e --- /dev/null +++ b/queue-6.12/tls-purge-async_hold-in-tls_decrypt_async_wait.patch @@ -0,0 +1,66 @@ +From 62ffe5a9aca02d0c79d2ef4f6891a43f380543ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 08:53:23 -0400 +Subject: tls: Purge async_hold in tls_decrypt_async_wait() + +From: Chuck Lever + +[ Upstream commit 84a8335d8300576f1b377ae24abca1d9f197807f ] + +The async_hold queue pins encrypted input skbs while +the AEAD engine references their scatterlist data. Once +tls_decrypt_async_wait() returns, every AEAD operation +has completed and the engine no longer references those +skbs, so they can be freed unconditionally. + +A subsequent patch adds batch async decryption to +tls_sw_read_sock(), introducing a new call site that +must drain pending AEAD operations and release held +skbs. Move __skb_queue_purge(&ctx->async_hold) into +tls_decrypt_async_wait() so the purge is centralized +and every caller -- recvmsg's drain path, the -EBUSY +fallback in tls_do_decryption(), and the new read_sock +batch path -- releases held skbs on synchronization +without each site managing the purge independently. + +This fixes a leak when tls_strp_msg_hold() fails part-way through, +after having added some cloned skbs to the async_hold +queue. tls_decrypt_sg() will then call tls_decrypt_async_wait() to +process all pending decrypts, and drop back to synchronous mode, but +tls_sw_recvmsg() only flushes the async_hold queue when one record has +been processed in "fully-async" mode, which may not be the case here. + +Signed-off-by: Chuck Lever +Reported-by: Yiming Qian +Fixes: b8a6ff84abbc ("tls: wait for pending async decryptions if tls_strp_msg_hold fails") +Link: https://patch.msgid.link/20260324-tls-read-sock-v5-1-5408befe5774@oracle.com +[pabeni@redhat.com: added leak comment] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_sw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index bf01155b1011a..e12aa76d1aa71 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -246,6 +246,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + atomic_inc(&ctx->decrypt_pending); + ++ __skb_queue_purge(&ctx->async_hold); + return ctx->async_wait.err; + } + +@@ -2191,7 +2192,6 @@ int tls_sw_recvmsg(struct sock *sk, + + /* Wait for all previously submitted records to be decrypted */ + ret = tls_decrypt_async_wait(ctx); +- __skb_queue_purge(&ctx->async_hold); + + if (ret) { + if (err >= 0 || err == -EINPROGRESS) +-- +2.51.0 + diff --git a/queue-6.12/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch b/queue-6.12/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch new file mode 100644 index 0000000000..340175f563 --- /dev/null +++ b/queue-6.12/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch @@ -0,0 +1,160 @@ +From 07f3eb664cb42e135c56c53d56d34d36154d804c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 11:18:17 -0700 +Subject: udp: Fix wildcard bind conflict check when using hash2 + +From: Martin KaFai Lau + +[ Upstream commit e537dd15d0d4ad989d56a1021290f0c674dd8b28 ] + +When binding a udp_sock to a local address and port, UDP uses +two hashes (udptable->hash and udptable->hash2) for collision +detection. The current code switches to "hash2" when +hslot->count > 10. + +"hash2" is keyed by local address and local port. +"hash" is keyed by local port only. + +The issue can be shown in the following bind sequence (pseudo code): + +bind(fd1, "[fd00::1]:8888") +bind(fd2, "[fd00::2]:8888") +bind(fd3, "[fd00::3]:8888") +bind(fd4, "[fd00::4]:8888") +bind(fd5, "[fd00::5]:8888") +bind(fd6, "[fd00::6]:8888") +bind(fd7, "[fd00::7]:8888") +bind(fd8, "[fd00::8]:8888") +bind(fd9, "[fd00::9]:8888") +bind(fd10, "[fd00::10]:8888") + +/* Correctly return -EADDRINUSE because "hash" is used + * instead of "hash2". udp_lib_lport_inuse() detects the + * conflict. + */ +bind(fail_fd, "[::]:8888") + +/* After one more socket is bound to "[fd00::11]:8888", + * hslot->count exceeds 10 and "hash2" is used instead. + */ +bind(fd11, "[fd00::11]:8888") +bind(fail_fd, "[::]:8888") /* succeeds unexpectedly */ + +The same issue applies to the IPv4 wildcard address "0.0.0.0" +and the IPv4-mapped wildcard address "::ffff:0.0.0.0". For +example, if there are existing sockets bound to +"192.168.1.[1-11]:8888", then binding "0.0.0.0:8888" or +"[::ffff:0.0.0.0]:8888" can also miss the conflict when +hslot->count > 10. + +TCP inet_csk_get_port() already has the correct check in +inet_use_bhash2_on_bind(). Rename it to +inet_use_hash2_on_bind() and move it to inet_hashtables.h +so udp.c can reuse it in this fix. + +Fixes: 30fff9231fad ("udp: bind() optimisation") +Reported-by: Andrew Onyshchuk +Signed-off-by: Martin KaFai Lau +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260319181817.1901357-1-martin.lau@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_hashtables.h | 14 ++++++++++++++ + net/ipv4/inet_connection_sock.c | 20 +++----------------- + net/ipv4/udp.c | 2 +- + 3 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 3c4118c63cfe1..b111812548663 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -273,6 +273,20 @@ inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk, + return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)]; + } + ++static inline bool inet_use_hash2_on_bind(const struct sock *sk) ++{ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) { ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ return false; ++ ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ return true; ++ } ++#endif ++ return sk->sk_rcv_saddr != htonl(INADDR_ANY); ++} ++ + struct inet_bind_hashbucket * + inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port); + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 72049d04a2b7d..2691d69f33502 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -153,20 +153,6 @@ bool inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) + } + EXPORT_SYMBOL(inet_sk_get_local_port_range); + +-static bool inet_use_bhash2_on_bind(const struct sock *sk) +-{ +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) { +- if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) +- return false; +- +- if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) +- return true; +- } +-#endif +- return sk->sk_rcv_saddr != htonl(INADDR_ANY); +-} +- + static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, + kuid_t sk_uid, bool relax, + bool reuseport_cb_ok, bool reuseport_ok) +@@ -258,7 +244,7 @@ static int inet_csk_bind_conflict(const struct sock *sk, + * checks separately because their spinlocks have to be acquired/released + * independently of each other, to prevent possible deadlocks + */ +- if (inet_use_bhash2_on_bind(sk)) ++ if (inet_use_hash2_on_bind(sk)) + return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, + reuseport_cb_ok, reuseport_ok); + +@@ -375,7 +361,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); +- if (inet_use_bhash2_on_bind(sk)) { ++ if (inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false)) + goto next_port; + } +@@ -560,7 +546,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + check_bind_conflict = false; + } + +- if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) { ++ if (check_bind_conflict && inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true)) + goto fail_unlock; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index f4e24fc878fab..d1090a1f860cc 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -288,7 +288,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + } else { + hslot = udp_hashslot(udptable, net, snum); + spin_lock_bh(&hslot->lock); +- if (hslot->count > 10) { ++ if (inet_use_hash2_on_bind(sk) && hslot->count > 10) { + int exist; + unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; + +-- +2.51.0 + diff --git a/queue-6.12/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch b/queue-6.12/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch new file mode 100644 index 0000000000..d0cc01ecfd --- /dev/null +++ b/queue-6.12/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch @@ -0,0 +1,49 @@ +From b28c54924b90baf4529a763527c511f791b14ac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:11 +0100 +Subject: xfrm: add missing extack for XFRMA_SA_PCPU in add_acquire and + allocspi + +From: Sabrina Dubroca + +[ Upstream commit aa8a3f3c67235422a0c3608a8772f69ca3b7b63f ] + +We're returning an error caused by invalid user input without setting +an extack. Add one. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 1a4d2fac08594..7d03a6e486b34 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1785,6 +1785,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + if (pcpu_num >= num_possible_cpus()) { + err = -EINVAL; ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto out_noput; + } + } +@@ -2934,8 +2935,10 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + if (attrs[XFRMA_SA_PCPU]) { + x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + err = -EINVAL; +- if (x->pcpu_num >= num_possible_cpus()) ++ if (x->pcpu_num >= num_possible_cpus()) { ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto free_state; ++ } + } + + err = verify_newpolicy_info(&ua->policy, extack); +-- +2.51.0 + diff --git a/queue-6.12/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-6.12/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..4b7223a161 --- /dev/null +++ b/queue-6.12/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From cf6cd477f96c95936f4c8386c6b0ed933c6e79d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index c927560a77316..a55c88b43c339 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2180,6 +2180,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-6.12/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch b/queue-6.12/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch new file mode 100644 index 0000000000..9e0b9dc0ef --- /dev/null +++ b/queue-6.12/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch @@ -0,0 +1,38 @@ +From 6f035dcb9a3b48d230e0c163c9898d2d9383a3d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:12 +0100 +Subject: xfrm: fix the condition on x->pcpu_num in xfrm_sa_len + +From: Sabrina Dubroca + +[ Upstream commit b57defcf8f109da5ba9cf59b2a736606faf3d846 ] + +pcpu_num = 0 is a valid value. The marker for "unset pcpu_num" which +makes copy_to_user_state_extra not add the XFRMA_SA_PCPU attribute is +UINT_MAX. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 7d03a6e486b34..419def2cd1280 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -3577,7 +3577,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) + } + if (x->if_id) + l += nla_total_size(sizeof(x->if_id)); +- if (x->pcpu_num) ++ if (x->pcpu_num != UINT_MAX) + l += nla_total_size(sizeof(x->pcpu_num)); + + /* Must count x->lastused as it may become non-zero behind our back. */ +-- +2.51.0 + diff --git a/queue-6.12/xfrm-fix-the-usage-of-skb-sk.patch b/queue-6.12/xfrm-fix-the-usage-of-skb-sk.patch new file mode 100644 index 0000000000..6300ed1542 --- /dev/null +++ b/queue-6.12/xfrm-fix-the-usage-of-skb-sk.patch @@ -0,0 +1,135 @@ +From 98d16dcdbb69592c91228ea27af1b9c22065dd6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 11:46:03 +0100 +Subject: xfrm: Fix the usage of skb->sk + +From: Steffen Klassert + +[ Upstream commit 1620c88887b16940e00dbe57dd38c74eda9bad9e ] + +xfrm assumed to always have a full socket at skb->sk. +This is not always true, so fix it by converting to a +full socket before it is used. + +Signed-off-by: Steffen Klassert +Reviewed-by: Eric Dumazet +Stable-dep-of: 0c0eef8ccd24 ("esp: fix skb leak with espintcp and async crypto") +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 2 +- + net/ipv6/esp6.c | 2 +- + net/ipv6/xfrm6_output.c | 4 ++-- + net/xfrm/xfrm_interface_core.c | 2 +- + net/xfrm/xfrm_output.c | 7 ++++--- + net/xfrm/xfrm_policy.c | 2 +- + 6 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index cbe4c6fc8b8e9..b8c7c8b42c0a0 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -238,7 +238,7 @@ static void esp_output_done(void *data, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 62d17d7f6d9a9..9c4c7b1f29550 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -274,7 +274,7 @@ static void esp_output_done(void *data, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c +index 5f7b1fdbffe62..b3d5d1f266eee 100644 +--- a/net/ipv6/xfrm6_output.c ++++ b/net/ipv6/xfrm6_output.c +@@ -82,14 +82,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + toobig = skb->len > mtu && !skb_is_gso(skb); + +- if (toobig && xfrm6_local_dontfrag(skb->sk)) { ++ if (toobig && xfrm6_local_dontfrag(sk)) { + xfrm6_local_rxpmtu(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; + } else if (toobig && xfrm6_noneed_fragment(skb)) { + skb->ignore_df = 1; + goto skip_frag; +- } else if (!skb->ignore_df && toobig && skb->sk) { ++ } else if (!skb->ignore_df && toobig && sk) { + xfrm_local_error(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; +diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c +index b95d882f9dbcb..c92db6b497d4b 100644 +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -506,7 +506,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + skb_dst_set(skb, dst); + skb->dev = tdev; + +- err = dst_output(xi->net, skb->sk, skb); ++ err = dst_output(xi->net, skb_to_full_sk(skb), skb); + if (net_xmit_eval(err) == 0) { + dev_sw_netstats_tx_add(dev, 1, length); + } else { +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 9277dd4ed541a..a5b5d82bd7550 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -841,7 +841,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) + !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { + skb->protocol = htons(ETH_P_IP); + +- if (skb->sk) ++ if (skb->sk && sk_fullsock(skb->sk)) + xfrm_local_error(skb, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, +@@ -877,6 +877,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + { + int mtu, ret = 0; + struct dst_entry *dst = skb_dst(skb); ++ struct sock *sk = skb_to_full_sk(skb); + + if (skb->ignore_df) + goto out; +@@ -891,9 +892,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + skb->dev = dst->dev; + skb->protocol = htons(ETH_P_IPV6); + +- if (xfrm6_local_dontfrag(skb->sk)) ++ if (xfrm6_local_dontfrag(sk)) + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); +- else if (skb->sk) ++ else if (sk) + xfrm_local_error(skb, mtu); + else + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index aba06ff8694de..e1ce873b83234 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2962,7 +2962,7 @@ static void xfrm_policy_queue_process(struct timer_list *t) + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- dst_output(net, skb->sk, skb); ++ dst_output(net, skb_to_full_sk(skb), skb); + } + + out: +-- +2.51.0 + diff --git a/queue-6.12/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch b/queue-6.12/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch new file mode 100644 index 0000000000..9122a3a70a --- /dev/null +++ b/queue-6.12/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch @@ -0,0 +1,70 @@ +From 01a6638ca0ebd8180a653d9507bc7b6c7e15ad06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Mar 2026 03:16:29 +0900 +Subject: xfrm: Fix work re-schedule after cancel in + xfrm_nat_keepalive_net_fini() + +From: Hyunwoo Kim + +[ Upstream commit daf8e3b253aa760ff9e96c7768a464bc1d6b3c90 ] + +After cancel_delayed_work_sync() is called from +xfrm_nat_keepalive_net_fini(), xfrm_state_fini() flushes remaining +states via __xfrm_state_delete(), which calls +xfrm_nat_keepalive_state_updated() to re-schedule nat_keepalive_work. + +The following is a simple race scenario: + + cpu0 cpu1 + +cleanup_net() [Round 1] + ops_undo_list() + xfrm_net_exit() + xfrm_nat_keepalive_net_fini() + cancel_delayed_work_sync(nat_keepalive_work); + xfrm_state_fini() + xfrm_state_flush() + xfrm_state_delete(x) + __xfrm_state_delete(x) + xfrm_nat_keepalive_state_updated(x) + schedule_delayed_work(nat_keepalive_work); + rcu_barrier(); + net_complete_free(); + net_passive_dec(net); + llist_add(&net->defer_free_list, &defer_free_list); + +cleanup_net() [Round 2] + rcu_barrier(); + net_complete_free() + kmem_cache_free(net_cachep, net); + nat_keepalive_work() + // on freed net + +To prevent this, cancel_delayed_work_sync() is replaced with +disable_delayed_work_sync(). + +Fixes: f531d13bdfe3 ("xfrm: support sending NAT keepalives in ESP in UDP states") +Signed-off-by: Hyunwoo Kim +Reviewed-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_nat_keepalive.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_nat_keepalive.c b/net/xfrm/xfrm_nat_keepalive.c +index 82f0a301683f0..8a0379c8c41c8 100644 +--- a/net/xfrm/xfrm_nat_keepalive.c ++++ b/net/xfrm/xfrm_nat_keepalive.c +@@ -251,7 +251,7 @@ int __net_init xfrm_nat_keepalive_net_init(struct net *net) + + int xfrm_nat_keepalive_net_fini(struct net *net) + { +- cancel_delayed_work_sync(&net->xfrm.nat_keepalive_work); ++ disable_delayed_work_sync(&net->xfrm.nat_keepalive_work); + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.12/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch b/queue-6.12/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch new file mode 100644 index 0000000000..95e87851bd --- /dev/null +++ b/queue-6.12/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch @@ -0,0 +1,48 @@ +From e2b9d829e649990f5b5d860366b378d8239fb35d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 00:58:44 +0900 +Subject: xfrm: prevent policy_hthresh.work from racing with netns teardown + +From: Minwoo Ra + +[ Upstream commit 29fe3a61bcdce398ee3955101c39f89c01a8a77e ] + +A XFRM_MSG_NEWSPDINFO request can queue the per-net work item +policy_hthresh.work onto the system workqueue. + +The queued callback, xfrm_hash_rebuild(), retrieves the enclosing +struct net via container_of(). If the net namespace is torn down +before that work runs, the associated struct net may already have +been freed, and xfrm_hash_rebuild() may then dereference stale memory. + +xfrm_policy_fini() already flushes policy_hash_work during teardown, +but it does not synchronize policy_hthresh.work. + +Synchronize policy_hthresh.work in xfrm_policy_fini() as well, so the +queued work cannot outlive the net namespace teardown and access a +freed struct net. + +Fixes: 880a6fab8f6b ("xfrm: configure policy hash table thresholds by netlink") +Signed-off-by: Minwoo Ra +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index e1ce873b83234..f4713ab7996f2 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -4270,6 +4270,8 @@ static void xfrm_policy_fini(struct net *net) + unsigned int sz; + int dir; + ++ disable_work_sync(&net->xfrm.policy_hthresh.work); ++ + flush_work(&net->xfrm.policy_hash_work); + #ifdef CONFIG_XFRM_SUB_POLICY + xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false); +-- +2.51.0 + diff --git a/queue-6.18/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-6.18/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..da074fbe6e --- /dev/null +++ b/queue-6.18/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From 5a352cd1d07b175c504ed1899128ae891341472a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 2ebde03522459..ceaa82bc78acc 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch b/queue-6.18/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch new file mode 100644 index 0000000000..b045effdbe --- /dev/null +++ b/queue-6.18/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch @@ -0,0 +1,101 @@ +From 85004061d2cf2d5a6fb7ac9e91bbdbcb493a70ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 20:54:03 +0800 +Subject: Bluetooth: btintel: serialize btintel_hw_error() with + hci_req_sync_lock + +From: Cen Zhang + +[ Upstream commit 94d8e6fe5d0818e9300e514e095a200bd5ff93ae ] + +btintel_hw_error() issues two __hci_cmd_sync() calls (HCI_OP_RESET +and Intel exception-info retrieval) without holding +hci_req_sync_lock(). This lets it race against +hci_dev_do_close() -> btintel_shutdown_combined(), which also runs +__hci_cmd_sync() under the same lock. When both paths manipulate +hdev->req_status/req_rsp concurrently, the close path may free the +response skb first, and the still-running hw_error path hits a +slab-use-after-free in kfree_skb(). + +Wrap the whole recovery sequence in hci_req_sync_lock/unlock so it +is serialized with every other synchronous HCI command issuer. + +Below is the data race report and the kasan report: + + BUG: data-race in __hci_cmd_sync_sk / btintel_shutdown_combined + + read of hdev->req_rsp at net/bluetooth/hci_sync.c:199 + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x114/0x670 drivers/bluetooth/btintel.c:254 + hci_error_reset+0x348/0xa30 net/bluetooth/hci_core.c:1030 + + write/free by task ioctl/22580: + btintel_shutdown_combined+0xd0/0x360 + drivers/bluetooth/btintel.c:3648 + hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246 + hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526 + + BUG: KASAN: slab-use-after-free in + sk_skb_reason_drop+0x43/0x380 net/core/skbuff.c:1202 + Read of size 4 at addr ffff888144a738dc + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x186/0x670 drivers/bluetooth/btintel.c:260 + +Fixes: 973bb97e5aee ("Bluetooth: btintel: Add generic function for handling hardware errors") +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 9d29ab811f802..5e0a05edcbfd1 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -251,11 +251,13 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + + bt_dev_err(hdev, "Hardware error 0x%2.2x", code); + ++ hci_req_sync_lock(hdev); ++ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reset after hardware error failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + kfree_skb(skb); + +@@ -263,18 +265,21 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + + if (skb->len != 13) { + bt_dev_err(hdev, "Exception info size mismatch"); + kfree_skb(skb); +- return; ++ goto unlock; + } + + bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); + + kfree_skb(skb); ++ ++unlock: ++ hci_req_sync_unlock(hdev); + } + EXPORT_SYMBOL_GPL(btintel_hw_error); + +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-6.18/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..6a3bd99986 --- /dev/null +++ b/queue-6.18/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From bad8c4219aed40f524b89dafc6cda731487b042d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 7c7955afa8e8a..40f0c3b4eee6c 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2356,8 +2356,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-6.18/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..c52bbb41ec --- /dev/null +++ b/queue-6.18/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From d26329c52e7078a9d36f50274f8260b8aec2206f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 6f4e25917b863..c4584f4085766 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch b/queue-6.18/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch new file mode 100644 index 0000000000..ccee2b617b --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch @@ -0,0 +1,64 @@ +From f560ebf4ed242f2f8fba7ec0a8ce47b3f304f312 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:01:26 +0900 +Subject: Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del() + +From: Hyunwoo Kim + +[ Upstream commit 00fdebbbc557a2fc21321ff2eaa22fd70c078608 ] + +l2cap_conn_del() calls cancel_delayed_work_sync() for both info_timer +and id_addr_timer while holding conn->lock. However, the work functions +l2cap_info_timeout() and l2cap_conn_update_id_addr() both acquire +conn->lock, creating a potential AB-BA deadlock if the work is already +executing when l2cap_conn_del() takes the lock. + +Move the work cancellations before acquiring conn->lock and use +disable_delayed_work_sync() to additionally prevent the works from +being rearmed after cancellation, consistent with the pattern used in +hci_conn_del(). + +Fixes: ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 5bd5561a8dbf5..734cbb5dc1bfa 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1748,6 +1748,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + + BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); + ++ disable_delayed_work_sync(&conn->info_timer); ++ disable_delayed_work_sync(&conn->id_addr_timer); ++ + mutex_lock(&conn->lock); + + kfree_skb(conn->rx_skb); +@@ -1763,8 +1766,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + + ida_destroy(&conn->tx_ida); + +- cancel_delayed_work_sync(&conn->id_addr_timer); +- + l2cap_unregister_all_users(conn); + + /* Force the connection to be immediately dropped */ +@@ -1783,9 +1784,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + l2cap_chan_put(chan); + } + +- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) +- cancel_delayed_work_sync(&conn->info_timer); +- + hci_chan_del(conn->hchan); + conn->hchan = NULL; + +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-6.18/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..fb07cfec47 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From 845070baa663780691ace05d836a21747faeed52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 734cbb5dc1bfa..b72f2da57257d 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2375,6 +2375,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4310,14 +4313,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch b/queue-6.18/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch new file mode 100644 index 0000000000..fed83d5821 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch @@ -0,0 +1,150 @@ +From 07ced461ff649342426c5e1c0b600eea0a329983 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:39:44 -0500 +Subject: Bluetooth: L2CAP: Fix not tracking outstanding TX ident + +From: Luiz Augusto von Dentz + +[ Upstream commit 6c3ea155e5ee3e56606233acde8309afda66d483 ] + +This attempts to proper track outstanding request by using struct ida +and allocating from it in l2cap_get_ident using ida_alloc_range which +would reuse ids as they are free, then upon completion release +the id using ida_free. + +This fixes the qualification test case L2CAP/COS/CED/BI-29-C which +attempts to check if the host stack is able to work after 256 attempts +to connect which requires Ident field to use the full range of possible +values in order to pass the test. + +Link: https://github.com/bluez/bluez/issues/1829 +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Stable-dep-of: 00fdebbbc557 ("Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del()") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/l2cap.h | 3 +-- + net/bluetooth/l2cap_core.c | 46 ++++++++++++++++++++++++----------- + 2 files changed, 33 insertions(+), 16 deletions(-) + +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index f08ed93bb6fa3..010f1a8fd15f8 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -657,8 +657,7 @@ struct l2cap_conn { + + struct sk_buff *rx_skb; + __u32 rx_len; +- __u8 tx_ident; +- struct mutex ident_lock; ++ struct ida tx_ida; + + struct sk_buff_head pending_rx; + struct work_struct pending_rx_work; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index b5e393e4f3eb1..5bd5561a8dbf5 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -924,26 +924,18 @@ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) + initiator); + } + +-static u8 l2cap_get_ident(struct l2cap_conn *conn) ++static int l2cap_get_ident(struct l2cap_conn *conn) + { +- u8 id; ++ /* LE link does not support tools like l2ping so use the full range */ ++ if (conn->hcon->type == LE_LINK) ++ return ida_alloc_range(&conn->tx_ida, 1, 255, GFP_ATOMIC); + + /* Get next available identificator. + * 1 - 128 are used by kernel. + * 129 - 199 are reserved. + * 200 - 254 are used by utilities like l2ping, etc. + */ +- +- mutex_lock(&conn->ident_lock); +- +- if (++conn->tx_ident > 128) +- conn->tx_ident = 1; +- +- id = conn->tx_ident; +- +- mutex_unlock(&conn->ident_lock); +- +- return id; ++ return ida_alloc_range(&conn->tx_ida, 1, 128, GFP_ATOMIC); + } + + static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb, +@@ -1769,6 +1761,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + if (work_pending(&conn->pending_rx_work)) + cancel_work_sync(&conn->pending_rx_work); + ++ ida_destroy(&conn->tx_ida); ++ + cancel_delayed_work_sync(&conn->id_addr_timer); + + l2cap_unregister_all_users(conn); +@@ -4780,12 +4774,34 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, + return err; + } + ++static void l2cap_put_ident(struct l2cap_conn *conn, u8 code, u8 id) ++{ ++ switch (code) { ++ case L2CAP_COMMAND_REJ: ++ case L2CAP_CONN_RSP: ++ case L2CAP_CONF_RSP: ++ case L2CAP_DISCONN_RSP: ++ case L2CAP_ECHO_RSP: ++ case L2CAP_INFO_RSP: ++ case L2CAP_CONN_PARAM_UPDATE_RSP: ++ case L2CAP_ECRED_CONN_RSP: ++ case L2CAP_ECRED_RECONF_RSP: ++ /* First do a lookup since the remote may send bogus ids that ++ * would make ida_free to generate warnings. ++ */ ++ if (ida_find_first_range(&conn->tx_ida, id, id) >= 0) ++ ida_free(&conn->tx_ida, id); ++ } ++} ++ + static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_command_rej(conn, cmd, cmd_len, data); +@@ -5470,6 +5486,8 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_le_command_rej(conn, cmd, cmd_len, data); +@@ -6972,13 +6990,13 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) + hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) + conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; + +- mutex_init(&conn->ident_lock); + mutex_init(&conn->lock); + + INIT_LIST_HEAD(&conn->chan_l); + INIT_LIST_HEAD(&conn->users); + + INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); ++ ida_init(&conn->tx_ida); + + skb_queue_head_init(&conn->pending_rx); + INIT_WORK(&conn->pending_rx_work, process_pending_rx); +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-6.18/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..ee4b2f4198 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From 4cfc4c85ec7c60e8e20df3851be673feaa74f9b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index ab86aeef98d18..80a37d56b040f 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1681,6 +1681,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch b/queue-6.18/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch new file mode 100644 index 0000000000..ff9a3b6c04 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch @@ -0,0 +1,50 @@ +From 9f3ff991a4a9ba3b09a16133ddeaf58a0c693868 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 17:32:11 +0800 +Subject: Bluetooth: L2CAP: Fix send LE flow credits in ACL link + +From: Zhang Chen + +[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ] + +When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, +l2cap_publish_rx_avail will be called and le flow credits will be sent in +l2cap_chan_rx_avail, even though the link type is ACL. + +The logs in question as follows: +> ACL Data RX: Handle 129 flags 0x02 dlen 12 + L2CAP: Unknown (0x16) ident 4 len 4 + 40 00 ed 05 +< ACL Data TX: Handle 129 flags 0x00 dlen 10 + L2CAP: Command Reject (0x01) ident 4 len 2 + Reason: Command not understood (0x0000) + +Bluetooth: Unknown BR/EDR signaling command 0x16 +Bluetooth: Wrong link type (-22) + +Fixes: ce60b9231b66 ("Bluetooth: compute LE flow credits based on recvbuf space") +Signed-off-by: Zhang Chen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 848a9b945de89..b5e393e4f3eb1 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6589,6 +6589,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + struct l2cap_le_credits pkt; + u16 return_credits = l2cap_le_rx_credits(chan); + ++ if (chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ + if (chan->rx_credits >= return_credits) + return; + +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch b/queue-6.18/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch new file mode 100644 index 0000000000..963c4d3241 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch @@ -0,0 +1,67 @@ +From a4e9d4d27114a81f85b4c77cc7dba7ab0c4c83d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 22:14:37 +0900 +Subject: Bluetooth: L2CAP: Fix stack-out-of-bounds read in + l2cap_ecred_conn_req + +From: Minseo Park + +[ Upstream commit 9d87cb22195b2c67405f5485d525190747ad5493 ] + +Syzbot reported a KASAN stack-out-of-bounds read in l2cap_build_cmd() +that is triggered by a malformed Enhanced Credit Based Connection Request. + +The vulnerability stems from l2cap_ecred_conn_req(). The function allocates +a local stack buffer (`pdu`) designed to hold a maximum of 5 Source Channel +IDs (SCIDs), totaling 18 bytes. When an attacker sends a request with more +than 5 SCIDs, the function calculates `rsp_len` based on this unvalidated +`cmd_len` before checking if the number of SCIDs exceeds +L2CAP_ECRED_MAX_CID. + +If the SCID count is too high, the function correctly jumps to the +`response` label to reject the packet, but `rsp_len` retains the +attacker's oversized value. Consequently, l2cap_send_cmd() is instructed +to read past the end of the 18-byte `pdu` buffer, triggering a +KASAN panic. + +Fix this by moving the assignment of `rsp_len` to after the `num_scid` +boundary check. If the packet is rejected, `rsp_len` will safely +remain 0, and the error response will only read the 8-byte base header +from the stack. + +Fixes: c28d2bff7044 ("Bluetooth: L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short") +Reported-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b7f3e7d9a596bf6a63e3 +Tested-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Signed-off-by: Minseo Park +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9ea030fc9a9cc..583fe3b654c11 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -5065,14 +5065,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, + cmd_len -= sizeof(*req); + num_scid = cmd_len / sizeof(u16); + +- /* Always respond with the same number of scids as in the request */ +- rsp_len = cmd_len; +- + if (num_scid > L2CAP_ECRED_MAX_CID) { + result = L2CAP_CR_LE_INVALID_PARAMS; + goto response; + } + ++ /* Always respond with the same number of scids as in the request */ ++ rsp_len = cmd_len; ++ + mtu = __le16_to_cpu(req->mtu); + mps = __le16_to_cpu(req->mps); + +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-6.18/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..e221361635 --- /dev/null +++ b/queue-6.18/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 252799c4bb4e7e0170b7ed9f26a3b29b0c045acd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 583fe3b654c11..848a9b945de89 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6672,6 +6672,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch b/queue-6.18/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch new file mode 100644 index 0000000000..008f90d331 --- /dev/null +++ b/queue-6.18/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch @@ -0,0 +1,42 @@ +From cea78899d6bdd49a6e597b8a075024fb2699d17d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:03:27 -0400 +Subject: Bluetooth: MGMT: Fix dangling pointer on + mgmt_add_adv_patterns_monitor_complete + +From: Luiz Augusto von Dentz + +[ Upstream commit 5f5fa4cd35f707344f65ce9e225b6528691dbbaa ] + +This fixes the condition checking so mgmt_pending_valid is executed +whenever status != -ECANCELED otherwise calling mgmt_pending_free(cmd) +would kfree(cmd) without unlinking it from the list first, leaving a +dangling pointer. Any subsequent list traversal (e.g., +mgmt_pending_foreach during __mgmt_power_off, or another +mgmt_pending_valid call) would dereference freed memory. + +Link: https://lore.kernel.org/linux-bluetooth/20260315132013.75ab40c5@kernel.org/T/#m1418f9c82eeff8510c1beaa21cf53af20db96c06 +Fixes: 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs") +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 1a270f0b17d9e..5d70b1f69bb6d 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -5273,7 +5273,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, + * hci_adv_monitors_clear is about to be called which will take care of + * freeing the adv_monitor instances. + */ +- if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd)) ++ if (status == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) + return; + + monitor = cmd->user_data; +-- +2.51.0 + diff --git a/queue-6.18/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-6.18/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..070c5ad1ec --- /dev/null +++ b/queue-6.18/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From 18852ec86599665578e182f124544ed94769bcd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 49a47eaa674da..f7b50cc730476 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -401,7 +401,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -410,11 +410,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-6.18/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-6.18/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..fe9c78e0d6 --- /dev/null +++ b/queue-6.18/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From 189f680c2ab8ffde48b0e8a7e1f4b5425e7dc28d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index 770173d8db428..a624c04ed5c63 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -469,7 +469,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -573,7 +573,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 0938bf7dd646a..de4d05ae34597 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-6.18/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-6.18/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..8f2dfd86b0 --- /dev/null +++ b/queue-6.18/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 999e0d038f82d38f65b1a0c61ab25e501fc27881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index aa36a0d1d9df6..190eab9f5e8c2 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -240,8 +240,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-6.18/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch b/queue-6.18/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch new file mode 100644 index 0000000000..1a8ce110fc --- /dev/null +++ b/queue-6.18/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch @@ -0,0 +1,83 @@ +From 0b6868f4c11409705e82f0325086f50e5c4d773a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 17:27:49 +0900 +Subject: dma: swiotlb: add KMSAN annotations to swiotlb_bounce() + +From: Shigeru Yoshida + +[ Upstream commit 6f770b73d0311a5b099277653199bb6421c4fed2 ] + +When a device performs DMA to a bounce buffer, KMSAN is unaware of +the write and does not mark the data as initialized. When +swiotlb_bounce() later copies the bounce buffer back to the original +buffer, memcpy propagates the uninitialized shadow to the original +buffer, causing false positive uninit-value reports. + +Fix this by calling kmsan_unpoison_memory() on the bounce buffer +before copying it back in the DMA_FROM_DEVICE path, so that memcpy +naturally propagates initialized shadow to the destination. + +Suggested-by: Alexander Potapenko +Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/ +Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") +Signed-off-by: Shigeru Yoshida +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index 0d37da3d95b65..e27225f8aeb27 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -903,10 +904,19 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + + local_irq_save(flags); + page = pfn_to_page(pfn); +- if (dir == DMA_TO_DEVICE) ++ if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_highmem_page() ++ * could be used here to detect infoleaks, ++ * but callers may map uninitialized buffers ++ * that will be written by the device, ++ * causing false positives. ++ */ + memcpy_from_page(vaddr, page, offset, sz); +- else ++ } else { ++ kmsan_unpoison_memory(vaddr, sz); + memcpy_to_page(page, offset, vaddr, sz); ++ } + local_irq_restore(flags); + + size -= sz; +@@ -915,8 +925,15 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + offset = 0; + } + } else if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_memory() could be used here to detect ++ * infoleaks (uninitialized data being sent to device), but ++ * callers may map uninitialized buffers that will be written ++ * by the device, causing false positives. ++ */ + memcpy(vaddr, phys_to_virt(orig_addr), size); + } else { ++ kmsan_unpoison_memory(vaddr, size); + memcpy(phys_to_virt(orig_addr), vaddr, size); + } + } +-- +2.51.0 + diff --git a/queue-6.18/erofs-set-fileio-bio-failed-in-short-read-case.patch b/queue-6.18/erofs-set-fileio-bio-failed-in-short-read-case.patch new file mode 100644 index 0000000000..c8ad0bb64f --- /dev/null +++ b/queue-6.18/erofs-set-fileio-bio-failed-in-short-read-case.patch @@ -0,0 +1,60 @@ +From dccf4c95b2a28110a47eba36a4a95bcc66001121 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Feb 2026 10:30:08 +0800 +Subject: erofs: set fileio bio failed in short read case + +From: Sheng Yong + +[ Upstream commit eade54040384f54b7fb330e4b0975c5734850b3c ] + +For file-backed mount, IO requests are handled by vfs_iocb_iter_read(). +However, it can be interrupted by SIGKILL, returning the number of +bytes actually copied. Unused folios in bio are unexpectedly marked +as uptodate. + + vfs_read + filemap_read + filemap_get_pages + filemap_readahead + erofs_fileio_readahead + erofs_fileio_rq_submit + vfs_iocb_iter_read + filemap_read + filemap_get_pages <= detect signal + erofs_fileio_ki_complete <= set all folios uptodate + +This patch addresses this by setting short read bio with an error +directly. + +Fixes: bc804a8d7e86 ("erofs: handle end of filesystem properly for file-backed mounts") +Reported-by: chenguanyou +Signed-off-by: Yunlei He +Signed-off-by: Sheng Yong +Reviewed-by: Gao Xiang +Reviewed-by: Chao Yu +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/fileio.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c +index 5b77ee8cc99f4..740efd2097bf1 100644 +--- a/fs/erofs/fileio.c ++++ b/fs/erofs/fileio.c +@@ -25,10 +25,8 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret) + container_of(iocb, struct erofs_fileio_rq, iocb); + struct folio_iter fi; + +- if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) { +- bio_advance(&rq->bio, ret); +- zero_fill_bio(&rq->bio); +- } ++ if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) ++ ret = -EIO; + if (!rq->bio.bi_end_io) { + bio_for_each_folio_all(fi, &rq->bio) { + DBG_BUGON(folio_test_uptodate(fi.folio)); +-- +2.51.0 + diff --git a/queue-6.18/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-6.18/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..20fb4a59db --- /dev/null +++ b/queue-6.18/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From eb9feef2577d268838e58a07373e1ee64683c408 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 2c922afadb8f6..6dfc0bcdef654 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -235,10 +235,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index e75da98f52838..9f75313734f8c 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -271,10 +271,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-6.18/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch b/queue-6.18/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch new file mode 100644 index 0000000000..ef772698a8 --- /dev/null +++ b/queue-6.18/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch @@ -0,0 +1,158 @@ +From 0e49b3a81b77766d1aec88819e35fb004648c87d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Feb 2026 19:14:25 +0000 +Subject: iavf: fix out-of-bounds writes in iavf_get_ethtool_stats() + +From: Kohei Enju + +[ Upstream commit fecacfc95f195b99c71c579a472120d0b4ed65fa ] + +iavf incorrectly uses real_num_tx_queues for ETH_SS_STATS. Since the +value could change in runtime, we should use num_tx_queues instead. + +Moreover iavf_get_ethtool_stats() uses num_active_queues while +iavf_get_sset_count() and iavf_get_stat_strings() use +real_num_tx_queues, which triggers out-of-bounds writes when we do +"ethtool -L" and "ethtool -S" simultaneously [1]. + +For example when we change channels from 1 to 8, Thread 3 could be +scheduled before Thread 2, and out-of-bounds writes could be triggered +in Thread 3: + +Thread 1 (ethtool -L) Thread 2 (work) Thread 3 (ethtool -S) +iavf_set_channels() +... +iavf_alloc_queues() +-> num_active_queues = 8 +iavf_schedule_finish_config() + iavf_get_sset_count() + real_num_tx_queues: 1 + -> buffer for 1 queue + iavf_get_ethtool_stats() + num_active_queues: 8 + -> out-of-bounds! + iavf_finish_config() + -> real_num_tx_queues = 8 + +Use immutable num_tx_queues in all related functions to avoid the issue. + +[1] + BUG: KASAN: vmalloc-out-of-bounds in iavf_add_one_ethtool_stat+0x200/0x270 + Write of size 8 at addr ffffc900031c9080 by task ethtool/5800 + + CPU: 1 UID: 0 PID: 5800 Comm: ethtool Not tainted 6.19.0-enjuk-08403-g8137e3db7f1c #241 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + Call Trace: + + dump_stack_lvl+0x6f/0xb0 + print_report+0x170/0x4f3 + kasan_report+0xe1/0x180 + iavf_add_one_ethtool_stat+0x200/0x270 + iavf_get_ethtool_stats+0x14c/0x2e0 + __dev_ethtool+0x3d0c/0x5830 + dev_ethtool+0x12d/0x270 + dev_ioctl+0x53c/0xe30 + sock_do_ioctl+0x1a9/0x270 + sock_ioctl+0x3d4/0x5e0 + __x64_sys_ioctl+0x137/0x1c0 + do_syscall_64+0xf3/0x690 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + RIP: 0033:0x7f7da0e6e36d + ... + + + The buggy address belongs to a 1-page vmalloc region starting at 0xffffc900031c9000 allocated at __dev_ethtool+0x3cc9/0x5830 + The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff88813a013de0 pfn:0x13a013 + flags: 0x200000000000000(node=0|zone=2) + raw: 0200000000000000 0000000000000000 dead000000000122 0000000000000000 + raw: ffff88813a013de0 0000000000000000 00000001ffffffff 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffffc900031c8f80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ffffc900031c9080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffffc900031c9100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9180: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + +Fixes: 64430f70ba6f ("iavf: Fix displaying queue statistics shown by ethtool") +Signed-off-by: Kohei Enju +Reviewed-by: Simon Horman +Reviewed-by: Przemek Kitszel +Reviewed-by: Paul Menzel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../net/ethernet/intel/iavf/iavf_ethtool.c | 31 +++++++++---------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +index cb3f78aab23a6..9ed1fb9432fc7 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +@@ -313,14 +313,13 @@ static int iavf_get_sset_count(struct net_device *netdev, int sset) + { + /* Report the maximum number queues, even if not every queue is + * currently configured. Since allocation of queues is in pairs, +- * use netdev->real_num_tx_queues * 2. The real_num_tx_queues is set +- * at device creation and never changes. ++ * use netdev->num_tx_queues * 2. The num_tx_queues is set at ++ * device creation and never changes. + */ + + if (sset == ETH_SS_STATS) + return IAVF_STATS_LEN + +- (IAVF_QUEUE_STATS_LEN * 2 * +- netdev->real_num_tx_queues); ++ (IAVF_QUEUE_STATS_LEN * 2 * netdev->num_tx_queues); + else + return -EINVAL; + } +@@ -345,19 +344,19 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, + iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats); + + rcu_read_lock(); +- /* As num_active_queues describe both tx and rx queues, we can use +- * it to iterate over rings' stats. ++ /* Use num_tx_queues to report stats for the maximum number of queues. ++ * Queues beyond num_active_queues will report zero. + */ +- for (i = 0; i < adapter->num_active_queues; i++) { +- struct iavf_ring *ring; ++ for (i = 0; i < netdev->num_tx_queues; i++) { ++ struct iavf_ring *tx_ring = NULL, *rx_ring = NULL; + +- /* Tx rings stats */ +- ring = &adapter->tx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ if (i < adapter->num_active_queues) { ++ tx_ring = &adapter->tx_rings[i]; ++ rx_ring = &adapter->rx_rings[i]; ++ } + +- /* Rx rings stats */ +- ring = &adapter->rx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ iavf_add_queue_stats(&data, tx_ring); ++ iavf_add_queue_stats(&data, rx_ring); + } + rcu_read_unlock(); + } +@@ -376,9 +375,9 @@ static void iavf_get_stat_strings(struct net_device *netdev, u8 *data) + iavf_add_stat_strings(&data, iavf_gstrings_stats); + + /* Queues are always allocated in pairs, so we just use +- * real_num_tx_queues for both Tx and Rx queues. ++ * num_tx_queues for both Tx and Rx queues. + */ +- for (i = 0; i < netdev->real_num_tx_queues; i++) { ++ for (i = 0; i < netdev->num_tx_queues; i++) { + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, + "tx", i); + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, +-- +2.51.0 + diff --git a/queue-6.18/ice-fix-inverted-ready-check-for-vf-representors.patch b/queue-6.18/ice-fix-inverted-ready-check-for-vf-representors.patch new file mode 100644 index 0000000000..721789a25e --- /dev/null +++ b/queue-6.18/ice-fix-inverted-ready-check-for-vf-representors.patch @@ -0,0 +1,50 @@ +From 96b785d2fa6f1dd7dca0db807d0ba09d5dcf4edb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:10 +0100 +Subject: ice: fix inverted ready check for VF representors + +From: Petr Oros + +[ Upstream commit ad85de0fc09eb3236e73df5acb2bc257625103f5 ] + +Commit 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +refactored the VF readiness check into a generic repr->ops.ready() +callback but implemented ice_repr_ready_vf() with inverted logic: + + return !ice_check_vf_ready_for_cfg(repr->vf); + +ice_check_vf_ready_for_cfg() returns 0 on success, so the negation +makes ready() return non-zero when the VF is ready. All callers treat +non-zero as "not ready, skip", causing ndo_get_stats64, get_drvinfo, +get_strings and get_ethtool_stats to always bail out in switchdev mode. + +Remove the erroneous negation. The SF variant ice_repr_ready_sf() is +already correct (returns !active, i.e. non-zero when not active). + +Fixes: 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Michal Swiatkowski +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_repr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index cb08746556a67..2a84f65640582 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -315,7 +315,7 @@ ice_repr_reg_netdev(struct net_device *netdev, const struct net_device_ops *ops) + + static int ice_repr_ready_vf(struct ice_repr *repr) + { +- return !ice_check_vf_ready_for_cfg(repr->vf); ++ return ice_check_vf_ready_for_cfg(repr->vf); + } + + static int ice_repr_ready_sf(struct ice_repr *repr) +-- +2.51.0 + diff --git a/queue-6.18/ice-use-ice_update_eth_stats-for-representor-stats.patch b/queue-6.18/ice-use-ice_update_eth_stats-for-representor-stats.patch new file mode 100644 index 0000000000..86ee6611be --- /dev/null +++ b/queue-6.18/ice-use-ice_update_eth_stats-for-representor-stats.patch @@ -0,0 +1,100 @@ +From ea75bb6eaaff8b398099636594339cb502ccd2fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:11 +0100 +Subject: ice: use ice_update_eth_stats() for representor stats + +From: Petr Oros + +[ Upstream commit 2526e440df2725e7328d59b835a164826f179b93 ] + +ice_repr_get_stats64() and __ice_get_ethtool_stats() call +ice_update_vsi_stats() on the VF's src_vsi. This always returns early +because ICE_VSI_DOWN is permanently set for VF VSIs - ice_up() is never +called on them since queues are managed by iavf through virtchnl. + +In __ice_get_ethtool_stats() the original code called +ice_update_vsi_stats() for all VSIs including representors, iterated +over ice_gstrings_vsi_stats[] to populate the data, and then bailed out +with an early return before the per-queue ring stats section. That early +return was necessary because representor VSIs have no rings on the PF +side - the rings belong to the VF driver (iavf), so accessing per-queue +stats would be invalid. + +Move the representor handling to the top of __ice_get_ethtool_stats() +and call ice_update_eth_stats() directly to read the hardware GLV_* +counters. This matches ice_get_vf_stats() which already uses +ice_update_eth_stats() for the same VF VSI in legacy mode. Apply the +same fix to ice_repr_get_stats64(). + +Note that ice_gstrings_vsi_stats[] contains five software ring counters +(rx_buf_failed, rx_page_failed, tx_linearize, tx_busy, tx_restart) that +are always zero for representors since the PF never processes packets on +VF rings. This is pre-existing behavior unchanged by this patch. + +Fixes: 7aae80cef7ba ("ice: add port representor ethtool ops and stats") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 14 +++++++++++--- + drivers/net/ethernet/intel/ice/ice_repr.c | 3 ++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 5396ddd66ef75..b52fcf7b899f7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1940,6 +1940,17 @@ __ice_get_ethtool_stats(struct net_device *netdev, + int i = 0; + char *p; + ++ if (ice_is_port_repr_netdev(netdev)) { ++ ice_update_eth_stats(vsi); ++ ++ for (j = 0; j < ICE_VSI_STATS_LEN; j++) { ++ p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; ++ data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ return; ++ } ++ + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + +@@ -1949,9 +1960,6 @@ __ice_get_ethtool_stats(struct net_device *netdev, + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + +- if (ice_is_port_repr_netdev(netdev)) +- return; +- + /* populate per queue stats */ + rcu_read_lock(); + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index 2a84f65640582..f1e82ba155cff 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2019-2021, Intel Corporation. */ + + #include "ice.h" ++#include "ice_lib.h" + #include "ice_eswitch.h" + #include "devlink/devlink.h" + #include "devlink/port.h" +@@ -67,7 +68,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) + return; + vsi = repr->src_vsi; + +- ice_update_vsi_stats(vsi); ++ ice_update_eth_stats(vsi); + eth_stats = &vsi->eth_stats; + + stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast + +-- +2.51.0 + diff --git a/queue-6.18/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-6.18/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..db757da2c8 --- /dev/null +++ b/queue-6.18/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From a9b187884c1d07c560cababf294cde43719edd8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index b28966ae50c22..29a8a25a3ed08 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1719,13 +1719,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-6.18/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch b/queue-6.18/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch new file mode 100644 index 0000000000..bc82df218c --- /dev/null +++ b/queue-6.18/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch @@ -0,0 +1,144 @@ +From 5a91ff6b24343d1ba5cc2672fd4eb0269be9f896 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:23:00 +0000 +Subject: ipv6: Don't remove permanent routes with exceptions from + tb6_gc_hlist. + +From: Kuniyuki Iwashima + +[ Upstream commit 4be7b99c253f0c85a255cc1db7127ba3232dfa30 ] + +The cited commit mechanically put fib6_remove_gc_list() +just after every fib6_clean_expires() call. + +When a temporary route is promoted to a permanent route, +there may already be exception routes tied to it. + +If fib6_remove_gc_list() removes the route from tb6_gc_hlist, +such exception routes will no longer be aged. + +Let's replace fib6_remove_gc_list() with a new helper +fib6_may_remove_gc_list() and use fib6_age_exceptions() there. + +Note that net->ipv6 is only compiled when CONFIG_IPV6 is +enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded. + +Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/ip6_fib.h | 21 ++++++++++++++++++++- + net/ipv6/addrconf.c | 4 ++-- + net/ipv6/ip6_fib.c | 6 +++--- + net/ipv6/route.c | 2 +- + 4 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 88b0dd4d8e094..9f8b6814a96a0 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -507,12 +507,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt, + void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + unsigned int flags); + ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now); + void fib6_run_gc(unsigned long expires, struct net *net, bool force); +- + void fib6_gc_cleanup(void); + + int fib6_init(void); + ++#if IS_ENABLED(CONFIG_IPV6) + /* Add the route to the gc list if it is not already there + * + * The callers should hold f6i->fib6_table->tb6_lock. +@@ -545,6 +547,23 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i) + hlist_del_init(&f6i->gc_link); + } + ++static inline void fib6_may_remove_gc_list(struct net *net, ++ struct fib6_info *f6i) ++{ ++ struct fib6_gc_args gc_args; ++ ++ if (hlist_unhashed(&f6i->gc_link)) ++ return; ++ ++ gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval); ++ gc_args.more = 0; ++ ++ rcu_read_lock(); ++ fib6_age_exceptions(f6i, &gc_args, jiffies); ++ rcu_read_unlock(); ++} ++#endif ++ + struct ipv6_route_iter { + struct seq_net_private p; + struct fib6_walker w; +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index cad5e4ab8c3db..4a745566b760d 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2863,7 +2863,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) + fib6_add_gc_list(rt); + } else { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } + + spin_unlock_bh(&table->tb6_lock); +@@ -4836,7 +4836,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp, + + if (!(flags & RTF_EXPIRES)) { + fib6_clean_expires(f6i); +- fib6_remove_gc_list(f6i); ++ fib6_may_remove_gc_list(net, f6i); + } else { + fib6_set_expires(f6i, expires); + fib6_add_gc_list(f6i); +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index a22af1c8f93ac..ffa7733598333 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + return -EEXIST; + if (!(rt->fib6_flags & RTF_EXPIRES)) { + fib6_clean_expires(iter); +- fib6_remove_gc_list(iter); ++ fib6_may_remove_gc_list(info->nl_net, iter); + } else { + fib6_set_expires(iter, rt->expires); + fib6_add_gc_list(iter); +@@ -2348,8 +2348,8 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ +-static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, +- unsigned long now) ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) + { + bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; + int old_more = gc_args->more; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index e01331d965313..446f4de7d6a22 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1033,7 +1033,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + + if (!addrconf_finite_timeout(lifetime)) { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } else { + fib6_set_expires(rt, jiffies + HZ * lifetime); + fib6_add_gc_list(rt); +-- +2.51.0 + diff --git a/queue-6.18/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch b/queue-6.18/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch new file mode 100644 index 0000000000..2ce5831f8a --- /dev/null +++ b/queue-6.18/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch @@ -0,0 +1,76 @@ +From eec4eee79c177d0798630a3e8ee7fbe35cb0304a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:22:59 +0000 +Subject: ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions + expire. + +From: Kuniyuki Iwashima + +[ Upstream commit 6af51e9f31336632263c4680b2a3712295103e1f ] + +Commit 5eb902b8e719 ("net/ipv6: Remove expired routes with a +separated list of routes.") introduced a per-table GC list and +changed GC to iterate over that list instead of traversing +the entire route table. + +However, it forgot to add permanent routes to tb6_gc_hlist +when exception routes are added. + +Commit cfe82469a00f ("ipv6: add exception routes to GC list +in rt6_insert_exception") fixed that issue but introduced +another one. + +Even after all exception routes expire, the permanent routes +remain in tb6_gc_hlist, potentially negating the performance +benefits intended by the initial change. + +Let's count gc_args->more before and after rt6_age_exceptions() +and remove the permanent route when the delta is 0. + +Note that the next patch will reuse fib6_age_exceptions(). + +Fixes: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Xin Long +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index cc149227b49f4..a22af1c8f93ac 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -2348,6 +2348,17 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ ++static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) ++{ ++ bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; ++ int old_more = gc_args->more; ++ ++ rt6_age_exceptions(rt, gc_args, now); ++ ++ if (!may_expire && old_more == gc_args->more) ++ fib6_remove_gc_list(rt); ++} + + static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + { +@@ -2370,7 +2381,7 @@ static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + * Note, that clones are aged out + * only if they are not in use now. + */ +- rt6_age_exceptions(rt, gc_args, now); ++ fib6_age_exceptions(rt, gc_args, now); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.18/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch b/queue-6.18/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch new file mode 100644 index 0000000000..1c6a5f1f95 --- /dev/null +++ b/queue-6.18/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch @@ -0,0 +1,41 @@ +From 79ff17dcacb2317dbac474a0ec8711e5d7300c64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:43:15 +0800 +Subject: net: airoha: add RCU lock around dev_fill_forward_path + +From: Qingfang Deng + +[ Upstream commit 1065913dedfd3a8269816835bfe810b6e2c28579 ] + +Since 0417adf367a0 ("ppp: fix race conditions in ppp_fill_forward_path") +dev_fill_forward_path() should be called with RCU read lock held. This +fix was applied to net, while the Airoha flowtable commit was applied to +net-next, so it hadn't been an issue until net was merged into net-next. + +Fixes: a8bdd935d1dd ("net: airoha: Add wlan flowtable TX offload") +Signed-off-by: Qingfang Deng +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260320094315.525126-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c +index 190d98970014f..b3632f964a580 100644 +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -201,7 +201,9 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr, + if (!dev) + return -ENODEV; + ++ rcu_read_lock(); + err = dev_fill_forward_path(dev, addr, &stack); ++ rcu_read_unlock(); + if (err) + return err; + +-- +2.51.0 + diff --git a/queue-6.18/net-bcmasp-fix-double-disable-of-clk.patch b/queue-6.18/net-bcmasp-fix-double-disable-of-clk.patch new file mode 100644 index 0000000000..c83c7516f2 --- /dev/null +++ b/queue-6.18/net-bcmasp-fix-double-disable-of-clk.patch @@ -0,0 +1,122 @@ +From 3b7b9694285241e0578004cdc506663aca2990a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:13 -0700 +Subject: net: bcmasp: fix double disable of clk + +From: Justin Chen + +[ Upstream commit 27dfe9030acbc601c260b42ecdbb4e5858a97b53 ] + +Switch to devm_clk_get_optional() so we can manage the clock ourselves. +We dynamically control the clocks depending on the state of the interface +for power savings. The default state is clock disabled, so unbinding the +driver causes a double disable. + +Fixes: 490cb412007d ("net: bcmasp: Add support for ASP2.0 Ethernet controller") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 33 ++++++++++++++------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index fac795ac0fcee..1fdf0822c8a02 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1254,7 +1254,7 @@ static int bcmasp_probe(struct platform_device *pdev) + if (priv->irq <= 0) + return -EINVAL; + +- priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp"); ++ priv->clk = devm_clk_get_optional(dev, "sw_asp"); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to request clock\n"); +@@ -1282,6 +1282,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + bcmasp_set_pdata(priv, pdata); + ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to start clock\n"); ++ + /* Enable all clocks to ensure successful probing */ + bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); + +@@ -1293,8 +1297,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0, + pdev->name, priv); +- if (ret) +- return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret); ++ if (ret) { ++ dev_err(dev, "Failed to request ASP interrupt: %d", ret); ++ goto err_clock_disable; ++ } + + /* Register mdio child nodes */ + of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev); +@@ -1306,13 +1312,17 @@ static int bcmasp_probe(struct platform_device *pdev) + + priv->mda_filters = devm_kcalloc(dev, priv->num_mda_filters, + sizeof(*priv->mda_filters), GFP_KERNEL); +- if (!priv->mda_filters) +- return -ENOMEM; ++ if (!priv->mda_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + priv->net_filters = devm_kcalloc(dev, priv->num_net_filters, + sizeof(*priv->net_filters), GFP_KERNEL); +- if (!priv->net_filters) +- return -ENOMEM; ++ if (!priv->net_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + bcmasp_core_init_filters(priv); + +@@ -1321,7 +1331,8 @@ static int bcmasp_probe(struct platform_device *pdev) + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_clock_disable; + } + + i = 0; +@@ -1343,8 +1354,6 @@ static int bcmasp_probe(struct platform_device *pdev) + */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE); + +- clk_disable_unprepare(priv->clk); +- + /* Now do the registration of the network ports which will take care + * of managing the clock properly. + */ +@@ -1357,12 +1366,16 @@ static int bcmasp_probe(struct platform_device *pdev) + count++; + } + ++ clk_disable_unprepare(priv->clk); ++ + dev_info(dev, "Initialized %d port(s)\n", count); + + return ret; + + err_cleanup: + bcmasp_remove_intfs(priv); ++err_clock_disable: ++ clk_disable_unprepare(priv->clk); + + return ret; + } +-- +2.51.0 + diff --git a/queue-6.18/net-bcmasp-fix-double-free-of-wol-irq.patch b/queue-6.18/net-bcmasp-fix-double-free-of-wol-irq.patch new file mode 100644 index 0000000000..968dadf3e7 --- /dev/null +++ b/queue-6.18/net-bcmasp-fix-double-free-of-wol-irq.patch @@ -0,0 +1,58 @@ +From 6b91c51fcf535d65697a4f16d0c1e1d7f7bd9297 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:12 -0700 +Subject: net: bcmasp: fix double free of WoL irq + +From: Justin Chen + +[ Upstream commit cbfa5be2bf64511d49b854a0f9fd6d0b5118621f ] + +We do not need to free wol_irq since it was instantiated with +devm_request_irq(). So devres will free for us. + +Fixes: a2f0751206b0 ("net: bcmasp: Add support for WoL magic packet") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-2-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index de5f540f78049..fac795ac0fcee 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1157,12 +1157,6 @@ void bcmasp_enable_wol(struct bcmasp_intf *intf, bool en) + } + } + +-static void bcmasp_wol_irq_destroy(struct bcmasp_priv *priv) +-{ +- if (priv->wol_irq > 0) +- free_irq(priv->wol_irq, priv); +-} +- + static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + { + u32 reg, phy_lpi_overwrite; +@@ -1368,7 +1362,6 @@ static int bcmasp_probe(struct platform_device *pdev) + return ret; + + err_cleanup: +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + + return ret; +@@ -1381,7 +1374,6 @@ static void bcmasp_remove(struct platform_device *pdev) + if (!priv) + return; + +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + } + +-- +2.51.0 + diff --git a/queue-6.18/net-bcmasp-streamline-early-exit-in-probe.patch b/queue-6.18/net-bcmasp-streamline-early-exit-in-probe.patch new file mode 100644 index 0000000000..4ab4e44cbe --- /dev/null +++ b/queue-6.18/net-bcmasp-streamline-early-exit-in-probe.patch @@ -0,0 +1,88 @@ +From 0f6c375a0813216f0fc88f3e0dabcdcd8af3019a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Jan 2026 11:49:49 -0800 +Subject: net: bcmasp: streamline early exit in probe + +From: Justin Chen + +[ Upstream commit 1fd1281250c38408d793863c8dcaa43c7de8932c ] + +Streamline the bcmasp_probe early exit. As support for other +functionality is added(i.e. ptp), it is easier to keep track of early +exit cleanup when it is all in one place. + +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260122194949.1145107-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 27 +++++++++++---------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 014340f33345a..de5f540f78049 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1322,6 +1322,8 @@ static int bcmasp_probe(struct platform_device *pdev) + + bcmasp_core_init_filters(priv); + ++ bcmasp_init_wol(priv); ++ + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +@@ -1333,16 +1335,14 @@ static int bcmasp_probe(struct platform_device *pdev) + intf = bcmasp_interface_create(priv, intf_node, i); + if (!intf) { + dev_err(dev, "Cannot create eth interface %d\n", i); +- bcmasp_remove_intfs(priv); +- ret = -ENOMEM; +- goto of_put_exit; ++ of_node_put(ports_node); ++ ret = -EINVAL; ++ goto err_cleanup; + } + list_add_tail(&intf->list, &priv->intfs); + i++; + } +- +- /* Check and enable WoL */ +- bcmasp_init_wol(priv); ++ of_node_put(ports_node); + + /* Drop the clock reference count now and let ndo_open()/ndo_close() + * manage it for us from now on. +@@ -1357,19 +1357,20 @@ static int bcmasp_probe(struct platform_device *pdev) + list_for_each_entry(intf, &priv->intfs, list) { + ret = register_netdev(intf->ndev); + if (ret) { +- netdev_err(intf->ndev, +- "failed to register net_device: %d\n", ret); +- bcmasp_wol_irq_destroy(priv); +- bcmasp_remove_intfs(priv); +- goto of_put_exit; ++ dev_err(dev, "failed to register net_device: %d\n", ret); ++ goto err_cleanup; + } + count++; + } + + dev_info(dev, "Initialized %d port(s)\n", count); + +-of_put_exit: +- of_node_put(ports_node); ++ return ret; ++ ++err_cleanup: ++ bcmasp_wol_irq_destroy(priv); ++ bcmasp_remove_intfs(priv); ++ + return ret; + } + +-- +2.51.0 + diff --git a/queue-6.18/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-6.18/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..a812d006b8 --- /dev/null +++ b/queue-6.18/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From e23adab798d8a7ee34fbe067e7d7bbcb15f00020 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index 71d052de669ab..0250ed95e48ca 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -788,6 +788,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-6.18/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-6.18/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..e383507937 --- /dev/null +++ b/queue-6.18/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From bd95625226f204f90b9adb2c0284ff12ed315f3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 173e6edda08f8..5c08e0da0dff4 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3135,6 +3135,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-6.18/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch b/queue-6.18/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch new file mode 100644 index 0000000000..512062623d --- /dev/null +++ b/queue-6.18/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch @@ -0,0 +1,49 @@ +From 7c5e5d0fe27fe489f4911d8f0eb1fb518bb4a596 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 12:23:45 +0530 +Subject: net: lan743x: fix duplex configuration in mac_link_up + +From: Thangaraj Samynathan + +[ Upstream commit 71399707876b93240f236f48b8062f3423a5fe97 ] + +The driver does not explicitly configure the MAC duplex mode when +bringing the link up. As a result, the MAC may retain a stale duplex +setting from a previous link state, leading to duplex mismatches with +the link partner and degraded network performance. + +Update lan743x_phylink_mac_link_up() to set or clear the MAC_CR_DPX_ +bit according to the negotiated duplex mode. + +This ensures the MAC configuration is consistent with the phylink +resolved state. + +Fixes: a5f199a8d8a03 ("net: lan743x: Migrate phylib to phylink") +Signed-off-by: Thangaraj Samynathan +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/20260323065345.144915-1-thangaraj.s@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index e4c542fc6c2b8..09d255e78f6cd 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -3054,6 +3054,11 @@ static void lan743x_phylink_mac_link_up(struct phylink_config *config, + else if (speed == SPEED_100) + mac_cr |= MAC_CR_CFG_L_; + ++ if (duplex == DUPLEX_FULL) ++ mac_cr |= MAC_CR_DPX_; ++ else ++ mac_cr &= ~MAC_CR_DPX_; ++ + lan743x_csr_write(adapter, MAC_CR, mac_cr); + + lan743x_ptp_update_latency(adapter, speed); +-- +2.51.0 + diff --git a/queue-6.18/net-macb-use-the-current-queue-number-for-stats.patch b/queue-6.18/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..8d36caa55b --- /dev/null +++ b/queue-6.18/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From e0073b6e064b4725bcbc24ad9c47ce4c982f9dff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 4624db166a27b..55a0258c2eaa5 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3258,7 +3258,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-6.18/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-6.18/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..88e2a0ea9a --- /dev/null +++ b/queue-6.18/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From 93cb07abd9df76cb9be4763862f3908430513287 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 6574f9bcdc026..c688dee96503f 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -151,11 +151,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -174,6 +178,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-6.18/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-6.18/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..7af544dca1 --- /dev/null +++ b/queue-6.18/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From f81cdd2bdc6da7ad7458a133742388f9f9338810 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index e7f1134453ef4..4a3d7b405132e 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -135,9 +135,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-6.18/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-6.18/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..05585b5e2e --- /dev/null +++ b/queue-6.18/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 5d54f7ca93fa185ed1ff35122a5aa4f07f412396 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index f261dd48973fe..768f741f59afe 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -909,8 +909,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -924,17 +924,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2633,7 +2627,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 0c1d086e96cb3..b67426c2189b2 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1385,9 +1385,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1414,10 +1414,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-6.18/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-6.18/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..f452e5026b --- /dev/null +++ b/queue-6.18/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From 3373cc5d89115a6bd204dc84559711e31c3c7a39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-6.18/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..9aaf8e9c7b --- /dev/null +++ b/queue-6.18/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From 75b6ad168c81641da95097dde1a2e8e02af659a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index cfc2daa3fc7f3..227fb5dc39e27 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-6.18/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..8be78e988d --- /dev/null +++ b/queue-6.18/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From 83ac9d2f13b308d7efd0b5653b274e056d94075e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 4ab5ef71d96db..17af0ff4ea7ab 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-6.18/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..8662548600 --- /dev/null +++ b/queue-6.18/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From 85836f80ee1413f80ba0857382d39d1791209312 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index bfcb9cd335bff..27dd35224e629 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -647,15 +647,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-6.18/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch b/queue-6.18/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch new file mode 100644 index 0000000000..6103035641 --- /dev/null +++ b/queue-6.18/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch @@ -0,0 +1,189 @@ +From 28b60461262e8819ffd01b8591d239326587e39c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:01 +0100 +Subject: netfilter: nft_set_rbtree: revisit array resize logic + +From: Pablo Neira Ayuso + +[ Upstream commit fafdd92b9e30fe057740c5bb5cd4f92ecea9bf26 ] + +Chris Arges reports high memory consumption with thousands of +containers, this patch revisits the array allocation logic. + +For anonymous sets, start by 16 slots (which takes 256 bytes on x86_64). +Expand it by x2 until threshold of 512 slots is reached, over that +threshold, expand it by x1.5. + +For non-anonymous set, start by 1024 slots in the array (which takes 16 +Kbytes initially on x86_64). Expand it by x1.5. + +Use set->ndeact to subtract deactivated elements when calculating the +number of the slots in the array, otherwise the array size array gets +increased artifically. Add special case shrink logic to deal with flush +set too. + +The shrink logic is skipped by anonymous sets. + +Use check_add_overflow() to calculate the new array size. + +Add a WARN_ON_ONCE check to make sure elements fit into the new array +size. + +Reported-by: Chris Arges +Fixes: 7e43e0a1141d ("netfilter: nft_set_rbtree: translate rbtree to array for binary search") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_set_rbtree.c | 92 +++++++++++++++++++++++++++------- + 1 file changed, 75 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 5d91b7d08d33a..154bf2772e27d 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -572,14 +572,12 @@ static struct nft_array *nft_array_alloc(u32 max_intervals) + return array; + } + +-#define NFT_ARRAY_EXTRA_SIZE 10240 +- + /* Similar to nft_rbtree_{u,k}size to hide details to userspace, but consider + * packed representation coming from userspace for anonymous sets too. + */ + static u32 nft_array_elems(const struct nft_set *set) + { +- u32 nelems = atomic_read(&set->nelems); ++ u32 nelems = atomic_read(&set->nelems) - set->ndeact; + + /* Adjacent intervals are represented with a single start element in + * anonymous sets, use the current element counter as is. +@@ -595,27 +593,87 @@ static u32 nft_array_elems(const struct nft_set *set) + return (nelems / 2) + 2; + } + +-static int nft_array_may_resize(const struct nft_set *set) ++#define NFT_ARRAY_INITIAL_SIZE 1024 ++#define NFT_ARRAY_INITIAL_ANON_SIZE 16 ++#define NFT_ARRAY_INITIAL_ANON_THRESH (8192U / sizeof(struct nft_array_interval)) ++ ++static int nft_array_may_resize(const struct nft_set *set, bool flush) + { +- u32 nelems = nft_array_elems(set), new_max_intervals; ++ u32 initial_intervals, max_intervals, new_max_intervals, delta; ++ u32 shrinked_max_intervals, nelems = nft_array_elems(set); + struct nft_rbtree *priv = nft_set_priv(set); + struct nft_array *array; + +- if (!priv->array_next) { +- array = nft_array_alloc(nelems + NFT_ARRAY_EXTRA_SIZE); +- if (!array) +- return -ENOMEM; ++ if (nft_set_is_anonymous(set)) ++ initial_intervals = NFT_ARRAY_INITIAL_ANON_SIZE; ++ else ++ initial_intervals = NFT_ARRAY_INITIAL_SIZE; ++ ++ if (priv->array_next) { ++ max_intervals = priv->array_next->max_intervals; ++ new_max_intervals = priv->array_next->max_intervals; ++ } else { ++ if (priv->array) { ++ max_intervals = priv->array->max_intervals; ++ new_max_intervals = priv->array->max_intervals; ++ } else { ++ max_intervals = 0; ++ new_max_intervals = initial_intervals; ++ } ++ } + +- priv->array_next = array; ++ if (nft_set_is_anonymous(set)) ++ goto maybe_grow; ++ ++ if (flush) { ++ /* Set flush just started, nelems still report elements.*/ ++ nelems = 0; ++ new_max_intervals = NFT_ARRAY_INITIAL_SIZE; ++ goto realloc_array; + } + +- if (nelems < priv->array_next->max_intervals) +- return 0; ++ if (check_add_overflow(new_max_intervals, new_max_intervals, ++ &shrinked_max_intervals)) ++ return -EOVERFLOW; ++ ++ shrinked_max_intervals = DIV_ROUND_UP(shrinked_max_intervals, 3); + +- new_max_intervals = priv->array_next->max_intervals + NFT_ARRAY_EXTRA_SIZE; +- if (nft_array_intervals_alloc(priv->array_next, new_max_intervals) < 0) ++ if (shrinked_max_intervals > NFT_ARRAY_INITIAL_SIZE && ++ nelems < shrinked_max_intervals) { ++ new_max_intervals = shrinked_max_intervals; ++ goto realloc_array; ++ } ++maybe_grow: ++ if (nelems > new_max_intervals) { ++ if (nft_set_is_anonymous(set) && ++ new_max_intervals < NFT_ARRAY_INITIAL_ANON_THRESH) { ++ new_max_intervals <<= 1; ++ } else { ++ delta = new_max_intervals >> 1; ++ if (check_add_overflow(new_max_intervals, delta, ++ &new_max_intervals)) ++ return -EOVERFLOW; ++ } ++ } ++ ++realloc_array: ++ if (WARN_ON_ONCE(nelems > new_max_intervals)) + return -ENOMEM; + ++ if (priv->array_next) { ++ if (max_intervals == new_max_intervals) ++ return 0; ++ ++ if (nft_array_intervals_alloc(priv->array_next, new_max_intervals) < 0) ++ return -ENOMEM; ++ } else { ++ array = nft_array_alloc(new_max_intervals); ++ if (!array) ++ return -ENOMEM; ++ ++ priv->array_next = array; ++ } ++ + return 0; + } + +@@ -630,7 +688,7 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, + + nft_rbtree_maybe_reset_start_cookie(priv, tstamp); + +- if (nft_array_may_resize(set) < 0) ++ if (nft_array_may_resize(set, false) < 0) + return -ENOMEM; + + do { +@@ -741,7 +799,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, + nft_rbtree_interval_null(set, this)) + priv->start_rbe_cookie = 0; + +- if (nft_array_may_resize(set) < 0) ++ if (nft_array_may_resize(set, false) < 0) + return NULL; + + while (parent != NULL) { +@@ -811,7 +869,7 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, + + switch (iter->type) { + case NFT_ITER_UPDATE_CLONE: +- if (nft_array_may_resize(set) < 0) { ++ if (nft_array_may_resize(set, true) < 0) { + iter->err = -ENOMEM; + break; + } +-- +2.51.0 + diff --git a/queue-6.18/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-6.18/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..5ca54e351f --- /dev/null +++ b/queue-6.18/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From 8b1fb90dc83269b3d05d08f3297f0e55a02585a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index d334b7aa8c172..25ba4cbb00e1e 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -579,8 +579,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -592,13 +591,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + timer_delete_sync(&ndev->cmd_timer); +@@ -613,6 +612,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.18/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch b/queue-6.18/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch new file mode 100644 index 0000000000..23a35f07ea --- /dev/null +++ b/queue-6.18/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch @@ -0,0 +1,50 @@ +From d027b86ee606ea93d1b55704e0a012c9f05a3929 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 07:42:41 +0000 +Subject: openvswitch: defer tunnel netdev_put to RCU release + +From: Yang Yang + +[ Upstream commit 6931d21f87bc6d657f145798fad0bf077b82486c ] + +ovs_netdev_tunnel_destroy() may run after NETDEV_UNREGISTER already +detached the device. Dropping the netdev reference in destroy can race +with concurrent readers that still observe vport->dev. + +Do not release vport->dev in ovs_netdev_tunnel_destroy(). Instead, let +vport_netdev_free() drop the reference from the RCU callback, matching +the non-tunnel destroy path and avoiding additional synchronization +under RTNL. + +Fixes: a9020fde67a6 ("openvswitch: Move tunnel destroy function to oppenvswitch module.") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319074241.3405262-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index c688dee96503f..12055af832dc0 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -196,8 +196,6 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + */ + if (vport->dev->reg_state == NETREG_REGISTERED) + rtnl_delete_link(vport->dev, 0, NULL); +- netdev_put(vport->dev, &vport->dev_tracker); +- vport->dev = NULL; + rtnl_unlock(); + + call_rcu(&vport->rcu, vport_netdev_free); +-- +2.51.0 + diff --git a/queue-6.18/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-6.18/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..b0cb0dcaaf --- /dev/null +++ b/queue-6.18/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From e75fcff7c56c14548d45758ce66714e024de90b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 2d536901309ea..2dc4a6c2aecec 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2953,6 +2953,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-6.18/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-6.18/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..bd4bfbc01a --- /dev/null +++ b/queue-6.18/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From 11964299eaaab4d6e0176c42dc4c415a85372c13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index d6a46fe0cda89..3f518dce6d23f 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1135,9 +1135,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-6.18/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch b/queue-6.18/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch new file mode 100644 index 0000000000..dfd4b352cd --- /dev/null +++ b/queue-6.18/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch @@ -0,0 +1,42 @@ +From 34c727c83f11112ba2f3102be2b2b228ab01c151 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Feb 2026 12:58:09 -0800 +Subject: pinctrl: renesas: rza1: Normalize return value of gpio_get() + +From: Dmitry Torokhov + +[ Upstream commit fb22bb9701d48c4b0e81fe204c2f96a37a520568 ] + +The GPIO .get() callback is expected to return 0 or 1 (or a negative +error code). Ensure that the value returned by rza1_gpio_get() is +normalized to the [0, 1] range. + +Fixes: 86ef402d805d606a ("gpiolib: sanitize the return value of gpio_chip::get()") +Signed-off-by: Dmitry Torokhov +Reviewed-by: Andy Shevchenko +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Linus Walleij +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/aZYnyl-Nf4S1U2yj@google.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rza1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rza1.c b/drivers/pinctrl/renesas/pinctrl-rza1.c +index f24e5915cbe4b..2677ee7035fce 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rza1.c ++++ b/drivers/pinctrl/renesas/pinctrl-rza1.c +@@ -590,7 +590,7 @@ static inline unsigned int rza1_get_bit(struct rza1_port *port, + { + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id); + +- return ioread16(mem) & BIT(bit); ++ return !!(ioread16(mem) & BIT(bit)); + } + + /** +-- +2.51.0 + diff --git a/queue-6.18/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch b/queue-6.18/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch new file mode 100644 index 0000000000..938b08bccb --- /dev/null +++ b/queue-6.18/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch @@ -0,0 +1,44 @@ +From 310e591cef9b95b5af87ab2c07fcd66beb573172 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jan 2026 00:35:47 +0800 +Subject: pinctrl: renesas: rzt2h: Fix device node leak in + rzt2h_gpio_register() + +From: Felix Gu + +[ Upstream commit e825c79ef914bd55cf7c2476ddcfb2738eb689c3 ] + +When calling of_parse_phandle_with_fixed_args(), the caller is +responsible for calling of_node_put() to release the device node +reference. + +In rzt2h_gpio_register(), the driver fails to call of_node_put() to +release the reference in of_args.np, which causes a memory leak. + +Add the missing of_node_put() call to fix the leak. + +Fixes: 34d4d093077a ("pinctrl: renesas: Add support for RZ/T2H") +Signed-off-by: Felix Gu +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260127-rzt2h-v1-1-86472e7421b8@gmail.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzt2h.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c +index 3161b2469c362..595ad5c83aa00 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c +@@ -648,6 +648,7 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) + if (ret) + return dev_err_probe(dev, ret, "Unable to parse gpio-ranges\n"); + ++ of_node_put(of_args.np); + if (of_args.args[0] != 0 || of_args.args[1] != 0 || + of_args.args[2] != pctrl->data->n_port_pins) + return dev_err_probe(dev, -EINVAL, +-- +2.51.0 + diff --git a/queue-6.18/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch b/queue-6.18/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch new file mode 100644 index 0000000000..a29df52c75 --- /dev/null +++ b/queue-6.18/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch @@ -0,0 +1,36 @@ +From 970710fa3cf176b437a9f256e38f12f2e7fdad7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:06:54 +0100 +Subject: pinctrl: stm32: fix HDP driver dependency on GPIO_GENERIC + +From: Amelie Delaunay + +[ Upstream commit c8cfeb4b9dda2cdfce79519aee4aaff16310a7b6 ] + +The HDP driver uses the generic GPIO chip API, but this configuration +may not be enabled. +Ensure it is enabled by selecting the appropriate option. + +Fixes: 4bcff9c05b9d ("pinctrl: stm32: use new generic GPIO chip API") +Signed-off-by: Amelie Delaunay +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/stm32/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig +index 5f67e1ee66dd9..d6a1715230121 100644 +--- a/drivers/pinctrl/stm32/Kconfig ++++ b/drivers/pinctrl/stm32/Kconfig +@@ -65,6 +65,7 @@ config PINCTRL_STM32_HDP + select PINMUX + select GENERIC_PINCONF + select GPIOLIB ++ select GPIO_GENERIC + help + The Hardware Debug Port allows the observation of internal signals. + It uses configurable multiplexer to route signals in a dedicated observation register. +-- +2.51.0 + diff --git a/queue-6.18/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-6.18/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..835b55bb03 --- /dev/null +++ b/queue-6.18/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From 254e90e36ee7a7262db8de147d481c019590fe1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index fa7b3bda688a6..bee271a4fda1a 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-6.18/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch b/queue-6.18/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch new file mode 100644 index 0000000000..2b122e4d1b --- /dev/null +++ b/queue-6.18/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch @@ -0,0 +1,62 @@ +From 2deb40966227005a2a060d05ff2361dd86df70cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Feb 2026 19:16:24 -0400 +Subject: platform/x86: intel-hid: disable wakeup_mode during hibernation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David McFarland + +[ Upstream commit e02ea3ae8ee40d5835a845884c7b161a27c10bcb ] + +Add a freeze handler which clears wakeup_mode. This fixes aborted hibernation on +Dell Precision 3880. + + Wakeup event detected during hibernation, rolling back + +This system sends power button events during hibernation, even when triggered by +software. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218634 +Fixes: 0c4cae1bc00d ("PM: hibernate: Avoid missing wakeup events during hibernation") +Signed-off-by: David McFarland +Link: https://patch.msgid.link/20260205231629.1336348-1-corngood@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/hid.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index f2b309f6e458a..c5e80887d0cb0 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -432,6 +432,14 @@ static int intel_hid_pl_suspend_handler(struct device *device) + return 0; + } + ++static int intel_hid_pl_freeze_handler(struct device *device) ++{ ++ struct intel_hid_priv *priv = dev_get_drvdata(device); ++ ++ priv->wakeup_mode = false; ++ return intel_hid_pl_suspend_handler(device); ++} ++ + static int intel_hid_pl_resume_handler(struct device *device) + { + intel_hid_pm_complete(device); +@@ -446,7 +454,7 @@ static int intel_hid_pl_resume_handler(struct device *device) + static const struct dev_pm_ops intel_hid_pl_pm_ops = { + .prepare = intel_hid_pm_prepare, + .complete = intel_hid_pm_complete, +- .freeze = intel_hid_pl_suspend_handler, ++ .freeze = intel_hid_pl_freeze_handler, + .thaw = intel_hid_pl_resume_handler, + .restore = intel_hid_pl_resume_handler, + .suspend = intel_hid_pl_suspend_handler, +-- +2.51.0 + diff --git a/queue-6.18/platform-x86-isst-check-hwp-support-before-msr-acces.patch b/queue-6.18/platform-x86-isst-check-hwp-support-before-msr-acces.patch new file mode 100644 index 0000000000..fce129178d --- /dev/null +++ b/queue-6.18/platform-x86-isst-check-hwp-support-before-msr-acces.patch @@ -0,0 +1,66 @@ +From 7dd5c97d9d07b8028a99720c6290cbe3eb759613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Mar 2026 02:46:35 -0500 +Subject: platform/x86: ISST: Check HWP support before MSR access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Li RongQing + +[ Upstream commit 9f11d9b15efb5f77e810b6dfbeb01b4650a79eae ] + +On some systems, HWP can be explicitly disabled in the BIOS settings +When HWP is disabled by firmware, the HWP CPUID bit is not set, and +attempting to read MSR_PM_ENABLE will result in a General Protection +(GP) fault. + + unchecked MSR access error: RDMSR from 0x770 at rIP: 0xffffffffc33db92e (disable_dynamic_sst_features+0xe/0x50 [isst_tpmi_core]) + Call Trace: + + ? ex_handler_msr+0xf6/0x150 + ? fixup_exception+0x1ad/0x340 + ? gp_try_fixup_and_notify+0x1e/0xb0 + ? exc_general_protection+0xc9/0x390 + ? terminate_walk+0x64/0x100 + ? asm_exc_general_protection+0x22/0x30 + ? disable_dynamic_sst_features+0xe/0x50 [isst_tpmi_core] + isst_if_def_ioctl+0xece/0x1050 [isst_tpmi_core] + ? ioctl_has_perm.constprop.42+0xe0/0x130 + isst_if_def_ioctl+0x10d/0x1a0 [isst_if_common] + __se_sys_ioctl+0x86/0xc0 + do_syscall_64+0x8a/0x100 + entry_SYSCALL_64_after_hwframe+0x78/0xe2 + RIP: 0033:0x7f36eaef54a7 + +Add a check for X86_FEATURE_HWP before accessing the MSR. If HWP is +not available, return true safely. + +Fixes: 12a7d2cb811d ("platform/x86: ISST: Add SST-CP support via TPMI") +Signed-off-by: Li RongQing +Acked-by: Srinivas Pandruvada +Link: https://patch.msgid.link/20260303074635.2218-1-lirongqing@baidu.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +index 13b11c3a2ec4e..e657b88bfd36e 100644 +--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c ++++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +@@ -558,6 +558,9 @@ static bool disable_dynamic_sst_features(void) + { + u64 value; + ++ if (!static_cpu_has(X86_FEATURE_HWP)) ++ return true; ++ + rdmsrq(MSR_PM_ENABLE, value); + return !(value & 0x1); + } +-- +2.51.0 + diff --git a/queue-6.18/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch b/queue-6.18/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch new file mode 100644 index 0000000000..bd5ab4c5e6 --- /dev/null +++ b/queue-6.18/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch @@ -0,0 +1,59 @@ +From 0dedb270bae2dd36d497de46edea537f2743515a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 14:06:34 -0700 +Subject: platform/x86: lenovo: wmi-gamezone: Drop gz_chain_head +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nathan Chancellor + +[ Upstream commit 5a3955f3602950d1888df743a5b1889e43b5cb60 ] + +The gz_chain_head variable has been unused since the driver's initial +addition to the tree. Its use was eliminated between v3 and v4 during +development but due to the reference of gz_chain_head's wait_list +member, the compiler could not warn that it was unused. + +After a (tip) commit ("locking/rwsem: Remove the list_head from struct +rw_semaphore"), which removed a reference to the variable passed to +__RWSEM_INITIALIZER(), certain configurations show an unused variable +warning from the Lenovo wmi-gamezone driver: + + drivers/platform/x86/lenovo/wmi-gamezone.c:34:31: warning: 'gz_chain_head' defined but not used [-Wunused-variable] + 34 | static BLOCKING_NOTIFIER_HEAD(gz_chain_head); + | ^~~~~~~~~~~~~ + include/linux/notifier.h:119:39: note: in definition of macro 'BLOCKING_NOTIFIER_HEAD' + 119 | struct blocking_notifier_head name = \ + | ^~~~ + +Remove the variable to prevent the warning from showing up. + +Fixes: 22024ac5366f ("platform/x86: Add Lenovo Gamezone WMI Driver") +Signed-off-by: Nathan Chancellor +Reviewed-by: Mark Pearson +Link: https://patch.msgid.link/20260313-lenovo-wmi-gamezone-remove-gz_chain_head-v1-1-ce5231f0c6fa@kernel.org +[ij: reorganized the changelog] +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/lenovo/wmi-gamezone.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/platform/x86/lenovo/wmi-gamezone.c b/drivers/platform/x86/lenovo/wmi-gamezone.c +index b26806b37d960..baf1238b4d1d9 100644 +--- a/drivers/platform/x86/lenovo/wmi-gamezone.c ++++ b/drivers/platform/x86/lenovo/wmi-gamezone.c +@@ -31,8 +31,6 @@ + #define LWMI_GZ_METHOD_ID_SMARTFAN_SET 44 + #define LWMI_GZ_METHOD_ID_SMARTFAN_GET 45 + +-static BLOCKING_NOTIFIER_HEAD(gz_chain_head); +- + struct lwmi_gz_priv { + enum thermal_mode current_mode; + struct notifier_block event_nb; +-- +2.51.0 + diff --git a/queue-6.18/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-6.18/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..27a6cbbaad --- /dev/null +++ b/queue-6.18/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From e90882f8042c5c067ec85d712ad40d0dd1476208 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 1960b59961cb8..b389210d518ef 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -707,11 +707,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-6.18/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch b/queue-6.18/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch new file mode 100644 index 0000000000..96c2ca76c9 --- /dev/null +++ b/queue-6.18/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch @@ -0,0 +1,59 @@ +From f5e205861a53bac780ad0b6058e88884c0851741 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:52 +0100 +Subject: rtnetlink: count IFLA_PARENT_DEV_{NAME,BUS_NAME} in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit 52501989c76206462d9b11a8485beef40ef41821 ] + +Commit 00e77ed8e64d ("rtnetlink: add IFLA_PARENT_[DEV|DEV_BUS]_NAME") +added those attributes to rtnl_fill_ifinfo, but forgot to extend +if_nlmsg_size. + +Fixes: 00e77ed8e64d ("rtnetlink: add IFLA_PARENT_[DEV|DEV_BUS]_NAME") +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/0b849da95562af45487080528d60f578636aba5c.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 576d5ec3bb364..1960b59961cb8 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1267,6 +1267,21 @@ static size_t rtnl_dpll_pin_size(const struct net_device *dev) + return size; + } + ++static size_t rtnl_dev_parent_size(const struct net_device *dev) ++{ ++ size_t size = 0; ++ ++ /* IFLA_PARENT_DEV_NAME */ ++ if (dev->dev.parent) ++ size += nla_total_size(strlen(dev_name(dev->dev.parent)) + 1); ++ ++ /* IFLA_PARENT_DEV_BUS_NAME */ ++ if (dev->dev.parent && dev->dev.parent->bus) ++ size += nla_total_size(strlen(dev->dev.parent->bus->name) + 1); ++ ++ return size; ++} ++ + static noinline size_t if_nlmsg_size(const struct net_device *dev, + u32 ext_filter_mask) + { +@@ -1328,6 +1343,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + + nla_total_size(8) /* IFLA_MAX_PACING_OFFLOAD_HORIZON */ + + nla_total_size(2) /* IFLA_HEADROOM */ + + nla_total_size(2) /* IFLA_TAILROOM */ ++ + rtnl_dev_parent_size(dev) + + 0; + } + +-- +2.51.0 + diff --git a/queue-6.18/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch b/queue-6.18/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch new file mode 100644 index 0000000000..87eb56281d --- /dev/null +++ b/queue-6.18/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch @@ -0,0 +1,40 @@ +From 08dc592ce4c2017bdcb04c599b447b948dbaf613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 16:19:43 +0100 +Subject: rtnetlink: fix leak of SRCU struct in rtnl_link_register + +From: Sabrina Dubroca + +[ Upstream commit 09474055f2619be9445ba4245e4013741ed01a5e ] + +Commit 6b57ff21a310 ("rtnetlink: Protect link_ops by mutex.") swapped +the EEXIST check with the init_srcu_struct, but didn't add cleanup of +the SRCU struct we just allocated in case of error. + +Fixes: 6b57ff21a310 ("rtnetlink: Protect link_ops by mutex.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/e77fe499f9a58c547b33b5212b3596dad417cec6.1774025341.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index b389210d518ef..f3b22d5526fe6 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -629,6 +629,9 @@ int rtnl_link_register(struct rtnl_link_ops *ops) + unlock: + mutex_unlock(&link_ops_mutex); + ++ if (err) ++ cleanup_srcu_struct(&ops->srcu); ++ + return err; + } + EXPORT_SYMBOL_GPL(rtnl_link_register); +-- +2.51.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 343f9a8f1f..2fd48fd242 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -65,3 +65,68 @@ usb-core-new-quirk-to-handle-devices-with-zero-confi.patch spi-intel-pci-add-support-for-nova-lake-mobile-spi-f.patch alsa-hda-realtek-add-quirk-for-asus-um6702rc.patch i3c-master-dw-i3c-fix-missing-of_node-for-virtual-i2.patch +xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch +xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch +xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch +pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch +xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch +xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch +af_key-validate-families-in-pfkey_send_migrate.patch +dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch +erofs-set-fileio-bio-failed-in-short-read-case.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch +bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +net-bcmasp-streamline-early-exit-in-probe.patch +net-bcmasp-fix-double-free-of-wol-irq.patch +net-bcmasp-fix-double-disable-of-clk.patch +platform-x86-isst-check-hwp-support-before-msr-acces.patch +platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch +ice-fix-inverted-ready-check-for-vf-representors.patch +ice-use-ice_update_eth_stats-for-representor-stats.patch +iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch +ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch +ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch +udp-fix-wildcard-bind-conflict-check-when-using-hash.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch +virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch +team-fix-header_ops-type-confusion-with-non-ethernet.patch +net-lan743x-fix-duplex-configuration-in-mac_link_up.patch +rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch +bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch +bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch +bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +tls-purge-async_hold-in-tls_decrypt_async_wait.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nft_set_rbtree-revisit-array-resize-logic.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-6.18/team-fix-header_ops-type-confusion-with-non-ethernet.patch b/queue-6.18/team-fix-header_ops-type-confusion-with-non-ethernet.patch new file mode 100644 index 0000000000..ca8843976c --- /dev/null +++ b/queue-6.18/team-fix-header_ops-type-confusion-with-non-ethernet.patch @@ -0,0 +1,132 @@ +From 4ddf414cc5d18b94575697410d8f7f61530a800b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 15:21:26 +0800 +Subject: team: fix header_ops type confusion with non-Ethernet ports + +From: Jiayuan Chen + +[ Upstream commit 425000dbf17373a4ab8be9428f5dc055ef870a56 ] + +Similar to commit 950803f72547 ("bonding: fix type confusion in +bond_setup_by_slave()") team has the same class of header_ops type +confusion. + +For non-Ethernet ports, team_setup_by_port() copies port_dev->header_ops +directly. When the team device later calls dev_hard_header() or +dev_parse_header(), these callbacks can run with the team net_device +instead of the real lower device, so netdev_priv(dev) is interpreted as +the wrong private type and can crash. + +The syzbot report shows a crash in bond_header_create(), but the root +cause is in team: the topology is gre -> bond -> team, and team calls +the inherited header_ops with its own net_device instead of the lower +device, so bond_header_create() receives a team device and interprets +netdev_priv() as bonding private data, causing a type confusion crash. + +Fix this by introducing team header_ops wrappers for create/parse, +selecting a team port under RCU, and calling the lower device callbacks +with port->dev, so each callback always sees the correct net_device +context. + +Also pass the selected lower device to the lower parse callback, so +recursion is bounded in stacked non-Ethernet topologies and parse +callbacks always run with the correct device context. + +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Reported-by: syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69b46af7.050a0220.36eb34.000e.GAE@google.com/T/ +Cc: Jiayuan Chen +Signed-off-by: Jiayuan Chen +Link: https://patch.msgid.link/20260320072139.134249-2-jiayuan.chen@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/team/team_core.c | 65 +++++++++++++++++++++++++++++++++++- + 1 file changed, 64 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c +index 6ec6708c52e2d..a98f5e5061544 100644 +--- a/drivers/net/team/team_core.c ++++ b/drivers/net/team/team_core.c +@@ -2059,6 +2059,68 @@ static const struct ethtool_ops team_ethtool_ops = { + * rt netlink interface + ***********************/ + ++/* For tx path we need a linkup && enabled port and for parse any port ++ * suffices. ++ */ ++static struct team_port *team_header_port_get_rcu(struct team *team, ++ bool txable) ++{ ++ struct team_port *port; ++ ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ if (!txable || team_port_txable(port)) ++ return port; ++ } ++ ++ return NULL; ++} ++ ++static int team_header_create(struct sk_buff *skb, struct net_device *team_dev, ++ unsigned short type, const void *daddr, ++ const void *saddr, unsigned int len) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, true); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->create) ++ ret = port_ops->create(skb, port->dev, ++ type, daddr, saddr, len); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static int team_header_parse(const struct sk_buff *skb, ++ const struct net_device *team_dev, ++ unsigned char *haddr) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, false); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->parse) ++ ret = port_ops->parse(skb, port->dev, haddr); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static const struct header_ops team_header_ops = { ++ .create = team_header_create, ++ .parse = team_header_parse, ++}; ++ + static void team_setup_by_port(struct net_device *dev, + struct net_device *port_dev) + { +@@ -2067,7 +2129,8 @@ static void team_setup_by_port(struct net_device *dev, + if (port_dev->type == ARPHRD_ETHER) + dev->header_ops = team->header_ops_cache; + else +- dev->header_ops = port_dev->header_ops; ++ dev->header_ops = port_dev->header_ops ? ++ &team_header_ops : NULL; + dev->type = port_dev->type; + dev->hard_header_len = port_dev->hard_header_len; + dev->needed_headroom = port_dev->needed_headroom; +-- +2.51.0 + diff --git a/queue-6.18/tls-purge-async_hold-in-tls_decrypt_async_wait.patch b/queue-6.18/tls-purge-async_hold-in-tls_decrypt_async_wait.patch new file mode 100644 index 0000000000..9a3e546cd5 --- /dev/null +++ b/queue-6.18/tls-purge-async_hold-in-tls_decrypt_async_wait.patch @@ -0,0 +1,66 @@ +From 9ad0b2e8f0476452ce64f04bc74d0766a0514f63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 08:53:23 -0400 +Subject: tls: Purge async_hold in tls_decrypt_async_wait() + +From: Chuck Lever + +[ Upstream commit 84a8335d8300576f1b377ae24abca1d9f197807f ] + +The async_hold queue pins encrypted input skbs while +the AEAD engine references their scatterlist data. Once +tls_decrypt_async_wait() returns, every AEAD operation +has completed and the engine no longer references those +skbs, so they can be freed unconditionally. + +A subsequent patch adds batch async decryption to +tls_sw_read_sock(), introducing a new call site that +must drain pending AEAD operations and release held +skbs. Move __skb_queue_purge(&ctx->async_hold) into +tls_decrypt_async_wait() so the purge is centralized +and every caller -- recvmsg's drain path, the -EBUSY +fallback in tls_do_decryption(), and the new read_sock +batch path -- releases held skbs on synchronization +without each site managing the purge independently. + +This fixes a leak when tls_strp_msg_hold() fails part-way through, +after having added some cloned skbs to the async_hold +queue. tls_decrypt_sg() will then call tls_decrypt_async_wait() to +process all pending decrypts, and drop back to synchronous mode, but +tls_sw_recvmsg() only flushes the async_hold queue when one record has +been processed in "fully-async" mode, which may not be the case here. + +Signed-off-by: Chuck Lever +Reported-by: Yiming Qian +Fixes: b8a6ff84abbc ("tls: wait for pending async decryptions if tls_strp_msg_hold fails") +Link: https://patch.msgid.link/20260324-tls-read-sock-v5-1-5408befe5774@oracle.com +[pabeni@redhat.com: added leak comment] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_sw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index c6a708ee21dc8..eecf1146c34f2 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -246,6 +246,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + atomic_inc(&ctx->decrypt_pending); + ++ __skb_queue_purge(&ctx->async_hold); + return ctx->async_wait.err; + } + +@@ -2225,7 +2226,6 @@ int tls_sw_recvmsg(struct sock *sk, + + /* Wait for all previously submitted records to be decrypted */ + ret = tls_decrypt_async_wait(ctx); +- __skb_queue_purge(&ctx->async_hold); + + if (ret) { + if (err >= 0 || err == -EINPROGRESS) +-- +2.51.0 + diff --git a/queue-6.18/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch b/queue-6.18/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch new file mode 100644 index 0000000000..54ff8249b9 --- /dev/null +++ b/queue-6.18/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch @@ -0,0 +1,160 @@ +From 490afea4db7216a0f1ea14203b8d4aaabbf14754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 11:18:17 -0700 +Subject: udp: Fix wildcard bind conflict check when using hash2 + +From: Martin KaFai Lau + +[ Upstream commit e537dd15d0d4ad989d56a1021290f0c674dd8b28 ] + +When binding a udp_sock to a local address and port, UDP uses +two hashes (udptable->hash and udptable->hash2) for collision +detection. The current code switches to "hash2" when +hslot->count > 10. + +"hash2" is keyed by local address and local port. +"hash" is keyed by local port only. + +The issue can be shown in the following bind sequence (pseudo code): + +bind(fd1, "[fd00::1]:8888") +bind(fd2, "[fd00::2]:8888") +bind(fd3, "[fd00::3]:8888") +bind(fd4, "[fd00::4]:8888") +bind(fd5, "[fd00::5]:8888") +bind(fd6, "[fd00::6]:8888") +bind(fd7, "[fd00::7]:8888") +bind(fd8, "[fd00::8]:8888") +bind(fd9, "[fd00::9]:8888") +bind(fd10, "[fd00::10]:8888") + +/* Correctly return -EADDRINUSE because "hash" is used + * instead of "hash2". udp_lib_lport_inuse() detects the + * conflict. + */ +bind(fail_fd, "[::]:8888") + +/* After one more socket is bound to "[fd00::11]:8888", + * hslot->count exceeds 10 and "hash2" is used instead. + */ +bind(fd11, "[fd00::11]:8888") +bind(fail_fd, "[::]:8888") /* succeeds unexpectedly */ + +The same issue applies to the IPv4 wildcard address "0.0.0.0" +and the IPv4-mapped wildcard address "::ffff:0.0.0.0". For +example, if there are existing sockets bound to +"192.168.1.[1-11]:8888", then binding "0.0.0.0:8888" or +"[::ffff:0.0.0.0]:8888" can also miss the conflict when +hslot->count > 10. + +TCP inet_csk_get_port() already has the correct check in +inet_use_bhash2_on_bind(). Rename it to +inet_use_hash2_on_bind() and move it to inet_hashtables.h +so udp.c can reuse it in this fix. + +Fixes: 30fff9231fad ("udp: bind() optimisation") +Reported-by: Andrew Onyshchuk +Signed-off-by: Martin KaFai Lau +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260319181817.1901357-1-martin.lau@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_hashtables.h | 14 ++++++++++++++ + net/ipv4/inet_connection_sock.c | 20 +++----------------- + net/ipv4/udp.c | 2 +- + 3 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 5a979dcab5383..6d936e9f2fd32 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -264,6 +264,20 @@ inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk, + return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)]; + } + ++static inline bool inet_use_hash2_on_bind(const struct sock *sk) ++{ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) { ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ return false; ++ ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ return true; ++ } ++#endif ++ return sk->sk_rcv_saddr != htonl(INADDR_ANY); ++} ++ + struct inet_bind_hashbucket * + inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port); + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index cdd1e12aac8c0..7a2f116106e96 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -153,20 +153,6 @@ bool inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) + } + EXPORT_SYMBOL(inet_sk_get_local_port_range); + +-static bool inet_use_bhash2_on_bind(const struct sock *sk) +-{ +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) { +- if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) +- return false; +- +- if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) +- return true; +- } +-#endif +- return sk->sk_rcv_saddr != htonl(INADDR_ANY); +-} +- + static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, + kuid_t uid, bool relax, + bool reuseport_cb_ok, bool reuseport_ok) +@@ -258,7 +244,7 @@ static int inet_csk_bind_conflict(const struct sock *sk, + * checks separately because their spinlocks have to be acquired/released + * independently of each other, to prevent possible deadlocks + */ +- if (inet_use_bhash2_on_bind(sk)) ++ if (inet_use_hash2_on_bind(sk)) + return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, + reuseport_cb_ok, reuseport_ok); + +@@ -375,7 +361,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); +- if (inet_use_bhash2_on_bind(sk)) { ++ if (inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false)) + goto next_port; + } +@@ -561,7 +547,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + check_bind_conflict = false; + } + +- if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) { ++ if (check_bind_conflict && inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true)) + goto fail_unlock; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 024cb4f5978c1..de0deded74f0a 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -287,7 +287,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + } else { + hslot = udp_hashslot(udptable, net, snum); + spin_lock_bh(&hslot->lock); +- if (hslot->count > 10) { ++ if (inet_use_hash2_on_bind(sk) && hslot->count > 10) { + int exist; + unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; + +-- +2.51.0 + diff --git a/queue-6.18/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch b/queue-6.18/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch new file mode 100644 index 0000000000..1cbfd29dec --- /dev/null +++ b/queue-6.18/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch @@ -0,0 +1,80 @@ +From 112c20df3fd6053e93aae5b8d5937b0b16fcdfa5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 10:18:18 +0800 +Subject: virtio-net: correct hdr_len handling for tunnel gso + +From: Xuan Zhuo + +[ Upstream commit 6c860dc02a8e60b438e26940227dfa641fcdb66a ] + +The commit a2fb4bc4e2a6a03 ("net: implement virtio helpers to handle UDP +GSO tunneling.") introduces support for the UDP GSO tunnel feature in +virtio-net. + +The virtio spec says: + + If the \field{gso_type} has the VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 bit or + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6 bit set, \field{hdr_len} accounts for + all the headers up to and including the inner transport. + +The commit did not update the hdr_len to include the inner transport. + +I observed that the "hdr_len" is 116 for this packet: + + 17:36:18.241105 52:55:00:d1:27:0a > 2e:2c:df:46:a9:e1, ethertype IPv4 (0x0800), length 2912: (tos 0x0, ttl 64, id 45197, offset 0, flags [none], proto UDP (17), length 2898) + 192.168.122.100.50613 > 192.168.122.1.4789: [bad udp cksum 0x8106 -> 0x26a0!] VXLAN, flags [I] (0x08), vni 1 + fa:c3:ba:82:05:ee > ce:85:0c:31:77:e5, ethertype IPv4 (0x0800), length 2862: (tos 0x0, ttl 64, id 14678, offset 0, flags [DF], proto TCP (6), length 2848) + 192.168.3.1.49880 > 192.168.3.2.9898: Flags [P.], cksum 0x9266 (incorrect -> 0xaa20), seq 515667:518463, ack 1, win 64, options [nop,nop,TS val 2990048824 ecr 2798801412], length 2796 + +116 = 14(mac) + 20(ip) + 8(udp) + 8(vxlan) + 14(inner mac) + 20(inner ip) + 32(innner tcp) + +Fixes: a2fb4bc4e2a6a03 ("net: implement virtio helpers to handle UDP GSO tunneling.") +Signed-off-by: Xuan Zhuo +Link: https://patch.msgid.link/20260320021818.111741-3-xuanzhuo@linux.alibaba.com +Acked-by: Michael S. Tsirkin +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/linux/virtio_net.h | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index 361b60c8be680..f36d21b5bc19e 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -224,6 +224,22 @@ static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb, + hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len); + } + ++/* This function must be called after virtio_net_hdr_from_skb(). */ ++static inline void __virtio_net_set_tnl_hdrlen(const struct sk_buff *skb, ++ struct virtio_net_hdr *hdr) ++{ ++ u16 hdr_len; ++ ++ hdr_len = skb_inner_transport_offset(skb); ++ ++ if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4) ++ hdr_len += sizeof(struct udphdr); ++ else ++ hdr_len += inner_tcp_hdrlen(skb); ++ ++ hdr->hdr_len = __cpu_to_virtio16(true, hdr_len); ++} ++ + static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian, +@@ -440,6 +456,9 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + if (ret) + return ret; + ++ if (feature_hdrlen && hdr->hdr_len) ++ __virtio_net_set_tnl_hdrlen(skb, hdr); ++ + if (skb->protocol == htons(ETH_P_IPV6)) + hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6; + else +-- +2.51.0 + diff --git a/queue-6.18/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch b/queue-6.18/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch new file mode 100644 index 0000000000..7945f8cb7b --- /dev/null +++ b/queue-6.18/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch @@ -0,0 +1,134 @@ +From 2eea8d0de9d0b9392791b520f0233922ca9f881b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 10:18:17 +0800 +Subject: virtio-net: correct hdr_len handling for VIRTIO_NET_F_GUEST_HDRLEN + +From: Xuan Zhuo + +[ Upstream commit 38ec410b99a5ee6566f75650ce3d4fd632940fd0 ] + +The commit be50da3e9d4a ("net: virtio_net: implement exact header length +guest feature") introduces support for the VIRTIO_NET_F_GUEST_HDRLEN +feature in virtio-net. + +This feature requires virtio-net to set hdr_len to the actual header +length of the packet when transmitting, the number of +bytes from the start of the packet to the beginning of the +transport-layer payload. + +However, in practice, hdr_len was being set using skb_headlen(skb), +which is clearly incorrect. This commit fixes that issue. + +Fixes: be50da3e9d4a ("net: virtio_net: implement exact header length guest feature") +Signed-off-by: Xuan Zhuo +Link: https://patch.msgid.link/20260320021818.111741-2-xuanzhuo@linux.alibaba.com +Acked-by: Michael S. Tsirkin +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/tun_vnet.h | 2 +- + drivers/net/virtio_net.c | 6 +++++- + include/linux/virtio_net.h | 34 ++++++++++++++++++++++++++++++---- + 3 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/tun_vnet.h b/drivers/net/tun_vnet.h +index a5f93b6c4482c..fa5cab9d3e55c 100644 +--- a/drivers/net/tun_vnet.h ++++ b/drivers/net/tun_vnet.h +@@ -244,7 +244,7 @@ tun_vnet_hdr_tnl_from_skb(unsigned int flags, + + if (virtio_net_hdr_tnl_from_skb(skb, tnl_hdr, has_tnl_offload, + tun_vnet_is_little_endian(flags), +- vlan_hlen, true)) { ++ vlan_hlen, true, false)) { + struct virtio_net_hdr_v1 *hdr = &tnl_hdr->hash_hdr.hdr; + struct skb_shared_info *sinfo = skb_shinfo(skb); + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index b67dbe346c807..9f855d196ae8f 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -3326,8 +3326,12 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan) + struct virtio_net_hdr_v1_hash_tunnel *hdr; + int num_sg; + unsigned hdr_len = vi->hdr_len; ++ bool feature_hdrlen; + bool can_push; + ++ feature_hdrlen = virtio_has_feature(vi->vdev, ++ VIRTIO_NET_F_GUEST_HDRLEN); ++ + pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); + + /* Make sure it's safe to cast between formats */ +@@ -3347,7 +3351,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan) + + if (virtio_net_hdr_tnl_from_skb(skb, hdr, vi->tx_tnl, + virtio_is_little_endian(vi->vdev), 0, +- false)) ++ false, feature_hdrlen)) + return -EPROTO; + + if (vi->mergeable_rx_bufs) +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index 75dabb763c650..361b60c8be680 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -207,6 +207,23 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + return __virtio_net_hdr_to_skb(skb, hdr, little_endian, hdr->gso_type); + } + ++/* This function must be called after virtio_net_hdr_from_skb(). */ ++static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb, ++ struct virtio_net_hdr *hdr, ++ bool little_endian) ++{ ++ u16 hdr_len; ++ ++ hdr_len = skb_transport_offset(skb); ++ ++ if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4) ++ hdr_len += sizeof(struct udphdr); ++ else ++ hdr_len += tcp_hdrlen(skb); ++ ++ hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len); ++} ++ + static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian, +@@ -385,7 +402,8 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + bool tnl_hdr_negotiated, + bool little_endian, + int vlan_hlen, +- bool has_data_valid) ++ bool has_data_valid, ++ bool feature_hdrlen) + { + struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)vhdr; + unsigned int inner_nh, outer_th; +@@ -394,9 +412,17 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + + tnl_gso_type = skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | + SKB_GSO_UDP_TUNNEL_CSUM); +- if (!tnl_gso_type) +- return virtio_net_hdr_from_skb(skb, hdr, little_endian, +- has_data_valid, vlan_hlen); ++ if (!tnl_gso_type) { ++ ret = virtio_net_hdr_from_skb(skb, hdr, little_endian, ++ has_data_valid, vlan_hlen); ++ if (ret) ++ return ret; ++ ++ if (feature_hdrlen && hdr->hdr_len) ++ __virtio_net_set_hdrlen(skb, hdr, little_endian); ++ ++ return ret; ++ } + + /* Tunnel support not negotiated but skb ask for it. */ + if (!tnl_hdr_negotiated) +-- +2.51.0 + diff --git a/queue-6.18/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch b/queue-6.18/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch new file mode 100644 index 0000000000..40c4c19393 --- /dev/null +++ b/queue-6.18/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch @@ -0,0 +1,49 @@ +From dccdfeb976846a25559e9d82e5d1eabeb07e3538 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:11 +0100 +Subject: xfrm: add missing extack for XFRMA_SA_PCPU in add_acquire and + allocspi + +From: Sabrina Dubroca + +[ Upstream commit aa8a3f3c67235422a0c3608a8772f69ca3b7b63f ] + +We're returning an error caused by invalid user input without setting +an extack. Add one. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 403b5ecac2c54..3e6477c6082e7 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1850,6 +1850,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + if (pcpu_num >= num_possible_cpus()) { + err = -EINVAL; ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto out_noput; + } + } +@@ -3001,8 +3002,10 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + if (attrs[XFRMA_SA_PCPU]) { + x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + err = -EINVAL; +- if (x->pcpu_num >= num_possible_cpus()) ++ if (x->pcpu_num >= num_possible_cpus()) { ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto free_state; ++ } + } + + err = verify_newpolicy_info(&ua->policy, extack); +-- +2.51.0 + diff --git a/queue-6.18/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-6.18/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..b8141a2e0c --- /dev/null +++ b/queue-6.18/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From 686db6909e5b0052f86b78ec89f6a1ef32f64db2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 98b362d518363..a00c4fe1ab0ce 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2264,6 +2264,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-6.18/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch b/queue-6.18/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch new file mode 100644 index 0000000000..236e83cb93 --- /dev/null +++ b/queue-6.18/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch @@ -0,0 +1,38 @@ +From 227806ac4eac14146bc6f3e8c59206effc2f7133 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:12 +0100 +Subject: xfrm: fix the condition on x->pcpu_num in xfrm_sa_len + +From: Sabrina Dubroca + +[ Upstream commit b57defcf8f109da5ba9cf59b2a736606faf3d846 ] + +pcpu_num = 0 is a valid value. The marker for "unset pcpu_num" which +makes copy_to_user_state_extra not add the XFRMA_SA_PCPU attribute is +UINT_MAX. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 3e6477c6082e7..4dd8341225bce 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -3676,7 +3676,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) + } + if (x->if_id) + l += nla_total_size(sizeof(x->if_id)); +- if (x->pcpu_num) ++ if (x->pcpu_num != UINT_MAX) + l += nla_total_size(sizeof(x->pcpu_num)); + + /* Must count x->lastused as it may become non-zero behind our back. */ +-- +2.51.0 + diff --git a/queue-6.18/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch b/queue-6.18/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch new file mode 100644 index 0000000000..288111d947 --- /dev/null +++ b/queue-6.18/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch @@ -0,0 +1,70 @@ +From 629fd9dd2fae55d5ffcd91604a645aa4c25f1c14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Mar 2026 03:16:29 +0900 +Subject: xfrm: Fix work re-schedule after cancel in + xfrm_nat_keepalive_net_fini() + +From: Hyunwoo Kim + +[ Upstream commit daf8e3b253aa760ff9e96c7768a464bc1d6b3c90 ] + +After cancel_delayed_work_sync() is called from +xfrm_nat_keepalive_net_fini(), xfrm_state_fini() flushes remaining +states via __xfrm_state_delete(), which calls +xfrm_nat_keepalive_state_updated() to re-schedule nat_keepalive_work. + +The following is a simple race scenario: + + cpu0 cpu1 + +cleanup_net() [Round 1] + ops_undo_list() + xfrm_net_exit() + xfrm_nat_keepalive_net_fini() + cancel_delayed_work_sync(nat_keepalive_work); + xfrm_state_fini() + xfrm_state_flush() + xfrm_state_delete(x) + __xfrm_state_delete(x) + xfrm_nat_keepalive_state_updated(x) + schedule_delayed_work(nat_keepalive_work); + rcu_barrier(); + net_complete_free(); + net_passive_dec(net); + llist_add(&net->defer_free_list, &defer_free_list); + +cleanup_net() [Round 2] + rcu_barrier(); + net_complete_free() + kmem_cache_free(net_cachep, net); + nat_keepalive_work() + // on freed net + +To prevent this, cancel_delayed_work_sync() is replaced with +disable_delayed_work_sync(). + +Fixes: f531d13bdfe3 ("xfrm: support sending NAT keepalives in ESP in UDP states") +Signed-off-by: Hyunwoo Kim +Reviewed-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_nat_keepalive.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_nat_keepalive.c b/net/xfrm/xfrm_nat_keepalive.c +index ebf95d48e86c1..1856beee0149b 100644 +--- a/net/xfrm/xfrm_nat_keepalive.c ++++ b/net/xfrm/xfrm_nat_keepalive.c +@@ -261,7 +261,7 @@ int __net_init xfrm_nat_keepalive_net_init(struct net *net) + + int xfrm_nat_keepalive_net_fini(struct net *net) + { +- cancel_delayed_work_sync(&net->xfrm.nat_keepalive_work); ++ disable_delayed_work_sync(&net->xfrm.nat_keepalive_work); + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.18/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch b/queue-6.18/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch new file mode 100644 index 0000000000..6b71cd52f4 --- /dev/null +++ b/queue-6.18/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch @@ -0,0 +1,80 @@ +From dbdc1e8fbcd94229d4adf1b714185f2a529c741c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Mar 2026 15:09:35 +0100 +Subject: xfrm: iptfs: fix skb_put() panic on non-linear skb during reassembly + +From: Fernando Fernandez Mancera + +[ Upstream commit 0b352f83cabfefdaafa806d6471f0eca117dc7d5 ] + +In iptfs_reassem_cont(), IP-TFS attempts to append data to the new inner +packet 'newskb' that is being reassembled. First a zero-copy approach is +tried if it succeeds then newskb becomes non-linear. + +When a subsequent fragment in the same datagram does not meet the +fast-path conditions, a memory copy is performed. It calls skb_put() to +append the data and as newskb is non-linear it triggers +SKB_LINEAR_ASSERT check. + + Oops: invalid opcode: 0000 [#1] SMP NOPTI + [...] + RIP: 0010:skb_put+0x3c/0x40 + [...] + Call Trace: + + iptfs_reassem_cont+0x1ab/0x5e0 [xfrm_iptfs] + iptfs_input_ordered+0x2af/0x380 [xfrm_iptfs] + iptfs_input+0x122/0x3e0 [xfrm_iptfs] + xfrm_input+0x91e/0x1a50 + xfrm4_esp_rcv+0x3a/0x110 + ip_protocol_deliver_rcu+0x1d7/0x1f0 + ip_local_deliver_finish+0xbe/0x1e0 + __netif_receive_skb_core.constprop.0+0xb56/0x1120 + __netif_receive_skb_list_core+0x133/0x2b0 + netif_receive_skb_list_internal+0x1ff/0x3f0 + napi_complete_done+0x81/0x220 + virtnet_poll+0x9d6/0x116e [virtio_net] + __napi_poll.constprop.0+0x2b/0x270 + net_rx_action+0x162/0x360 + handle_softirqs+0xdc/0x510 + __irq_exit_rcu+0xe7/0x110 + irq_exit_rcu+0xe/0x20 + common_interrupt+0x85/0xa0 + + + +Fix this by checking if the skb is non-linear. If it is, linearize it by +calling skb_linearize(). As the initial allocation of newskb originally +reserved enough tailroom for the entire reassembled packet we do not +need to check if we have enough tailroom or extend it. + +Fixes: 5f2b6a909574 ("xfrm: iptfs: add skb-fragment sharing code") +Reported-by: Hao Long +Closes: https://lore.kernel.org/netdev/DGRCO9SL0T5U.JTINSHJQ9KPK@imlonghao.com/ +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_iptfs.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c +index 3b6d7284fc70a..4e270628fc347 100644 +--- a/net/xfrm/xfrm_iptfs.c ++++ b/net/xfrm/xfrm_iptfs.c +@@ -901,6 +901,12 @@ static u32 iptfs_reassem_cont(struct xfrm_iptfs_data *xtfs, u64 seq, + iptfs_skb_can_add_frags(newskb, fragwalk, data, copylen)) { + iptfs_skb_add_frags(newskb, fragwalk, data, copylen); + } else { ++ if (skb_linearize(newskb)) { ++ XFRM_INC_STATS(xs_net(xtfs->x), ++ LINUX_MIB_XFRMINBUFFERERROR); ++ goto abandon; ++ } ++ + /* copy fragment data into newskb */ + if (skb_copy_seq_read(st, data, skb_put(newskb, copylen), + copylen)) { +-- +2.51.0 + diff --git a/queue-6.18/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch b/queue-6.18/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch new file mode 100644 index 0000000000..4acc9479d3 --- /dev/null +++ b/queue-6.18/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch @@ -0,0 +1,48 @@ +From 22961066125916e399a169a350c7d21da3b0e1c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 00:58:44 +0900 +Subject: xfrm: prevent policy_hthresh.work from racing with netns teardown + +From: Minwoo Ra + +[ Upstream commit 29fe3a61bcdce398ee3955101c39f89c01a8a77e ] + +A XFRM_MSG_NEWSPDINFO request can queue the per-net work item +policy_hthresh.work onto the system workqueue. + +The queued callback, xfrm_hash_rebuild(), retrieves the enclosing +struct net via container_of(). If the net namespace is torn down +before that work runs, the associated struct net may already have +been freed, and xfrm_hash_rebuild() may then dereference stale memory. + +xfrm_policy_fini() already flushes policy_hash_work during teardown, +but it does not synchronize policy_hthresh.work. + +Synchronize policy_hthresh.work in xfrm_policy_fini() as well, so the +queued work cannot outlive the net namespace teardown and access a +freed struct net. + +Fixes: 880a6fab8f6b ("xfrm: configure policy hash table thresholds by netlink") +Signed-off-by: Minwoo Ra +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 5428185196a1f..c32d34c441ee0 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -4282,6 +4282,8 @@ static void xfrm_policy_fini(struct net *net) + unsigned int sz; + int dir; + ++ disable_work_sync(&net->xfrm.policy_hthresh.work); ++ + flush_work(&net->xfrm.policy_hash_work); + #ifdef CONFIG_XFRM_SUB_POLICY + xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false); +-- +2.51.0 + diff --git a/queue-6.19/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-6.19/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..503f2094b7 --- /dev/null +++ b/queue-6.19/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From f9efbb2f085e2f446e4be19cf29e33dc0bc9992b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 571200433aa90..bc91aeeb74bbf 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3518,7 +3518,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3583,12 +3583,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch b/queue-6.19/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch new file mode 100644 index 0000000000..669bdfd58c --- /dev/null +++ b/queue-6.19/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch @@ -0,0 +1,101 @@ +From 4de3d0cff1918fe58fa086e1d9c12178eb424805 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 20:54:03 +0800 +Subject: Bluetooth: btintel: serialize btintel_hw_error() with + hci_req_sync_lock + +From: Cen Zhang + +[ Upstream commit 94d8e6fe5d0818e9300e514e095a200bd5ff93ae ] + +btintel_hw_error() issues two __hci_cmd_sync() calls (HCI_OP_RESET +and Intel exception-info retrieval) without holding +hci_req_sync_lock(). This lets it race against +hci_dev_do_close() -> btintel_shutdown_combined(), which also runs +__hci_cmd_sync() under the same lock. When both paths manipulate +hdev->req_status/req_rsp concurrently, the close path may free the +response skb first, and the still-running hw_error path hits a +slab-use-after-free in kfree_skb(). + +Wrap the whole recovery sequence in hci_req_sync_lock/unlock so it +is serialized with every other synchronous HCI command issuer. + +Below is the data race report and the kasan report: + + BUG: data-race in __hci_cmd_sync_sk / btintel_shutdown_combined + + read of hdev->req_rsp at net/bluetooth/hci_sync.c:199 + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x114/0x670 drivers/bluetooth/btintel.c:254 + hci_error_reset+0x348/0xa30 net/bluetooth/hci_core.c:1030 + + write/free by task ioctl/22580: + btintel_shutdown_combined+0xd0/0x360 + drivers/bluetooth/btintel.c:3648 + hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246 + hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526 + + BUG: KASAN: slab-use-after-free in + sk_skb_reason_drop+0x43/0x380 net/core/skbuff.c:1202 + Read of size 4 at addr ffff888144a738dc + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x186/0x670 drivers/bluetooth/btintel.c:260 + +Fixes: 973bb97e5aee ("Bluetooth: btintel: Add generic function for handling hardware errors") +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 9d29ab811f802..5e0a05edcbfd1 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -251,11 +251,13 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + + bt_dev_err(hdev, "Hardware error 0x%2.2x", code); + ++ hci_req_sync_lock(hdev); ++ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reset after hardware error failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + kfree_skb(skb); + +@@ -263,18 +265,21 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code) + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + + if (skb->len != 13) { + bt_dev_err(hdev, "Exception info size mismatch"); + kfree_skb(skb); +- return; ++ goto unlock; + } + + bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); + + kfree_skb(skb); ++ ++unlock: ++ hci_req_sync_unlock(hdev); + } + EXPORT_SYMBOL_GPL(btintel_hw_error); + +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-6.19/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..c7d7557224 --- /dev/null +++ b/queue-6.19/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From 7bc7bf6f196e5a1ea130525cfeac84aa8ee01fe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a41bb1e2a279a..4e161dcca00d8 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2378,8 +2378,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-6.19/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..6605a877bf --- /dev/null +++ b/queue-6.19/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From e43d49de3bbca34104ea178fb8a24447f4d55b03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 6f4e25917b863..c4584f4085766 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch b/queue-6.19/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch new file mode 100644 index 0000000000..c14eb11975 --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch @@ -0,0 +1,64 @@ +From b3328c8db42275fde709b5095f86a09912556d92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:01:26 +0900 +Subject: Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del() + +From: Hyunwoo Kim + +[ Upstream commit 00fdebbbc557a2fc21321ff2eaa22fd70c078608 ] + +l2cap_conn_del() calls cancel_delayed_work_sync() for both info_timer +and id_addr_timer while holding conn->lock. However, the work functions +l2cap_info_timeout() and l2cap_conn_update_id_addr() both acquire +conn->lock, creating a potential AB-BA deadlock if the work is already +executing when l2cap_conn_del() takes the lock. + +Move the work cancellations before acquiring conn->lock and use +disable_delayed_work_sync() to additionally prevent the works from +being rearmed after cancellation, consistent with the pattern used in +hci_conn_del(). + +Fixes: ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 5bd5561a8dbf5..734cbb5dc1bfa 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1748,6 +1748,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + + BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); + ++ disable_delayed_work_sync(&conn->info_timer); ++ disable_delayed_work_sync(&conn->id_addr_timer); ++ + mutex_lock(&conn->lock); + + kfree_skb(conn->rx_skb); +@@ -1763,8 +1766,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + + ida_destroy(&conn->tx_ida); + +- cancel_delayed_work_sync(&conn->id_addr_timer); +- + l2cap_unregister_all_users(conn); + + /* Force the connection to be immediately dropped */ +@@ -1783,9 +1784,6 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + l2cap_chan_put(chan); + } + +- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) +- cancel_delayed_work_sync(&conn->info_timer); +- + hci_chan_del(conn->hchan); + conn->hchan = NULL; + +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-6.19/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..29cb5036cf --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From 6a5825a7da70adbc6138d81848d88ba8cf441be3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 734cbb5dc1bfa..b72f2da57257d 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2375,6 +2375,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4310,14 +4313,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch b/queue-6.19/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch new file mode 100644 index 0000000000..3c9c77800b --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch @@ -0,0 +1,150 @@ +From e6f9d31d5758b56771e5a86fced6d44a604f226d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jan 2026 16:39:44 -0500 +Subject: Bluetooth: L2CAP: Fix not tracking outstanding TX ident + +From: Luiz Augusto von Dentz + +[ Upstream commit 6c3ea155e5ee3e56606233acde8309afda66d483 ] + +This attempts to proper track outstanding request by using struct ida +and allocating from it in l2cap_get_ident using ida_alloc_range which +would reuse ids as they are free, then upon completion release +the id using ida_free. + +This fixes the qualification test case L2CAP/COS/CED/BI-29-C which +attempts to check if the host stack is able to work after 256 attempts +to connect which requires Ident field to use the full range of possible +values in order to pass the test. + +Link: https://github.com/bluez/bluez/issues/1829 +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Stable-dep-of: 00fdebbbc557 ("Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del()") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/l2cap.h | 3 +-- + net/bluetooth/l2cap_core.c | 46 ++++++++++++++++++++++++----------- + 2 files changed, 33 insertions(+), 16 deletions(-) + +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index f08ed93bb6fa3..010f1a8fd15f8 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -657,8 +657,7 @@ struct l2cap_conn { + + struct sk_buff *rx_skb; + __u32 rx_len; +- __u8 tx_ident; +- struct mutex ident_lock; ++ struct ida tx_ida; + + struct sk_buff_head pending_rx; + struct work_struct pending_rx_work; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index b5e393e4f3eb1..5bd5561a8dbf5 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -924,26 +924,18 @@ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) + initiator); + } + +-static u8 l2cap_get_ident(struct l2cap_conn *conn) ++static int l2cap_get_ident(struct l2cap_conn *conn) + { +- u8 id; ++ /* LE link does not support tools like l2ping so use the full range */ ++ if (conn->hcon->type == LE_LINK) ++ return ida_alloc_range(&conn->tx_ida, 1, 255, GFP_ATOMIC); + + /* Get next available identificator. + * 1 - 128 are used by kernel. + * 129 - 199 are reserved. + * 200 - 254 are used by utilities like l2ping, etc. + */ +- +- mutex_lock(&conn->ident_lock); +- +- if (++conn->tx_ident > 128) +- conn->tx_ident = 1; +- +- id = conn->tx_ident; +- +- mutex_unlock(&conn->ident_lock); +- +- return id; ++ return ida_alloc_range(&conn->tx_ida, 1, 128, GFP_ATOMIC); + } + + static void l2cap_send_acl(struct l2cap_conn *conn, struct sk_buff *skb, +@@ -1769,6 +1761,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) + if (work_pending(&conn->pending_rx_work)) + cancel_work_sync(&conn->pending_rx_work); + ++ ida_destroy(&conn->tx_ida); ++ + cancel_delayed_work_sync(&conn->id_addr_timer); + + l2cap_unregister_all_users(conn); +@@ -4780,12 +4774,34 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, + return err; + } + ++static void l2cap_put_ident(struct l2cap_conn *conn, u8 code, u8 id) ++{ ++ switch (code) { ++ case L2CAP_COMMAND_REJ: ++ case L2CAP_CONN_RSP: ++ case L2CAP_CONF_RSP: ++ case L2CAP_DISCONN_RSP: ++ case L2CAP_ECHO_RSP: ++ case L2CAP_INFO_RSP: ++ case L2CAP_CONN_PARAM_UPDATE_RSP: ++ case L2CAP_ECRED_CONN_RSP: ++ case L2CAP_ECRED_RECONF_RSP: ++ /* First do a lookup since the remote may send bogus ids that ++ * would make ida_free to generate warnings. ++ */ ++ if (ida_find_first_range(&conn->tx_ida, id, id) >= 0) ++ ida_free(&conn->tx_ida, id); ++ } ++} ++ + static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_command_rej(conn, cmd, cmd_len, data); +@@ -5470,6 +5486,8 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_le_command_rej(conn, cmd, cmd_len, data); +@@ -6972,13 +6990,13 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) + hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) + conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; + +- mutex_init(&conn->ident_lock); + mutex_init(&conn->lock); + + INIT_LIST_HEAD(&conn->chan_l); + INIT_LIST_HEAD(&conn->users); + + INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); ++ ida_init(&conn->tx_ida); + + skb_queue_head_init(&conn->pending_rx); + INIT_WORK(&conn->pending_rx_work, process_pending_rx); +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-6.19/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..bb8ce471f9 --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From 62a6fe2bf9f8db650de0c7fc65bafc384f480736 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index bc9760e0abaf8..f1131e4415c95 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1681,6 +1681,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch b/queue-6.19/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch new file mode 100644 index 0000000000..4b96c7d7b4 --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch @@ -0,0 +1,50 @@ +From 4341b4655316f3857417dc3f0422723ae1931bbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 17:32:11 +0800 +Subject: Bluetooth: L2CAP: Fix send LE flow credits in ACL link + +From: Zhang Chen + +[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ] + +When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, +l2cap_publish_rx_avail will be called and le flow credits will be sent in +l2cap_chan_rx_avail, even though the link type is ACL. + +The logs in question as follows: +> ACL Data RX: Handle 129 flags 0x02 dlen 12 + L2CAP: Unknown (0x16) ident 4 len 4 + 40 00 ed 05 +< ACL Data TX: Handle 129 flags 0x00 dlen 10 + L2CAP: Command Reject (0x01) ident 4 len 2 + Reason: Command not understood (0x0000) + +Bluetooth: Unknown BR/EDR signaling command 0x16 +Bluetooth: Wrong link type (-22) + +Fixes: ce60b9231b66 ("Bluetooth: compute LE flow credits based on recvbuf space") +Signed-off-by: Zhang Chen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 848a9b945de89..b5e393e4f3eb1 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6589,6 +6589,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + struct l2cap_le_credits pkt; + u16 return_credits = l2cap_le_rx_credits(chan); + ++ if (chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ + if (chan->rx_credits >= return_credits) + return; + +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch b/queue-6.19/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch new file mode 100644 index 0000000000..8a42c8a272 --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch @@ -0,0 +1,67 @@ +From e54055a769a55bb91d264cc3e977837d64e187a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 22:14:37 +0900 +Subject: Bluetooth: L2CAP: Fix stack-out-of-bounds read in + l2cap_ecred_conn_req + +From: Minseo Park + +[ Upstream commit 9d87cb22195b2c67405f5485d525190747ad5493 ] + +Syzbot reported a KASAN stack-out-of-bounds read in l2cap_build_cmd() +that is triggered by a malformed Enhanced Credit Based Connection Request. + +The vulnerability stems from l2cap_ecred_conn_req(). The function allocates +a local stack buffer (`pdu`) designed to hold a maximum of 5 Source Channel +IDs (SCIDs), totaling 18 bytes. When an attacker sends a request with more +than 5 SCIDs, the function calculates `rsp_len` based on this unvalidated +`cmd_len` before checking if the number of SCIDs exceeds +L2CAP_ECRED_MAX_CID. + +If the SCID count is too high, the function correctly jumps to the +`response` label to reject the packet, but `rsp_len` retains the +attacker's oversized value. Consequently, l2cap_send_cmd() is instructed +to read past the end of the 18-byte `pdu` buffer, triggering a +KASAN panic. + +Fix this by moving the assignment of `rsp_len` to after the `num_scid` +boundary check. If the packet is rejected, `rsp_len` will safely +remain 0, and the error response will only read the 8-byte base header +from the stack. + +Fixes: c28d2bff7044 ("Bluetooth: L2CAP: Fix result of L2CAP_ECRED_CONN_RSP when MTU is too short") +Reported-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b7f3e7d9a596bf6a63e3 +Tested-by: syzbot+b7f3e7d9a596bf6a63e3@syzkaller.appspotmail.com +Signed-off-by: Minseo Park +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9ea030fc9a9cc..583fe3b654c11 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -5065,14 +5065,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, + cmd_len -= sizeof(*req); + num_scid = cmd_len / sizeof(u16); + +- /* Always respond with the same number of scids as in the request */ +- rsp_len = cmd_len; +- + if (num_scid > L2CAP_ECRED_MAX_CID) { + result = L2CAP_CR_LE_INVALID_PARAMS; + goto response; + } + ++ /* Always respond with the same number of scids as in the request */ ++ rsp_len = cmd_len; ++ + mtu = __le16_to_cpu(req->mtu); + mps = __le16_to_cpu(req->mps); + +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-6.19/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..2132fa1a4d --- /dev/null +++ b/queue-6.19/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From c45e9769ef694eb07d06984d2e3b90f38b85ae39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 583fe3b654c11..848a9b945de89 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6672,6 +6672,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch b/queue-6.19/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch new file mode 100644 index 0000000000..944368c3b5 --- /dev/null +++ b/queue-6.19/bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch @@ -0,0 +1,42 @@ +From 85403b01b6fa611036ff2a3f10b2269c0f246d19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:03:27 -0400 +Subject: Bluetooth: MGMT: Fix dangling pointer on + mgmt_add_adv_patterns_monitor_complete + +From: Luiz Augusto von Dentz + +[ Upstream commit 5f5fa4cd35f707344f65ce9e225b6528691dbbaa ] + +This fixes the condition checking so mgmt_pending_valid is executed +whenever status != -ECANCELED otherwise calling mgmt_pending_free(cmd) +would kfree(cmd) without unlinking it from the list first, leaving a +dangling pointer. Any subsequent list traversal (e.g., +mgmt_pending_foreach during __mgmt_power_off, or another +mgmt_pending_valid call) would dereference freed memory. + +Link: https://lore.kernel.org/linux-bluetooth/20260315132013.75ab40c5@kernel.org/T/#m1418f9c82eeff8510c1beaa21cf53af20db96c06 +Fixes: 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs") +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 2c63f49c33018..f3da1bc38a551 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -5355,7 +5355,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, + * hci_adv_monitors_clear is about to be called which will take care of + * freeing the adv_monitor instances. + */ +- if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd)) ++ if (status == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) + return; + + monitor = cmd->user_data; +-- +2.51.0 + diff --git a/queue-6.19/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-6.19/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..89aa14c21f --- /dev/null +++ b/queue-6.19/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From 3608ccdeade9228007348851204fff29d4628498 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index cccfaf5603174..6741b067d28b5 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -401,7 +401,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -410,11 +410,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-6.19/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-6.19/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..558e471069 --- /dev/null +++ b/queue-6.19/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From bb6b22ed2c55ca5871ffab9fc96c5afe8bdecbcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index 770173d8db428..a624c04ed5c63 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -469,7 +469,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -573,7 +573,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 0938bf7dd646a..de4d05ae34597 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-6.19/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-6.19/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..aa738bd521 --- /dev/null +++ b/queue-6.19/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 63d13d7974c9976eb285d5d5682eafdca1d064b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index aa36a0d1d9df6..190eab9f5e8c2 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -240,8 +240,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-6.19/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch b/queue-6.19/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch new file mode 100644 index 0000000000..8c943c4193 --- /dev/null +++ b/queue-6.19/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch @@ -0,0 +1,83 @@ +From 8d116776221fcfd5bd22b25b00b8d946d6ece58d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 17:27:49 +0900 +Subject: dma: swiotlb: add KMSAN annotations to swiotlb_bounce() + +From: Shigeru Yoshida + +[ Upstream commit 6f770b73d0311a5b099277653199bb6421c4fed2 ] + +When a device performs DMA to a bounce buffer, KMSAN is unaware of +the write and does not mark the data as initialized. When +swiotlb_bounce() later copies the bounce buffer back to the original +buffer, memcpy propagates the uninitialized shadow to the original +buffer, causing false positive uninit-value reports. + +Fix this by calling kmsan_unpoison_memory() on the bounce buffer +before copying it back in the DMA_FROM_DEVICE path, so that memcpy +naturally propagates initialized shadow to the destination. + +Suggested-by: Alexander Potapenko +Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/ +Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") +Signed-off-by: Shigeru Yoshida +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index a547c7693135b..b4bc7ce01dadc 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -901,10 +902,19 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + + local_irq_save(flags); + page = pfn_to_page(pfn); +- if (dir == DMA_TO_DEVICE) ++ if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_highmem_page() ++ * could be used here to detect infoleaks, ++ * but callers may map uninitialized buffers ++ * that will be written by the device, ++ * causing false positives. ++ */ + memcpy_from_page(vaddr, page, offset, sz); +- else ++ } else { ++ kmsan_unpoison_memory(vaddr, sz); + memcpy_to_page(page, offset, vaddr, sz); ++ } + local_irq_restore(flags); + + size -= sz; +@@ -913,8 +923,15 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + offset = 0; + } + } else if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_memory() could be used here to detect ++ * infoleaks (uninitialized data being sent to device), but ++ * callers may map uninitialized buffers that will be written ++ * by the device, causing false positives. ++ */ + memcpy(vaddr, phys_to_virt(orig_addr), size); + } else { ++ kmsan_unpoison_memory(vaddr, size); + memcpy(phys_to_virt(orig_addr), vaddr, size); + } + } +-- +2.51.0 + diff --git a/queue-6.19/erofs-set-fileio-bio-failed-in-short-read-case.patch b/queue-6.19/erofs-set-fileio-bio-failed-in-short-read-case.patch new file mode 100644 index 0000000000..1cd9b0b798 --- /dev/null +++ b/queue-6.19/erofs-set-fileio-bio-failed-in-short-read-case.patch @@ -0,0 +1,60 @@ +From 0ae3fdfdf069a6e9e21ca0776c5ce023dc9109d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Feb 2026 10:30:08 +0800 +Subject: erofs: set fileio bio failed in short read case + +From: Sheng Yong + +[ Upstream commit eade54040384f54b7fb330e4b0975c5734850b3c ] + +For file-backed mount, IO requests are handled by vfs_iocb_iter_read(). +However, it can be interrupted by SIGKILL, returning the number of +bytes actually copied. Unused folios in bio are unexpectedly marked +as uptodate. + + vfs_read + filemap_read + filemap_get_pages + filemap_readahead + erofs_fileio_readahead + erofs_fileio_rq_submit + vfs_iocb_iter_read + filemap_read + filemap_get_pages <= detect signal + erofs_fileio_ki_complete <= set all folios uptodate + +This patch addresses this by setting short read bio with an error +directly. + +Fixes: bc804a8d7e86 ("erofs: handle end of filesystem properly for file-backed mounts") +Reported-by: chenguanyou +Signed-off-by: Yunlei He +Signed-off-by: Sheng Yong +Reviewed-by: Gao Xiang +Reviewed-by: Chao Yu +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/fileio.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c +index 2a778a02681a0..aa580c59fe645 100644 +--- a/fs/erofs/fileio.c ++++ b/fs/erofs/fileio.c +@@ -25,10 +25,8 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret) + container_of(iocb, struct erofs_fileio_rq, iocb); + struct folio_iter fi; + +- if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) { +- bio_advance(&rq->bio, ret); +- zero_fill_bio(&rq->bio); +- } ++ if (ret >= 0 && ret != rq->bio.bi_iter.bi_size) ++ ret = -EIO; + if (!rq->bio.bi_end_io) { + bio_for_each_folio_all(fi, &rq->bio) { + DBG_BUGON(folio_test_uptodate(fi.folio)); +-- +2.51.0 + diff --git a/queue-6.19/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-6.19/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..6be82006ae --- /dev/null +++ b/queue-6.19/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 3e82da92a0a33d17136f9a7bd34b9083ec9f5bf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 2c922afadb8f6..6dfc0bcdef654 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -235,10 +235,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index e75da98f52838..9f75313734f8c 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -271,10 +271,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-6.19/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch b/queue-6.19/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch new file mode 100644 index 0000000000..84ea669e54 --- /dev/null +++ b/queue-6.19/iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch @@ -0,0 +1,158 @@ +From ac7a6d07ac2ed759de4af8559fa4ce33775eaee5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Feb 2026 19:14:25 +0000 +Subject: iavf: fix out-of-bounds writes in iavf_get_ethtool_stats() + +From: Kohei Enju + +[ Upstream commit fecacfc95f195b99c71c579a472120d0b4ed65fa ] + +iavf incorrectly uses real_num_tx_queues for ETH_SS_STATS. Since the +value could change in runtime, we should use num_tx_queues instead. + +Moreover iavf_get_ethtool_stats() uses num_active_queues while +iavf_get_sset_count() and iavf_get_stat_strings() use +real_num_tx_queues, which triggers out-of-bounds writes when we do +"ethtool -L" and "ethtool -S" simultaneously [1]. + +For example when we change channels from 1 to 8, Thread 3 could be +scheduled before Thread 2, and out-of-bounds writes could be triggered +in Thread 3: + +Thread 1 (ethtool -L) Thread 2 (work) Thread 3 (ethtool -S) +iavf_set_channels() +... +iavf_alloc_queues() +-> num_active_queues = 8 +iavf_schedule_finish_config() + iavf_get_sset_count() + real_num_tx_queues: 1 + -> buffer for 1 queue + iavf_get_ethtool_stats() + num_active_queues: 8 + -> out-of-bounds! + iavf_finish_config() + -> real_num_tx_queues = 8 + +Use immutable num_tx_queues in all related functions to avoid the issue. + +[1] + BUG: KASAN: vmalloc-out-of-bounds in iavf_add_one_ethtool_stat+0x200/0x270 + Write of size 8 at addr ffffc900031c9080 by task ethtool/5800 + + CPU: 1 UID: 0 PID: 5800 Comm: ethtool Not tainted 6.19.0-enjuk-08403-g8137e3db7f1c #241 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + Call Trace: + + dump_stack_lvl+0x6f/0xb0 + print_report+0x170/0x4f3 + kasan_report+0xe1/0x180 + iavf_add_one_ethtool_stat+0x200/0x270 + iavf_get_ethtool_stats+0x14c/0x2e0 + __dev_ethtool+0x3d0c/0x5830 + dev_ethtool+0x12d/0x270 + dev_ioctl+0x53c/0xe30 + sock_do_ioctl+0x1a9/0x270 + sock_ioctl+0x3d4/0x5e0 + __x64_sys_ioctl+0x137/0x1c0 + do_syscall_64+0xf3/0x690 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + RIP: 0033:0x7f7da0e6e36d + ... + + + The buggy address belongs to a 1-page vmalloc region starting at 0xffffc900031c9000 allocated at __dev_ethtool+0x3cc9/0x5830 + The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff88813a013de0 pfn:0x13a013 + flags: 0x200000000000000(node=0|zone=2) + raw: 0200000000000000 0000000000000000 dead000000000122 0000000000000000 + raw: ffff88813a013de0 0000000000000000 00000001ffffffff 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffffc900031c8f80: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ffffc900031c9080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffffc900031c9100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffffc900031c9180: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + +Fixes: 64430f70ba6f ("iavf: Fix displaying queue statistics shown by ethtool") +Signed-off-by: Kohei Enju +Reviewed-by: Simon Horman +Reviewed-by: Przemek Kitszel +Reviewed-by: Paul Menzel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../net/ethernet/intel/iavf/iavf_ethtool.c | 31 +++++++++---------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +index 6ff3842a1ff1f..98bec3afc2006 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +@@ -313,14 +313,13 @@ static int iavf_get_sset_count(struct net_device *netdev, int sset) + { + /* Report the maximum number queues, even if not every queue is + * currently configured. Since allocation of queues is in pairs, +- * use netdev->real_num_tx_queues * 2. The real_num_tx_queues is set +- * at device creation and never changes. ++ * use netdev->num_tx_queues * 2. The num_tx_queues is set at ++ * device creation and never changes. + */ + + if (sset == ETH_SS_STATS) + return IAVF_STATS_LEN + +- (IAVF_QUEUE_STATS_LEN * 2 * +- netdev->real_num_tx_queues); ++ (IAVF_QUEUE_STATS_LEN * 2 * netdev->num_tx_queues); + else + return -EINVAL; + } +@@ -345,19 +344,19 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, + iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats); + + rcu_read_lock(); +- /* As num_active_queues describe both tx and rx queues, we can use +- * it to iterate over rings' stats. ++ /* Use num_tx_queues to report stats for the maximum number of queues. ++ * Queues beyond num_active_queues will report zero. + */ +- for (i = 0; i < adapter->num_active_queues; i++) { +- struct iavf_ring *ring; ++ for (i = 0; i < netdev->num_tx_queues; i++) { ++ struct iavf_ring *tx_ring = NULL, *rx_ring = NULL; + +- /* Tx rings stats */ +- ring = &adapter->tx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ if (i < adapter->num_active_queues) { ++ tx_ring = &adapter->tx_rings[i]; ++ rx_ring = &adapter->rx_rings[i]; ++ } + +- /* Rx rings stats */ +- ring = &adapter->rx_rings[i]; +- iavf_add_queue_stats(&data, ring); ++ iavf_add_queue_stats(&data, tx_ring); ++ iavf_add_queue_stats(&data, rx_ring); + } + rcu_read_unlock(); + } +@@ -376,9 +375,9 @@ static void iavf_get_stat_strings(struct net_device *netdev, u8 *data) + iavf_add_stat_strings(&data, iavf_gstrings_stats); + + /* Queues are always allocated in pairs, so we just use +- * real_num_tx_queues for both Tx and Rx queues. ++ * num_tx_queues for both Tx and Rx queues. + */ +- for (i = 0; i < netdev->real_num_tx_queues; i++) { ++ for (i = 0; i < netdev->num_tx_queues; i++) { + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, + "tx", i); + iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, +-- +2.51.0 + diff --git a/queue-6.19/ice-fix-inverted-ready-check-for-vf-representors.patch b/queue-6.19/ice-fix-inverted-ready-check-for-vf-representors.patch new file mode 100644 index 0000000000..39fa5b9400 --- /dev/null +++ b/queue-6.19/ice-fix-inverted-ready-check-for-vf-representors.patch @@ -0,0 +1,50 @@ +From 47cfd60d0d9ef235a445a2b7dc96a5a291f56bd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:10 +0100 +Subject: ice: fix inverted ready check for VF representors + +From: Petr Oros + +[ Upstream commit ad85de0fc09eb3236e73df5acb2bc257625103f5 ] + +Commit 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +refactored the VF readiness check into a generic repr->ops.ready() +callback but implemented ice_repr_ready_vf() with inverted logic: + + return !ice_check_vf_ready_for_cfg(repr->vf); + +ice_check_vf_ready_for_cfg() returns 0 on success, so the negation +makes ready() return non-zero when the VF is ready. All callers treat +non-zero as "not ready, skip", causing ndo_get_stats64, get_drvinfo, +get_strings and get_ethtool_stats to always bail out in switchdev mode. + +Remove the erroneous negation. The SF variant ice_repr_ready_sf() is +already correct (returns !active, i.e. non-zero when not active). + +Fixes: 0f00a897c9fcbd ("ice: check if SF is ready in ethtool ops") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Michal Swiatkowski +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_repr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index cb08746556a67..2a84f65640582 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -315,7 +315,7 @@ ice_repr_reg_netdev(struct net_device *netdev, const struct net_device_ops *ops) + + static int ice_repr_ready_vf(struct ice_repr *repr) + { +- return !ice_check_vf_ready_for_cfg(repr->vf); ++ return ice_check_vf_ready_for_cfg(repr->vf); + } + + static int ice_repr_ready_sf(struct ice_repr *repr) +-- +2.51.0 + diff --git a/queue-6.19/ice-use-ice_update_eth_stats-for-representor-stats.patch b/queue-6.19/ice-use-ice_update_eth_stats-for-representor-stats.patch new file mode 100644 index 0000000000..987442c5dd --- /dev/null +++ b/queue-6.19/ice-use-ice_update_eth_stats-for-representor-stats.patch @@ -0,0 +1,100 @@ +From fddd798571fd8f6031cb67af8dd3dfa051c15461 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:11 +0100 +Subject: ice: use ice_update_eth_stats() for representor stats + +From: Petr Oros + +[ Upstream commit 2526e440df2725e7328d59b835a164826f179b93 ] + +ice_repr_get_stats64() and __ice_get_ethtool_stats() call +ice_update_vsi_stats() on the VF's src_vsi. This always returns early +because ICE_VSI_DOWN is permanently set for VF VSIs - ice_up() is never +called on them since queues are managed by iavf through virtchnl. + +In __ice_get_ethtool_stats() the original code called +ice_update_vsi_stats() for all VSIs including representors, iterated +over ice_gstrings_vsi_stats[] to populate the data, and then bailed out +with an early return before the per-queue ring stats section. That early +return was necessary because representor VSIs have no rings on the PF +side - the rings belong to the VF driver (iavf), so accessing per-queue +stats would be invalid. + +Move the representor handling to the top of __ice_get_ethtool_stats() +and call ice_update_eth_stats() directly to read the hardware GLV_* +counters. This matches ice_get_vf_stats() which already uses +ice_update_eth_stats() for the same VF VSI in legacy mode. Apply the +same fix to ice_repr_get_stats64(). + +Note that ice_gstrings_vsi_stats[] contains five software ring counters +(rx_buf_failed, rx_page_failed, tx_linearize, tx_busy, tx_restart) that +are always zero for representors since the PF never processes packets on +VF rings. This is pre-existing behavior unchanged by this patch. + +Fixes: 7aae80cef7ba ("ice: add port representor ethtool ops and stats") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 14 +++++++++++--- + drivers/net/ethernet/intel/ice/ice_repr.c | 3 ++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index fa4c7ae9ff6b1..3125dc1b27654 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1930,6 +1930,17 @@ __ice_get_ethtool_stats(struct net_device *netdev, + int i = 0; + char *p; + ++ if (ice_is_port_repr_netdev(netdev)) { ++ ice_update_eth_stats(vsi); ++ ++ for (j = 0; j < ICE_VSI_STATS_LEN; j++) { ++ p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; ++ data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ return; ++ } ++ + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + +@@ -1939,9 +1950,6 @@ __ice_get_ethtool_stats(struct net_device *netdev, + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + +- if (ice_is_port_repr_netdev(netdev)) +- return; +- + /* populate per queue stats */ + rcu_read_lock(); + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index 2a84f65640582..f1e82ba155cff 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2019-2021, Intel Corporation. */ + + #include "ice.h" ++#include "ice_lib.h" + #include "ice_eswitch.h" + #include "devlink/devlink.h" + #include "devlink/port.h" +@@ -67,7 +68,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) + return; + vsi = repr->src_vsi; + +- ice_update_vsi_stats(vsi); ++ ice_update_eth_stats(vsi); + eth_stats = &vsi->eth_stats; + + stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast + +-- +2.51.0 + diff --git a/queue-6.19/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-6.19/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..86d98a6afc --- /dev/null +++ b/queue-6.19/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From 603b6c99a1761926398fd50c20b8b9b658763219 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 058eea86e141c..38a827203a2f7 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1719,13 +1719,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-6.19/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch b/queue-6.19/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch new file mode 100644 index 0000000000..02401a1047 --- /dev/null +++ b/queue-6.19/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch @@ -0,0 +1,144 @@ +From 9c4f3210ddfd70140f7d9655ca8ceab73731e4dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:23:00 +0000 +Subject: ipv6: Don't remove permanent routes with exceptions from + tb6_gc_hlist. + +From: Kuniyuki Iwashima + +[ Upstream commit 4be7b99c253f0c85a255cc1db7127ba3232dfa30 ] + +The cited commit mechanically put fib6_remove_gc_list() +just after every fib6_clean_expires() call. + +When a temporary route is promoted to a permanent route, +there may already be exception routes tied to it. + +If fib6_remove_gc_list() removes the route from tb6_gc_hlist, +such exception routes will no longer be aged. + +Let's replace fib6_remove_gc_list() with a new helper +fib6_may_remove_gc_list() and use fib6_age_exceptions() there. + +Note that net->ipv6 is only compiled when CONFIG_IPV6 is +enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded. + +Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/ip6_fib.h | 21 ++++++++++++++++++++- + net/ipv6/addrconf.c | 4 ++-- + net/ipv6/ip6_fib.c | 6 +++--- + net/ipv6/route.c | 2 +- + 4 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 88b0dd4d8e094..9f8b6814a96a0 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -507,12 +507,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt, + void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + unsigned int flags); + ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now); + void fib6_run_gc(unsigned long expires, struct net *net, bool force); +- + void fib6_gc_cleanup(void); + + int fib6_init(void); + ++#if IS_ENABLED(CONFIG_IPV6) + /* Add the route to the gc list if it is not already there + * + * The callers should hold f6i->fib6_table->tb6_lock. +@@ -545,6 +547,23 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i) + hlist_del_init(&f6i->gc_link); + } + ++static inline void fib6_may_remove_gc_list(struct net *net, ++ struct fib6_info *f6i) ++{ ++ struct fib6_gc_args gc_args; ++ ++ if (hlist_unhashed(&f6i->gc_link)) ++ return; ++ ++ gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval); ++ gc_args.more = 0; ++ ++ rcu_read_lock(); ++ fib6_age_exceptions(f6i, &gc_args, jiffies); ++ rcu_read_unlock(); ++} ++#endif ++ + struct ipv6_route_iter { + struct seq_net_private p; + struct fib6_walker w; +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 27ab9d7adc649..3dcfa4b3094a8 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2863,7 +2863,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) + fib6_add_gc_list(rt); + } else { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } + + spin_unlock_bh(&table->tb6_lock); +@@ -4836,7 +4836,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp, + + if (!(flags & RTF_EXPIRES)) { + fib6_clean_expires(f6i); +- fib6_remove_gc_list(f6i); ++ fib6_may_remove_gc_list(net, f6i); + } else { + fib6_set_expires(f6i, expires); + fib6_add_gc_list(f6i); +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index a22af1c8f93ac..ffa7733598333 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1133,7 +1133,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + return -EEXIST; + if (!(rt->fib6_flags & RTF_EXPIRES)) { + fib6_clean_expires(iter); +- fib6_remove_gc_list(iter); ++ fib6_may_remove_gc_list(info->nl_net, iter); + } else { + fib6_set_expires(iter, rt->expires); + fib6_add_gc_list(iter); +@@ -2348,8 +2348,8 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ +-static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, +- unsigned long now) ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) + { + bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; + int old_more = gc_args->more; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index e01331d965313..446f4de7d6a22 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1033,7 +1033,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + + if (!addrconf_finite_timeout(lifetime)) { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } else { + fib6_set_expires(rt, jiffies + HZ * lifetime); + fib6_add_gc_list(rt); +-- +2.51.0 + diff --git a/queue-6.19/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch b/queue-6.19/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch new file mode 100644 index 0000000000..9c1a12da1d --- /dev/null +++ b/queue-6.19/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch @@ -0,0 +1,76 @@ +From 145f29d934611b2e1993f9e96536fcd1404b13ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:22:59 +0000 +Subject: ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions + expire. + +From: Kuniyuki Iwashima + +[ Upstream commit 6af51e9f31336632263c4680b2a3712295103e1f ] + +Commit 5eb902b8e719 ("net/ipv6: Remove expired routes with a +separated list of routes.") introduced a per-table GC list and +changed GC to iterate over that list instead of traversing +the entire route table. + +However, it forgot to add permanent routes to tb6_gc_hlist +when exception routes are added. + +Commit cfe82469a00f ("ipv6: add exception routes to GC list +in rt6_insert_exception") fixed that issue but introduced +another one. + +Even after all exception routes expire, the permanent routes +remain in tb6_gc_hlist, potentially negating the performance +benefits intended by the initial change. + +Let's count gc_args->more before and after rt6_age_exceptions() +and remove the permanent route when the delta is 0. + +Note that the next patch will reuse fib6_age_exceptions(). + +Fixes: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Xin Long +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index cc149227b49f4..a22af1c8f93ac 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -2348,6 +2348,17 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ ++static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) ++{ ++ bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; ++ int old_more = gc_args->more; ++ ++ rt6_age_exceptions(rt, gc_args, now); ++ ++ if (!may_expire && old_more == gc_args->more) ++ fib6_remove_gc_list(rt); ++} + + static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + { +@@ -2370,7 +2381,7 @@ static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + * Note, that clones are aged out + * only if they are not in use now. + */ +- rt6_age_exceptions(rt, gc_args, now); ++ fib6_age_exceptions(rt, gc_args, now); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.19/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch b/queue-6.19/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch new file mode 100644 index 0000000000..efdb1553fe --- /dev/null +++ b/queue-6.19/net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch @@ -0,0 +1,41 @@ +From 2a55cfdc8850c9b7634b130ad4299baa1d4e8bd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:43:15 +0800 +Subject: net: airoha: add RCU lock around dev_fill_forward_path + +From: Qingfang Deng + +[ Upstream commit 1065913dedfd3a8269816835bfe810b6e2c28579 ] + +Since 0417adf367a0 ("ppp: fix race conditions in ppp_fill_forward_path") +dev_fill_forward_path() should be called with RCU read lock held. This +fix was applied to net, while the Airoha flowtable commit was applied to +net-next, so it hadn't been an issue until net was merged into net-next. + +Fixes: a8bdd935d1dd ("net: airoha: Add wlan flowtable TX offload") +Signed-off-by: Qingfang Deng +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260320094315.525126-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c +index 2221bafaf7c9f..36e4f328c6e81 100644 +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -227,7 +227,9 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr, + if (!dev) + return -ENODEV; + ++ rcu_read_lock(); + err = dev_fill_forward_path(dev, addr, &stack); ++ rcu_read_unlock(); + if (err) + return err; + +-- +2.51.0 + diff --git a/queue-6.19/net-b44-always-select-config_fixed_phy.patch b/queue-6.19/net-b44-always-select-config_fixed_phy.patch new file mode 100644 index 0000000000..f2e3c40b73 --- /dev/null +++ b/queue-6.19/net-b44-always-select-config_fixed_phy.patch @@ -0,0 +1,48 @@ +From 069f08e34fdb59d72b4b096c68a1ea011bdb8637 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 16:49:19 +0100 +Subject: net: b44: always select CONFIG_FIXED_PHY + +From: Arnd Bergmann + +[ Upstream commit 3f0f591b44b04a77ff561676ae53fcfd7532a54c ] + +When CONFIG_FIXED_PHY=m but CONFIG_B44=y, the kernel fails to link: + +ld.lld: error: undefined symbol: fixed_phy_unregister +>>> referenced by b44.c +>>> drivers/net/ethernet/broadcom/b44.o:(b44_remove_one) in archive vmlinux.a + +ld.lld: error: undefined symbol: fixed_phy_register_100fd +>>> referenced by b44.c +>>> drivers/net/ethernet/broadcom/b44.o:(b44_register_phy_one) in archive vmlinux.a + +The fixed phy support is small enough that just always enabling it +for b44 is the simplest solution, and it avoids adding ugly #ifdef +checks. + +Fixes: 10d2f15afba2 ("net: b44: register a fixed phy using fixed_phy_register_100fd if needed") +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20260320154927.674555-1-arnd@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig +index cd7dddeb91dd6..9787c1857e13b 100644 +--- a/drivers/net/ethernet/broadcom/Kconfig ++++ b/drivers/net/ethernet/broadcom/Kconfig +@@ -25,7 +25,7 @@ config B44 + select SSB + select MII + select PHYLIB +- select FIXED_PHY if BCM47XX ++ select FIXED_PHY + help + If you have a network (Ethernet) controller of this type, say Y + or M here. +-- +2.51.0 + diff --git a/queue-6.19/net-bcmasp-fix-double-disable-of-clk.patch b/queue-6.19/net-bcmasp-fix-double-disable-of-clk.patch new file mode 100644 index 0000000000..a764a26f43 --- /dev/null +++ b/queue-6.19/net-bcmasp-fix-double-disable-of-clk.patch @@ -0,0 +1,122 @@ +From ea3d09b6d63f0a3805f8b110c4fc4e269695891b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:13 -0700 +Subject: net: bcmasp: fix double disable of clk + +From: Justin Chen + +[ Upstream commit 27dfe9030acbc601c260b42ecdbb4e5858a97b53 ] + +Switch to devm_clk_get_optional() so we can manage the clock ourselves. +We dynamically control the clocks depending on the state of the interface +for power savings. The default state is clock disabled, so unbinding the +driver causes a double disable. + +Fixes: 490cb412007d ("net: bcmasp: Add support for ASP2.0 Ethernet controller") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 33 ++++++++++++++------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index fac795ac0fcee..1fdf0822c8a02 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1254,7 +1254,7 @@ static int bcmasp_probe(struct platform_device *pdev) + if (priv->irq <= 0) + return -EINVAL; + +- priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp"); ++ priv->clk = devm_clk_get_optional(dev, "sw_asp"); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to request clock\n"); +@@ -1282,6 +1282,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + bcmasp_set_pdata(priv, pdata); + ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to start clock\n"); ++ + /* Enable all clocks to ensure successful probing */ + bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); + +@@ -1293,8 +1297,10 @@ static int bcmasp_probe(struct platform_device *pdev) + + ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0, + pdev->name, priv); +- if (ret) +- return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret); ++ if (ret) { ++ dev_err(dev, "Failed to request ASP interrupt: %d", ret); ++ goto err_clock_disable; ++ } + + /* Register mdio child nodes */ + of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev); +@@ -1306,13 +1312,17 @@ static int bcmasp_probe(struct platform_device *pdev) + + priv->mda_filters = devm_kcalloc(dev, priv->num_mda_filters, + sizeof(*priv->mda_filters), GFP_KERNEL); +- if (!priv->mda_filters) +- return -ENOMEM; ++ if (!priv->mda_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + priv->net_filters = devm_kcalloc(dev, priv->num_net_filters, + sizeof(*priv->net_filters), GFP_KERNEL); +- if (!priv->net_filters) +- return -ENOMEM; ++ if (!priv->net_filters) { ++ ret = -ENOMEM; ++ goto err_clock_disable; ++ } + + bcmasp_core_init_filters(priv); + +@@ -1321,7 +1331,8 @@ static int bcmasp_probe(struct platform_device *pdev) + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_clock_disable; + } + + i = 0; +@@ -1343,8 +1354,6 @@ static int bcmasp_probe(struct platform_device *pdev) + */ + bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE); + +- clk_disable_unprepare(priv->clk); +- + /* Now do the registration of the network ports which will take care + * of managing the clock properly. + */ +@@ -1357,12 +1366,16 @@ static int bcmasp_probe(struct platform_device *pdev) + count++; + } + ++ clk_disable_unprepare(priv->clk); ++ + dev_info(dev, "Initialized %d port(s)\n", count); + + return ret; + + err_cleanup: + bcmasp_remove_intfs(priv); ++err_clock_disable: ++ clk_disable_unprepare(priv->clk); + + return ret; + } +-- +2.51.0 + diff --git a/queue-6.19/net-bcmasp-fix-double-free-of-wol-irq.patch b/queue-6.19/net-bcmasp-fix-double-free-of-wol-irq.patch new file mode 100644 index 0000000000..25fce52a33 --- /dev/null +++ b/queue-6.19/net-bcmasp-fix-double-free-of-wol-irq.patch @@ -0,0 +1,58 @@ +From 25e1ffa539b8a5cc3b0b5e9707f81113f3ada494 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 16:48:12 -0700 +Subject: net: bcmasp: fix double free of WoL irq + +From: Justin Chen + +[ Upstream commit cbfa5be2bf64511d49b854a0f9fd6d0b5118621f ] + +We do not need to free wol_irq since it was instantiated with +devm_request_irq(). So devres will free for us. + +Fixes: a2f0751206b0 ("net: bcmasp: Add support for WoL magic packet") +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260319234813.1937315-2-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index de5f540f78049..fac795ac0fcee 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1157,12 +1157,6 @@ void bcmasp_enable_wol(struct bcmasp_intf *intf, bool en) + } + } + +-static void bcmasp_wol_irq_destroy(struct bcmasp_priv *priv) +-{ +- if (priv->wol_irq > 0) +- free_irq(priv->wol_irq, priv); +-} +- + static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en) + { + u32 reg, phy_lpi_overwrite; +@@ -1368,7 +1362,6 @@ static int bcmasp_probe(struct platform_device *pdev) + return ret; + + err_cleanup: +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + + return ret; +@@ -1381,7 +1374,6 @@ static void bcmasp_remove(struct platform_device *pdev) + if (!priv) + return; + +- bcmasp_wol_irq_destroy(priv); + bcmasp_remove_intfs(priv); + } + +-- +2.51.0 + diff --git a/queue-6.19/net-bcmasp-streamline-early-exit-in-probe.patch b/queue-6.19/net-bcmasp-streamline-early-exit-in-probe.patch new file mode 100644 index 0000000000..d680afe438 --- /dev/null +++ b/queue-6.19/net-bcmasp-streamline-early-exit-in-probe.patch @@ -0,0 +1,88 @@ +From 253f85b0340df21cb4b6ad5870d56aababc1b3a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Jan 2026 11:49:49 -0800 +Subject: net: bcmasp: streamline early exit in probe + +From: Justin Chen + +[ Upstream commit 1fd1281250c38408d793863c8dcaa43c7de8932c ] + +Streamline the bcmasp_probe early exit. As support for other +functionality is added(i.e. ptp), it is easier to keep track of early +exit cleanup when it is all in one place. + +Signed-off-by: Justin Chen +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20260122194949.1145107-3-justin.chen@broadcom.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: cbfa5be2bf64 ("net: bcmasp: fix double free of WoL irq") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/asp2/bcmasp.c | 27 +++++++++++---------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +index 014340f33345a..de5f540f78049 100644 +--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c ++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c +@@ -1322,6 +1322,8 @@ static int bcmasp_probe(struct platform_device *pdev) + + bcmasp_core_init_filters(priv); + ++ bcmasp_init_wol(priv); ++ + ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports"); + if (!ports_node) { + dev_warn(dev, "No ports found\n"); +@@ -1333,16 +1335,14 @@ static int bcmasp_probe(struct platform_device *pdev) + intf = bcmasp_interface_create(priv, intf_node, i); + if (!intf) { + dev_err(dev, "Cannot create eth interface %d\n", i); +- bcmasp_remove_intfs(priv); +- ret = -ENOMEM; +- goto of_put_exit; ++ of_node_put(ports_node); ++ ret = -EINVAL; ++ goto err_cleanup; + } + list_add_tail(&intf->list, &priv->intfs); + i++; + } +- +- /* Check and enable WoL */ +- bcmasp_init_wol(priv); ++ of_node_put(ports_node); + + /* Drop the clock reference count now and let ndo_open()/ndo_close() + * manage it for us from now on. +@@ -1357,19 +1357,20 @@ static int bcmasp_probe(struct platform_device *pdev) + list_for_each_entry(intf, &priv->intfs, list) { + ret = register_netdev(intf->ndev); + if (ret) { +- netdev_err(intf->ndev, +- "failed to register net_device: %d\n", ret); +- bcmasp_wol_irq_destroy(priv); +- bcmasp_remove_intfs(priv); +- goto of_put_exit; ++ dev_err(dev, "failed to register net_device: %d\n", ret); ++ goto err_cleanup; + } + count++; + } + + dev_info(dev, "Initialized %d port(s)\n", count); + +-of_put_exit: +- of_node_put(ports_node); ++ return ret; ++ ++err_cleanup: ++ bcmasp_wol_irq_destroy(priv); ++ bcmasp_remove_intfs(priv); ++ + return ret; + } + +-- +2.51.0 + diff --git a/queue-6.19/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-6.19/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..4641905a28 --- /dev/null +++ b/queue-6.19/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From 3ba230a5f019b371ee785bf80625a878284bf9df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index fed89d4f1e1dc..2fe140ddebb23 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -813,6 +813,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-6.19/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-6.19/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..6916907536 --- /dev/null +++ b/queue-6.19/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From 33444c248f606e1714906d083acb0ea4c09531e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 494d628d10a51..070f7eba6b837 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3135,6 +3135,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-6.19/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch b/queue-6.19/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch new file mode 100644 index 0000000000..dbb3b5ceeb --- /dev/null +++ b/queue-6.19/net-lan743x-fix-duplex-configuration-in-mac_link_up.patch @@ -0,0 +1,49 @@ +From dae0284b9073e625c9fd523f4905e902bd4d88b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 12:23:45 +0530 +Subject: net: lan743x: fix duplex configuration in mac_link_up + +From: Thangaraj Samynathan + +[ Upstream commit 71399707876b93240f236f48b8062f3423a5fe97 ] + +The driver does not explicitly configure the MAC duplex mode when +bringing the link up. As a result, the MAC may retain a stale duplex +setting from a previous link state, leading to duplex mismatches with +the link partner and degraded network performance. + +Update lan743x_phylink_mac_link_up() to set or clear the MAC_CR_DPX_ +bit according to the negotiated duplex mode. + +This ensures the MAC configuration is consistent with the phylink +resolved state. + +Fixes: a5f199a8d8a03 ("net: lan743x: Migrate phylib to phylink") +Signed-off-by: Thangaraj Samynathan +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/20260323065345.144915-1-thangaraj.s@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index e4c542fc6c2b8..09d255e78f6cd 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -3054,6 +3054,11 @@ static void lan743x_phylink_mac_link_up(struct phylink_config *config, + else if (speed == SPEED_100) + mac_cr |= MAC_CR_CFG_L_; + ++ if (duplex == DUPLEX_FULL) ++ mac_cr |= MAC_CR_DPX_; ++ else ++ mac_cr &= ~MAC_CR_DPX_; ++ + lan743x_csr_write(adapter, MAC_CR, mac_cr); + + lan743x_ptp_update_latency(adapter, speed); +-- +2.51.0 + diff --git a/queue-6.19/net-macb-use-the-current-queue-number-for-stats.patch b/queue-6.19/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..684a3a0313 --- /dev/null +++ b/queue-6.19/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From a1d60ffc4d6bb0217e6e560690d9064d5ec57b41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 1a46e27bfbb4a..094e04980c782 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3224,7 +3224,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-6.19/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-6.19/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..e46c0df0fd --- /dev/null +++ b/queue-6.19/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From a4f8b7a8026d793126c231e90696f1389e6eecff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 6574f9bcdc026..c688dee96503f 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -151,11 +151,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -174,6 +178,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-6.19/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-6.19/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..f3c7fc00a7 --- /dev/null +++ b/queue-6.19/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From 7e198ab0c32eb5fba066476728fddf620134106d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index e7f1134453ef4..4a3d7b405132e 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -135,9 +135,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-6.19/net-ti-icssg-prueth-fix-use-after-free-of-cppi-descr.patch b/queue-6.19/net-ti-icssg-prueth-fix-use-after-free-of-cppi-descr.patch new file mode 100644 index 0000000000..25788a474c --- /dev/null +++ b/queue-6.19/net-ti-icssg-prueth-fix-use-after-free-of-cppi-descr.patch @@ -0,0 +1,73 @@ +From d02e598fd4f1e46a1d3e3f794efa4e3e8f1bc23a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:44:39 +0000 +Subject: net: ti: icssg-prueth: fix use-after-free of CPPI descriptor in RX + path + +From: David Carlier + +[ Upstream commit eb8c426c9803beb171f89d15fea17505eb517714 ] + +cppi5_hdesc_get_psdata() returns a pointer into the CPPI descriptor. +In both emac_rx_packet() and emac_rx_packet_zc(), the descriptor is +freed via k3_cppi_desc_pool_free() before the psdata pointer is used +by emac_rx_timestamp(), which dereferences psdata[0] and psdata[1]. +This constitutes a use-after-free on every received packet that goes +through the timestamp path. + +Defer the descriptor free until after all accesses through the psdata +pointer are complete. For emac_rx_packet(), move the free into the +requeue label so both early-exit and success paths free the descriptor +after all accesses are done. For emac_rx_packet_zc(), move the free to +the end of the loop body after emac_dispatch_skb_zc() (which calls +emac_rx_timestamp()) has returned. + +Fixes: 46eeb90f03e0 ("net: ti: icssg-prueth: Use page_pool API for RX buffer allocation") +Signed-off-by: David Carlier +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260320174439.41080-1-devnexen@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/icssg/icssg_common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c +index a9b5f86bc71bc..11d5b23a61bad 100644 +--- a/drivers/net/ethernet/ti/icssg/icssg_common.c ++++ b/drivers/net/ethernet/ti/icssg/icssg_common.c +@@ -962,7 +962,6 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id, + pkt_len -= 4; + cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL); + psdata = cppi5_hdesc_get_psdata(desc_rx); +- k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + count++; + xsk_buff_set_size(xdp, pkt_len); + xsk_buff_dma_sync_for_cpu(xdp); +@@ -988,6 +987,7 @@ static int emac_rx_packet_zc(struct prueth_emac *emac, u32 flow_id, + emac_dispatch_skb_zc(emac, xdp, psdata); + xsk_buff_free(xdp); + } ++ k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + } + + if (xdp_status & ICSSG_XDP_REDIR) +@@ -1057,7 +1057,6 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state) + /* firmware adds 4 CRC bytes, strip them */ + pkt_len -= 4; + cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL); +- k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + + /* if allocation fails we drop the packet but push the + * descriptor back to the ring with old page to prevent a stall +@@ -1115,6 +1114,7 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state) + ndev->stats.rx_packets++; + + requeue: ++ k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); + /* queue another RX DMA */ + ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page, + PRUETH_MAX_PKT_SIZE); +-- +2.51.0 + diff --git a/queue-6.19/net_sched-codel-fix-stale-state-for-empty-flows-in-f.patch b/queue-6.19/net_sched-codel-fix-stale-state-for-empty-flows-in-f.patch new file mode 100644 index 0000000000..0c70bf29e1 --- /dev/null +++ b/queue-6.19/net_sched-codel-fix-stale-state-for-empty-flows-in-f.patch @@ -0,0 +1,79 @@ +From 5923b4c4205495ecd72b901f88c9e5056ffddebd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 18:49:20 +0100 +Subject: net_sched: codel: fix stale state for empty flows in fq_codel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jonas Köppeler + +[ Upstream commit 815980fe6dbb01ad4007e8b260a45617f598b76d ] + +When codel_dequeue() finds an empty queue, it resets vars->dropping +but does not reset vars->first_above_time. The reference CoDel +algorithm (Nichols & Jacobson, ACM Queue 2012) resets both: + + dodeque_result codel_queue_t::dodeque(time_t now) { + ... + if (r.p == NULL) { + first_above_time = 0; // <-- Linux omits this + } + ... + } + +Note that codel_should_drop() does reset first_above_time when called +with a NULL skb, but codel_dequeue() returns early before ever calling +codel_should_drop() in the empty-queue case. The post-drop code paths +do reach codel_should_drop(NULL) and correctly reset the timer, so a +dropped packet breaks the cycle -- but the next delivered packet +re-arms first_above_time and the cycle repeats. + +For sparse flows such as ICMP ping (one packet every 200ms-1s), the +first packet arms first_above_time, the flow goes empty, and the +second packet arrives after the interval has elapsed and gets dropped. +The pattern repeats, producing sustained loss on flows that are not +actually congested. + +Test: veth pair, fq_codel, BQL disabled, 30000 iptables rules in the +consumer namespace (NAPI-64 cycle ~14ms, well above fq_codel's 5ms +target), ping at 5 pps under UDP flood: + + Before fix: 26% ping packet loss + After fix: 0% ping packet loss + +Fix by resetting first_above_time to zero in the empty-queue path +of codel_dequeue(), matching the reference algorithm. + +Fixes: 76e3cc126bb2 ("codel: Controlled Delay AQM") +Fixes: d068ca2ae2e6 ("codel: split into multiple files") +Co-developed-by: Jesper Dangaard Brouer +Signed-off-by: Jesper Dangaard Brouer +Signed-off-by: Jonas Köppeler +Reported-by: Chris Arges +Tested-by: Jonas Köppeler +Reviewed-by: Toke Høiland-Jørgensen +Link: https://lore.kernel.org/all/20260318134826.1281205-7-hawk@kernel.org/ +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20260323174920.253526-1-hawk@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/codel_impl.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/net/codel_impl.h b/include/net/codel_impl.h +index 78a27ac730700..b2c359c6dd1b8 100644 +--- a/include/net/codel_impl.h ++++ b/include/net/codel_impl.h +@@ -158,6 +158,7 @@ static struct sk_buff *codel_dequeue(void *ctx, + bool drop; + + if (!skb) { ++ vars->first_above_time = 0; + vars->dropping = false; + return skb; + } +-- +2.51.0 + diff --git a/queue-6.19/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-6.19/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..dab997f362 --- /dev/null +++ b/queue-6.19/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 68ca1677b68368fccb5560cab9083a66519779ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index d9f33a6c807c8..fea750653e967 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -909,8 +909,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -924,17 +924,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2633,7 +2627,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 0c1d086e96cb3..b67426c2189b2 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1385,9 +1385,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1414,10 +1414,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-6.19/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-6.19/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..d1d932b46a --- /dev/null +++ b/queue-6.19/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From acc9733f0585e14f47f576456d1f2c8b6127e105 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-6.19/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-6.19/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..dbfbb442fc --- /dev/null +++ b/queue-6.19/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From 55c2fd31c8766843c68df7f57e5858594b829179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index cfc2daa3fc7f3..227fb5dc39e27 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-6.19/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-6.19/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..ceede52878 --- /dev/null +++ b/queue-6.19/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From d3937bebf86f04eb872304e1c6fe7075383ba1d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 4ab5ef71d96db..17af0ff4ea7ab 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-6.19/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-6.19/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..91c4e13e36 --- /dev/null +++ b/queue-6.19/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From 0b07c7d9bc04c6dce296c60d7c5b25110f6cd691 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index bfcb9cd335bff..27dd35224e629 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -647,15 +647,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-6.19/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch b/queue-6.19/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch new file mode 100644 index 0000000000..6268650947 --- /dev/null +++ b/queue-6.19/netfilter-nft_set_rbtree-revisit-array-resize-logic.patch @@ -0,0 +1,189 @@ +From d27994bb3a89b8ab608019f3d52f374e32fd0848 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:01 +0100 +Subject: netfilter: nft_set_rbtree: revisit array resize logic + +From: Pablo Neira Ayuso + +[ Upstream commit fafdd92b9e30fe057740c5bb5cd4f92ecea9bf26 ] + +Chris Arges reports high memory consumption with thousands of +containers, this patch revisits the array allocation logic. + +For anonymous sets, start by 16 slots (which takes 256 bytes on x86_64). +Expand it by x2 until threshold of 512 slots is reached, over that +threshold, expand it by x1.5. + +For non-anonymous set, start by 1024 slots in the array (which takes 16 +Kbytes initially on x86_64). Expand it by x1.5. + +Use set->ndeact to subtract deactivated elements when calculating the +number of the slots in the array, otherwise the array size array gets +increased artifically. Add special case shrink logic to deal with flush +set too. + +The shrink logic is skipped by anonymous sets. + +Use check_add_overflow() to calculate the new array size. + +Add a WARN_ON_ONCE check to make sure elements fit into the new array +size. + +Reported-by: Chris Arges +Fixes: 7e43e0a1141d ("netfilter: nft_set_rbtree: translate rbtree to array for binary search") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_set_rbtree.c | 92 +++++++++++++++++++++++++++------- + 1 file changed, 75 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 5d91b7d08d33a..154bf2772e27d 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -572,14 +572,12 @@ static struct nft_array *nft_array_alloc(u32 max_intervals) + return array; + } + +-#define NFT_ARRAY_EXTRA_SIZE 10240 +- + /* Similar to nft_rbtree_{u,k}size to hide details to userspace, but consider + * packed representation coming from userspace for anonymous sets too. + */ + static u32 nft_array_elems(const struct nft_set *set) + { +- u32 nelems = atomic_read(&set->nelems); ++ u32 nelems = atomic_read(&set->nelems) - set->ndeact; + + /* Adjacent intervals are represented with a single start element in + * anonymous sets, use the current element counter as is. +@@ -595,27 +593,87 @@ static u32 nft_array_elems(const struct nft_set *set) + return (nelems / 2) + 2; + } + +-static int nft_array_may_resize(const struct nft_set *set) ++#define NFT_ARRAY_INITIAL_SIZE 1024 ++#define NFT_ARRAY_INITIAL_ANON_SIZE 16 ++#define NFT_ARRAY_INITIAL_ANON_THRESH (8192U / sizeof(struct nft_array_interval)) ++ ++static int nft_array_may_resize(const struct nft_set *set, bool flush) + { +- u32 nelems = nft_array_elems(set), new_max_intervals; ++ u32 initial_intervals, max_intervals, new_max_intervals, delta; ++ u32 shrinked_max_intervals, nelems = nft_array_elems(set); + struct nft_rbtree *priv = nft_set_priv(set); + struct nft_array *array; + +- if (!priv->array_next) { +- array = nft_array_alloc(nelems + NFT_ARRAY_EXTRA_SIZE); +- if (!array) +- return -ENOMEM; ++ if (nft_set_is_anonymous(set)) ++ initial_intervals = NFT_ARRAY_INITIAL_ANON_SIZE; ++ else ++ initial_intervals = NFT_ARRAY_INITIAL_SIZE; ++ ++ if (priv->array_next) { ++ max_intervals = priv->array_next->max_intervals; ++ new_max_intervals = priv->array_next->max_intervals; ++ } else { ++ if (priv->array) { ++ max_intervals = priv->array->max_intervals; ++ new_max_intervals = priv->array->max_intervals; ++ } else { ++ max_intervals = 0; ++ new_max_intervals = initial_intervals; ++ } ++ } + +- priv->array_next = array; ++ if (nft_set_is_anonymous(set)) ++ goto maybe_grow; ++ ++ if (flush) { ++ /* Set flush just started, nelems still report elements.*/ ++ nelems = 0; ++ new_max_intervals = NFT_ARRAY_INITIAL_SIZE; ++ goto realloc_array; + } + +- if (nelems < priv->array_next->max_intervals) +- return 0; ++ if (check_add_overflow(new_max_intervals, new_max_intervals, ++ &shrinked_max_intervals)) ++ return -EOVERFLOW; ++ ++ shrinked_max_intervals = DIV_ROUND_UP(shrinked_max_intervals, 3); + +- new_max_intervals = priv->array_next->max_intervals + NFT_ARRAY_EXTRA_SIZE; +- if (nft_array_intervals_alloc(priv->array_next, new_max_intervals) < 0) ++ if (shrinked_max_intervals > NFT_ARRAY_INITIAL_SIZE && ++ nelems < shrinked_max_intervals) { ++ new_max_intervals = shrinked_max_intervals; ++ goto realloc_array; ++ } ++maybe_grow: ++ if (nelems > new_max_intervals) { ++ if (nft_set_is_anonymous(set) && ++ new_max_intervals < NFT_ARRAY_INITIAL_ANON_THRESH) { ++ new_max_intervals <<= 1; ++ } else { ++ delta = new_max_intervals >> 1; ++ if (check_add_overflow(new_max_intervals, delta, ++ &new_max_intervals)) ++ return -EOVERFLOW; ++ } ++ } ++ ++realloc_array: ++ if (WARN_ON_ONCE(nelems > new_max_intervals)) + return -ENOMEM; + ++ if (priv->array_next) { ++ if (max_intervals == new_max_intervals) ++ return 0; ++ ++ if (nft_array_intervals_alloc(priv->array_next, new_max_intervals) < 0) ++ return -ENOMEM; ++ } else { ++ array = nft_array_alloc(new_max_intervals); ++ if (!array) ++ return -ENOMEM; ++ ++ priv->array_next = array; ++ } ++ + return 0; + } + +@@ -630,7 +688,7 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, + + nft_rbtree_maybe_reset_start_cookie(priv, tstamp); + +- if (nft_array_may_resize(set) < 0) ++ if (nft_array_may_resize(set, false) < 0) + return -ENOMEM; + + do { +@@ -741,7 +799,7 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, + nft_rbtree_interval_null(set, this)) + priv->start_rbe_cookie = 0; + +- if (nft_array_may_resize(set) < 0) ++ if (nft_array_may_resize(set, false) < 0) + return NULL; + + while (parent != NULL) { +@@ -811,7 +869,7 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, + + switch (iter->type) { + case NFT_ITER_UPDATE_CLONE: +- if (nft_array_may_resize(set) < 0) { ++ if (nft_array_may_resize(set, true) < 0) { + iter->err = -ENOMEM; + break; + } +-- +2.51.0 + diff --git a/queue-6.19/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-6.19/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..733d823b2b --- /dev/null +++ b/queue-6.19/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From a7df74fde6c266ea6ef1dd3b1a28edca0ce32912 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index d334b7aa8c172..25ba4cbb00e1e 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -579,8 +579,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -592,13 +591,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + timer_delete_sync(&ndev->cmd_timer); +@@ -613,6 +612,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.19/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch b/queue-6.19/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch new file mode 100644 index 0000000000..bd8db44a07 --- /dev/null +++ b/queue-6.19/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch @@ -0,0 +1,50 @@ +From 562f184850981866e8982691407f6212653c6b12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 07:42:41 +0000 +Subject: openvswitch: defer tunnel netdev_put to RCU release + +From: Yang Yang + +[ Upstream commit 6931d21f87bc6d657f145798fad0bf077b82486c ] + +ovs_netdev_tunnel_destroy() may run after NETDEV_UNREGISTER already +detached the device. Dropping the netdev reference in destroy can race +with concurrent readers that still observe vport->dev. + +Do not release vport->dev in ovs_netdev_tunnel_destroy(). Instead, let +vport_netdev_free() drop the reference from the RCU callback, matching +the non-tunnel destroy path and avoiding additional synchronization +under RTNL. + +Fixes: a9020fde67a6 ("openvswitch: Move tunnel destroy function to oppenvswitch module.") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319074241.3405262-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index c688dee96503f..12055af832dc0 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -196,8 +196,6 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + */ + if (vport->dev->reg_state == NETREG_REGISTERED) + rtnl_delete_link(vport->dev, 0, NULL); +- netdev_put(vport->dev, &vport->dev_tracker); +- vport->dev = NULL; + rtnl_unlock(); + + call_rcu(&vport->rcu, vport_netdev_free); +-- +2.51.0 + diff --git a/queue-6.19/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-6.19/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..ea9549e5a4 --- /dev/null +++ b/queue-6.19/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From e5bc3d3ead82c2c96edf95b4189de9cf7fadd936 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 2d536901309ea..2dc4a6c2aecec 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2953,6 +2953,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-6.19/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-6.19/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..547455be4f --- /dev/null +++ b/queue-6.19/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From 92186fc5d75ad1bcaa948e61821f67a1465ccf7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index d6a46fe0cda89..3f518dce6d23f 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1135,9 +1135,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-6.19/pinctrl-qcom-spmi-gpio-implement-.get_direction.patch b/queue-6.19/pinctrl-qcom-spmi-gpio-implement-.get_direction.patch new file mode 100644 index 0000000000..dd59eaccb3 --- /dev/null +++ b/queue-6.19/pinctrl-qcom-spmi-gpio-implement-.get_direction.patch @@ -0,0 +1,67 @@ +From c19391e96b7774f8a7d52ec7206d2d03ab172683 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Mar 2026 18:41:08 +0100 +Subject: pinctrl: qcom: spmi-gpio: implement .get_direction() + +From: Neil Armstrong + +[ Upstream commit 263447532463cf4444a3595e835b99a4e90952fa ] + +GPIO controller driver should typically implement the .get_direction() +callback as GPIOLIB internals may try to use it to determine the state +of a pin. Since introduction of shared proxy, it prints a warning splat +when using a shared spmi gpio. + +The implementation is not easy because the controller supports enabling +the input and output logic at the same time, so we aligns on the +behaviour of the .get() operation and return -EINVAL in other +situations. + +Fixes: eadff3024472 ("pinctrl: Qualcomm SPMI PMIC GPIO pin controller driver") +Fixes: d7b5f5cc5eb4 ("pinctrl: qcom: spmi-gpio: Add support for GPIO LV/MV subtype") +Signed-off-by: Neil Armstrong +Reviewed-by: Konrad Dybcio +Reviewed-by: Bartosz Golaszewski +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +index 83f940fe30b26..d02d42513ebbc 100644 +--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c ++++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +@@ -723,6 +723,21 @@ static const struct pinconf_ops pmic_gpio_pinconf_ops = { + .pin_config_group_dbg_show = pmic_gpio_config_dbg_show, + }; + ++static int pmic_gpio_get_direction(struct gpio_chip *chip, unsigned pin) ++{ ++ struct pmic_gpio_state *state = gpiochip_get_data(chip); ++ struct pmic_gpio_pad *pad; ++ ++ pad = state->ctrl->desc->pins[pin].drv_data; ++ ++ if (!pad->is_enabled || pad->analog_pass || ++ (!pad->input_enabled && !pad->output_enabled)) ++ return -EINVAL; ++ ++ /* Make sure the state is aligned on what pmic_gpio_get() returns */ ++ return pad->input_enabled ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT; ++} ++ + static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned pin) + { + struct pmic_gpio_state *state = gpiochip_get_data(chip); +@@ -801,6 +816,7 @@ static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) + } + + static const struct gpio_chip pmic_gpio_gpio_template = { ++ .get_direction = pmic_gpio_get_direction, + .direction_input = pmic_gpio_direction_input, + .direction_output = pmic_gpio_direction_output, + .get = pmic_gpio_get, +-- +2.51.0 + diff --git a/queue-6.19/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch b/queue-6.19/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch new file mode 100644 index 0000000000..94eac4596b --- /dev/null +++ b/queue-6.19/pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch @@ -0,0 +1,42 @@ +From 5d26bd5a1651a1052f6d96a74fa9094feb2a4fc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Feb 2026 12:58:09 -0800 +Subject: pinctrl: renesas: rza1: Normalize return value of gpio_get() + +From: Dmitry Torokhov + +[ Upstream commit fb22bb9701d48c4b0e81fe204c2f96a37a520568 ] + +The GPIO .get() callback is expected to return 0 or 1 (or a negative +error code). Ensure that the value returned by rza1_gpio_get() is +normalized to the [0, 1] range. + +Fixes: 86ef402d805d606a ("gpiolib: sanitize the return value of gpio_chip::get()") +Signed-off-by: Dmitry Torokhov +Reviewed-by: Andy Shevchenko +Reviewed-by: Bartosz Golaszewski +Reviewed-by: Linus Walleij +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/aZYnyl-Nf4S1U2yj@google.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rza1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rza1.c b/drivers/pinctrl/renesas/pinctrl-rza1.c +index 3cfa4c8be80ea..d83c7d8ee82c4 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rza1.c ++++ b/drivers/pinctrl/renesas/pinctrl-rza1.c +@@ -589,7 +589,7 @@ static inline unsigned int rza1_get_bit(struct rza1_port *port, + { + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id); + +- return ioread16(mem) & BIT(bit); ++ return !!(ioread16(mem) & BIT(bit)); + } + + /** +-- +2.51.0 + diff --git a/queue-6.19/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch b/queue-6.19/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch new file mode 100644 index 0000000000..e591c1eade --- /dev/null +++ b/queue-6.19/pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch @@ -0,0 +1,44 @@ +From 3eec7ac217dd3484d92f01a129af98dfd49e1b26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jan 2026 00:35:47 +0800 +Subject: pinctrl: renesas: rzt2h: Fix device node leak in + rzt2h_gpio_register() + +From: Felix Gu + +[ Upstream commit e825c79ef914bd55cf7c2476ddcfb2738eb689c3 ] + +When calling of_parse_phandle_with_fixed_args(), the caller is +responsible for calling of_node_put() to release the device node +reference. + +In rzt2h_gpio_register(), the driver fails to call of_node_put() to +release the reference in of_args.np, which causes a memory leak. + +Add the missing of_node_put() call to fix the leak. + +Fixes: 34d4d093077a ("pinctrl: renesas: Add support for RZ/T2H") +Signed-off-by: Felix Gu +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20260127-rzt2h-v1-1-86472e7421b8@gmail.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzt2h.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c +index 40df706210119..24b90c80f5131 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c +@@ -648,6 +648,7 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) + if (ret) + return dev_err_probe(dev, ret, "Unable to parse gpio-ranges\n"); + ++ of_node_put(of_args.np); + if (of_args.args[0] != 0 || of_args.args[1] != 0 || + of_args.args[2] != pctrl->data->n_port_pins) + return dev_err_probe(dev, -EINVAL, +-- +2.51.0 + diff --git a/queue-6.19/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch b/queue-6.19/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch new file mode 100644 index 0000000000..baaa27ac65 --- /dev/null +++ b/queue-6.19/pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch @@ -0,0 +1,36 @@ +From 442c9930522e6d6a8d898574820837b80d5cf9ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:06:54 +0100 +Subject: pinctrl: stm32: fix HDP driver dependency on GPIO_GENERIC + +From: Amelie Delaunay + +[ Upstream commit c8cfeb4b9dda2cdfce79519aee4aaff16310a7b6 ] + +The HDP driver uses the generic GPIO chip API, but this configuration +may not be enabled. +Ensure it is enabled by selecting the appropriate option. + +Fixes: 4bcff9c05b9d ("pinctrl: stm32: use new generic GPIO chip API") +Signed-off-by: Amelie Delaunay +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/stm32/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig +index 5f67e1ee66dd9..d6a1715230121 100644 +--- a/drivers/pinctrl/stm32/Kconfig ++++ b/drivers/pinctrl/stm32/Kconfig +@@ -65,6 +65,7 @@ config PINCTRL_STM32_HDP + select PINMUX + select GENERIC_PINCONF + select GPIOLIB ++ select GPIO_GENERIC + help + The Hardware Debug Port allows the observation of internal signals. + It uses configurable multiplexer to route signals in a dedicated observation register. +-- +2.51.0 + diff --git a/queue-6.19/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-6.19/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..d1e41bfdd5 --- /dev/null +++ b/queue-6.19/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From a215b6b553ebc3bfddeb7d39e98724986f7ee677 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index fa7b3bda688a6..bee271a4fda1a 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-6.19/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch b/queue-6.19/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch new file mode 100644 index 0000000000..1dc5558e6a --- /dev/null +++ b/queue-6.19/platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch @@ -0,0 +1,62 @@ +From 87d90f3f054ba7681aa788533d0e2e8c555a042d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Feb 2026 19:16:24 -0400 +Subject: platform/x86: intel-hid: disable wakeup_mode during hibernation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David McFarland + +[ Upstream commit e02ea3ae8ee40d5835a845884c7b161a27c10bcb ] + +Add a freeze handler which clears wakeup_mode. This fixes aborted hibernation on +Dell Precision 3880. + + Wakeup event detected during hibernation, rolling back + +This system sends power button events during hibernation, even when triggered by +software. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218634 +Fixes: 0c4cae1bc00d ("PM: hibernate: Avoid missing wakeup events during hibernation") +Signed-off-by: David McFarland +Link: https://patch.msgid.link/20260205231629.1336348-1-corngood@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/hid.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index f2b309f6e458a..c5e80887d0cb0 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -432,6 +432,14 @@ static int intel_hid_pl_suspend_handler(struct device *device) + return 0; + } + ++static int intel_hid_pl_freeze_handler(struct device *device) ++{ ++ struct intel_hid_priv *priv = dev_get_drvdata(device); ++ ++ priv->wakeup_mode = false; ++ return intel_hid_pl_suspend_handler(device); ++} ++ + static int intel_hid_pl_resume_handler(struct device *device) + { + intel_hid_pm_complete(device); +@@ -446,7 +454,7 @@ static int intel_hid_pl_resume_handler(struct device *device) + static const struct dev_pm_ops intel_hid_pl_pm_ops = { + .prepare = intel_hid_pm_prepare, + .complete = intel_hid_pm_complete, +- .freeze = intel_hid_pl_suspend_handler, ++ .freeze = intel_hid_pl_freeze_handler, + .thaw = intel_hid_pl_resume_handler, + .restore = intel_hid_pl_resume_handler, + .suspend = intel_hid_pl_suspend_handler, +-- +2.51.0 + diff --git a/queue-6.19/platform-x86-isst-check-hwp-support-before-msr-acces.patch b/queue-6.19/platform-x86-isst-check-hwp-support-before-msr-acces.patch new file mode 100644 index 0000000000..b9f3ab013d --- /dev/null +++ b/queue-6.19/platform-x86-isst-check-hwp-support-before-msr-acces.patch @@ -0,0 +1,66 @@ +From a0a28f8a42151efe9eaac75cd974e55f4d62a1f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Mar 2026 02:46:35 -0500 +Subject: platform/x86: ISST: Check HWP support before MSR access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Li RongQing + +[ Upstream commit 9f11d9b15efb5f77e810b6dfbeb01b4650a79eae ] + +On some systems, HWP can be explicitly disabled in the BIOS settings +When HWP is disabled by firmware, the HWP CPUID bit is not set, and +attempting to read MSR_PM_ENABLE will result in a General Protection +(GP) fault. + + unchecked MSR access error: RDMSR from 0x770 at rIP: 0xffffffffc33db92e (disable_dynamic_sst_features+0xe/0x50 [isst_tpmi_core]) + Call Trace: + + ? ex_handler_msr+0xf6/0x150 + ? fixup_exception+0x1ad/0x340 + ? gp_try_fixup_and_notify+0x1e/0xb0 + ? exc_general_protection+0xc9/0x390 + ? terminate_walk+0x64/0x100 + ? asm_exc_general_protection+0x22/0x30 + ? disable_dynamic_sst_features+0xe/0x50 [isst_tpmi_core] + isst_if_def_ioctl+0xece/0x1050 [isst_tpmi_core] + ? ioctl_has_perm.constprop.42+0xe0/0x130 + isst_if_def_ioctl+0x10d/0x1a0 [isst_if_common] + __se_sys_ioctl+0x86/0xc0 + do_syscall_64+0x8a/0x100 + entry_SYSCALL_64_after_hwframe+0x78/0xe2 + RIP: 0033:0x7f36eaef54a7 + +Add a check for X86_FEATURE_HWP before accessing the MSR. If HWP is +not available, return true safely. + +Fixes: 12a7d2cb811d ("platform/x86: ISST: Add SST-CP support via TPMI") +Signed-off-by: Li RongQing +Acked-by: Srinivas Pandruvada +Link: https://patch.msgid.link/20260303074635.2218-1-lirongqing@baidu.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +index 13b11c3a2ec4e..e657b88bfd36e 100644 +--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c ++++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +@@ -558,6 +558,9 @@ static bool disable_dynamic_sst_features(void) + { + u64 value; + ++ if (!static_cpu_has(X86_FEATURE_HWP)) ++ return true; ++ + rdmsrq(MSR_PM_ENABLE, value); + return !(value & 0x1); + } +-- +2.51.0 + diff --git a/queue-6.19/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch b/queue-6.19/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch new file mode 100644 index 0000000000..17a0d82c39 --- /dev/null +++ b/queue-6.19/platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch @@ -0,0 +1,59 @@ +From 92282a517d99957fa90d21efeb7a9c3f441d1b85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 14:06:34 -0700 +Subject: platform/x86: lenovo: wmi-gamezone: Drop gz_chain_head +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nathan Chancellor + +[ Upstream commit 5a3955f3602950d1888df743a5b1889e43b5cb60 ] + +The gz_chain_head variable has been unused since the driver's initial +addition to the tree. Its use was eliminated between v3 and v4 during +development but due to the reference of gz_chain_head's wait_list +member, the compiler could not warn that it was unused. + +After a (tip) commit ("locking/rwsem: Remove the list_head from struct +rw_semaphore"), which removed a reference to the variable passed to +__RWSEM_INITIALIZER(), certain configurations show an unused variable +warning from the Lenovo wmi-gamezone driver: + + drivers/platform/x86/lenovo/wmi-gamezone.c:34:31: warning: 'gz_chain_head' defined but not used [-Wunused-variable] + 34 | static BLOCKING_NOTIFIER_HEAD(gz_chain_head); + | ^~~~~~~~~~~~~ + include/linux/notifier.h:119:39: note: in definition of macro 'BLOCKING_NOTIFIER_HEAD' + 119 | struct blocking_notifier_head name = \ + | ^~~~ + +Remove the variable to prevent the warning from showing up. + +Fixes: 22024ac5366f ("platform/x86: Add Lenovo Gamezone WMI Driver") +Signed-off-by: Nathan Chancellor +Reviewed-by: Mark Pearson +Link: https://patch.msgid.link/20260313-lenovo-wmi-gamezone-remove-gz_chain_head-v1-1-ce5231f0c6fa@kernel.org +[ij: reorganized the changelog] +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/lenovo/wmi-gamezone.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/platform/x86/lenovo/wmi-gamezone.c b/drivers/platform/x86/lenovo/wmi-gamezone.c +index 381836d29a964..c7fe7e3c9f179 100644 +--- a/drivers/platform/x86/lenovo/wmi-gamezone.c ++++ b/drivers/platform/x86/lenovo/wmi-gamezone.c +@@ -31,8 +31,6 @@ + #define LWMI_GZ_METHOD_ID_SMARTFAN_SET 44 + #define LWMI_GZ_METHOD_ID_SMARTFAN_GET 45 + +-static BLOCKING_NOTIFIER_HEAD(gz_chain_head); +- + struct lwmi_gz_priv { + enum thermal_mode current_mode; + struct notifier_block event_nb; +-- +2.51.0 + diff --git a/queue-6.19/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-6.19/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..343ebf1b48 --- /dev/null +++ b/queue-6.19/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From 7c44d393c150df4340012ca8669a24d30d0cf6cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 63cbba9e46b93..6cdf6ee8be216 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -707,11 +707,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-6.19/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch b/queue-6.19/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch new file mode 100644 index 0000000000..e318aaebe3 --- /dev/null +++ b/queue-6.19/rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch @@ -0,0 +1,59 @@ +From 14e4d85c6ac5f5f4b8cb8e2d1e76ccaacdc64101 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:52 +0100 +Subject: rtnetlink: count IFLA_PARENT_DEV_{NAME,BUS_NAME} in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit 52501989c76206462d9b11a8485beef40ef41821 ] + +Commit 00e77ed8e64d ("rtnetlink: add IFLA_PARENT_[DEV|DEV_BUS]_NAME") +added those attributes to rtnl_fill_ifinfo, but forgot to extend +if_nlmsg_size. + +Fixes: 00e77ed8e64d ("rtnetlink: add IFLA_PARENT_[DEV|DEV_BUS]_NAME") +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/0b849da95562af45487080528d60f578636aba5c.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index b1ed55141d8a7..63cbba9e46b93 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1267,6 +1267,21 @@ static size_t rtnl_dpll_pin_size(const struct net_device *dev) + return size; + } + ++static size_t rtnl_dev_parent_size(const struct net_device *dev) ++{ ++ size_t size = 0; ++ ++ /* IFLA_PARENT_DEV_NAME */ ++ if (dev->dev.parent) ++ size += nla_total_size(strlen(dev_name(dev->dev.parent)) + 1); ++ ++ /* IFLA_PARENT_DEV_BUS_NAME */ ++ if (dev->dev.parent && dev->dev.parent->bus) ++ size += nla_total_size(strlen(dev->dev.parent->bus->name) + 1); ++ ++ return size; ++} ++ + static noinline size_t if_nlmsg_size(const struct net_device *dev, + u32 ext_filter_mask) + { +@@ -1328,6 +1343,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + + nla_total_size(8) /* IFLA_MAX_PACING_OFFLOAD_HORIZON */ + + nla_total_size(2) /* IFLA_HEADROOM */ + + nla_total_size(2) /* IFLA_TAILROOM */ ++ + rtnl_dev_parent_size(dev) + + 0; + + if (!(ext_filter_mask & RTEXT_FILTER_SKIP_STATS)) +-- +2.51.0 + diff --git a/queue-6.19/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch b/queue-6.19/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch new file mode 100644 index 0000000000..a264dcbab4 --- /dev/null +++ b/queue-6.19/rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch @@ -0,0 +1,40 @@ +From 6eb027b56ea15fc10eddd90259a253d8494404b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 16:19:43 +0100 +Subject: rtnetlink: fix leak of SRCU struct in rtnl_link_register + +From: Sabrina Dubroca + +[ Upstream commit 09474055f2619be9445ba4245e4013741ed01a5e ] + +Commit 6b57ff21a310 ("rtnetlink: Protect link_ops by mutex.") swapped +the EEXIST check with the init_srcu_struct, but didn't add cleanup of +the SRCU struct we just allocated in case of error. + +Fixes: 6b57ff21a310 ("rtnetlink: Protect link_ops by mutex.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/e77fe499f9a58c547b33b5212b3596dad417cec6.1774025341.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 6cdf6ee8be216..11cdad3972ad8 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -629,6 +629,9 @@ int rtnl_link_register(struct rtnl_link_ops *ops) + unlock: + mutex_unlock(&link_ops_mutex); + ++ if (err) ++ cleanup_srcu_struct(&ops->srcu); ++ + return err; + } + EXPORT_SYMBOL_GPL(rtnl_link_register); +-- +2.51.0 + diff --git a/queue-6.19/series b/queue-6.19/series index 3c27f20d18..f90e913c16 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -75,3 +75,72 @@ spi-intel-pci-add-support-for-nova-lake-mobile-spi-f.patch alsa-usb-audio-add-iface-reset-and-delay-quirk-for-s.patch alsa-hda-realtek-add-quirk-for-asus-um6702rc.patch i3c-master-dw-i3c-fix-missing-of_node-for-virtual-i2.patch +xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch +xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +pinctrl-renesas-rzt2h-fix-device-node-leak-in-rzt2h_.patch +xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch +pinctrl-qcom-spmi-gpio-implement-.get_direction.patch +pinctrl-renesas-rza1-normalize-return-value-of-gpio_.patch +xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch +xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch +af_key-validate-families-in-pfkey_send_migrate.patch +dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch +erofs-set-fileio-bio-failed-in-short-read-case.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +pinctrl-stm32-fix-hdp-driver-dependency-on-gpio_gene.patch +bluetooth-l2cap-fix-stack-out-of-bounds-read-in-l2ca.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-mgmt-fix-dangling-pointer-on-mgmt_add_adv_.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_parent_dev_-name-bus_name-in-if.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +net-bcmasp-streamline-early-exit-in-probe.patch +net-bcmasp-fix-double-free-of-wol-irq.patch +net-bcmasp-fix-double-disable-of-clk.patch +platform-x86-isst-check-hwp-support-before-msr-acces.patch +platform-x86-lenovo-wmi-gamezone-drop-gz_chain_head.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +platform-x86-intel-hid-disable-wakeup_mode-during-hi.patch +ice-fix-inverted-ready-check-for-vf-representors.patch +ice-use-ice_update_eth_stats-for-representor-stats.patch +iavf-fix-out-of-bounds-writes-in-iavf_get_ethtool_st.patch +ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch +ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +net-airoha-add-rcu-lock-around-dev_fill_forward_path.patch +net-b44-always-select-config_fixed_phy.patch +udp-fix-wildcard-bind-conflict-check-when-using-hash.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch +virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch +team-fix-header_ops-type-confusion-with-non-ethernet.patch +net-ti-icssg-prueth-fix-use-after-free-of-cppi-descr.patch +net-lan743x-fix-duplex-configuration-in-mac_link_up.patch +rtnetlink-fix-leak-of-srcu-struct-in-rtnl_link_regis.patch +net_sched-codel-fix-stale-state-for-empty-flows-in-f.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch +bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch +bluetooth-l2cap-fix-not-tracking-outstanding-tx-iden.patch +bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +tls-purge-async_hold-in-tls_decrypt_async_wait.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nft_set_rbtree-revisit-array-resize-logic.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-6.19/team-fix-header_ops-type-confusion-with-non-ethernet.patch b/queue-6.19/team-fix-header_ops-type-confusion-with-non-ethernet.patch new file mode 100644 index 0000000000..0f2870ad95 --- /dev/null +++ b/queue-6.19/team-fix-header_ops-type-confusion-with-non-ethernet.patch @@ -0,0 +1,132 @@ +From 567a62298354bbcf845a538246d41c6d3636c44c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 15:21:26 +0800 +Subject: team: fix header_ops type confusion with non-Ethernet ports + +From: Jiayuan Chen + +[ Upstream commit 425000dbf17373a4ab8be9428f5dc055ef870a56 ] + +Similar to commit 950803f72547 ("bonding: fix type confusion in +bond_setup_by_slave()") team has the same class of header_ops type +confusion. + +For non-Ethernet ports, team_setup_by_port() copies port_dev->header_ops +directly. When the team device later calls dev_hard_header() or +dev_parse_header(), these callbacks can run with the team net_device +instead of the real lower device, so netdev_priv(dev) is interpreted as +the wrong private type and can crash. + +The syzbot report shows a crash in bond_header_create(), but the root +cause is in team: the topology is gre -> bond -> team, and team calls +the inherited header_ops with its own net_device instead of the lower +device, so bond_header_create() receives a team device and interprets +netdev_priv() as bonding private data, causing a type confusion crash. + +Fix this by introducing team header_ops wrappers for create/parse, +selecting a team port under RCU, and calling the lower device callbacks +with port->dev, so each callback always sees the correct net_device +context. + +Also pass the selected lower device to the lower parse callback, so +recursion is bounded in stacked non-Ethernet topologies and parse +callbacks always run with the correct device context. + +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Reported-by: syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/69b46af7.050a0220.36eb34.000e.GAE@google.com/T/ +Cc: Jiayuan Chen +Signed-off-by: Jiayuan Chen +Link: https://patch.msgid.link/20260320072139.134249-2-jiayuan.chen@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/team/team_core.c | 65 +++++++++++++++++++++++++++++++++++- + 1 file changed, 64 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c +index a0fe998cc055d..98772d749f2bf 100644 +--- a/drivers/net/team/team_core.c ++++ b/drivers/net/team/team_core.c +@@ -2060,6 +2060,68 @@ static const struct ethtool_ops team_ethtool_ops = { + * rt netlink interface + ***********************/ + ++/* For tx path we need a linkup && enabled port and for parse any port ++ * suffices. ++ */ ++static struct team_port *team_header_port_get_rcu(struct team *team, ++ bool txable) ++{ ++ struct team_port *port; ++ ++ list_for_each_entry_rcu(port, &team->port_list, list) { ++ if (!txable || team_port_txable(port)) ++ return port; ++ } ++ ++ return NULL; ++} ++ ++static int team_header_create(struct sk_buff *skb, struct net_device *team_dev, ++ unsigned short type, const void *daddr, ++ const void *saddr, unsigned int len) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, true); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->create) ++ ret = port_ops->create(skb, port->dev, ++ type, daddr, saddr, len); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static int team_header_parse(const struct sk_buff *skb, ++ const struct net_device *team_dev, ++ unsigned char *haddr) ++{ ++ struct team *team = netdev_priv(team_dev); ++ const struct header_ops *port_ops; ++ struct team_port *port; ++ int ret = 0; ++ ++ rcu_read_lock(); ++ port = team_header_port_get_rcu(team, false); ++ if (port) { ++ port_ops = READ_ONCE(port->dev->header_ops); ++ if (port_ops && port_ops->parse) ++ ret = port_ops->parse(skb, port->dev, haddr); ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static const struct header_ops team_header_ops = { ++ .create = team_header_create, ++ .parse = team_header_parse, ++}; ++ + static void team_setup_by_port(struct net_device *dev, + struct net_device *port_dev) + { +@@ -2068,7 +2130,8 @@ static void team_setup_by_port(struct net_device *dev, + if (port_dev->type == ARPHRD_ETHER) + dev->header_ops = team->header_ops_cache; + else +- dev->header_ops = port_dev->header_ops; ++ dev->header_ops = port_dev->header_ops ? ++ &team_header_ops : NULL; + dev->type = port_dev->type; + dev->hard_header_len = port_dev->hard_header_len; + dev->needed_headroom = port_dev->needed_headroom; +-- +2.51.0 + diff --git a/queue-6.19/tls-purge-async_hold-in-tls_decrypt_async_wait.patch b/queue-6.19/tls-purge-async_hold-in-tls_decrypt_async_wait.patch new file mode 100644 index 0000000000..a14f186317 --- /dev/null +++ b/queue-6.19/tls-purge-async_hold-in-tls_decrypt_async_wait.patch @@ -0,0 +1,66 @@ +From 07c5fc7785ea4ce1478dbbcf7aa9d6c33b9ae0f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 08:53:23 -0400 +Subject: tls: Purge async_hold in tls_decrypt_async_wait() + +From: Chuck Lever + +[ Upstream commit 84a8335d8300576f1b377ae24abca1d9f197807f ] + +The async_hold queue pins encrypted input skbs while +the AEAD engine references their scatterlist data. Once +tls_decrypt_async_wait() returns, every AEAD operation +has completed and the engine no longer references those +skbs, so they can be freed unconditionally. + +A subsequent patch adds batch async decryption to +tls_sw_read_sock(), introducing a new call site that +must drain pending AEAD operations and release held +skbs. Move __skb_queue_purge(&ctx->async_hold) into +tls_decrypt_async_wait() so the purge is centralized +and every caller -- recvmsg's drain path, the -EBUSY +fallback in tls_do_decryption(), and the new read_sock +batch path -- releases held skbs on synchronization +without each site managing the purge independently. + +This fixes a leak when tls_strp_msg_hold() fails part-way through, +after having added some cloned skbs to the async_hold +queue. tls_decrypt_sg() will then call tls_decrypt_async_wait() to +process all pending decrypts, and drop back to synchronous mode, but +tls_sw_recvmsg() only flushes the async_hold queue when one record has +been processed in "fully-async" mode, which may not be the case here. + +Signed-off-by: Chuck Lever +Reported-by: Yiming Qian +Fixes: b8a6ff84abbc ("tls: wait for pending async decryptions if tls_strp_msg_hold fails") +Link: https://patch.msgid.link/20260324-tls-read-sock-v5-1-5408befe5774@oracle.com +[pabeni@redhat.com: added leak comment] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_sw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index b1fa62de9dab5..c0aadc8dce146 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -246,6 +246,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + atomic_inc(&ctx->decrypt_pending); + ++ __skb_queue_purge(&ctx->async_hold); + return ctx->async_wait.err; + } + +@@ -2225,7 +2226,6 @@ int tls_sw_recvmsg(struct sock *sk, + + /* Wait for all previously submitted records to be decrypted */ + ret = tls_decrypt_async_wait(ctx); +- __skb_queue_purge(&ctx->async_hold); + + if (ret) { + if (err >= 0 || err == -EINPROGRESS) +-- +2.51.0 + diff --git a/queue-6.19/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch b/queue-6.19/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch new file mode 100644 index 0000000000..ac954c6903 --- /dev/null +++ b/queue-6.19/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch @@ -0,0 +1,160 @@ +From 6a579235a994e8b70be033ac55ce31fa21d53585 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 11:18:17 -0700 +Subject: udp: Fix wildcard bind conflict check when using hash2 + +From: Martin KaFai Lau + +[ Upstream commit e537dd15d0d4ad989d56a1021290f0c674dd8b28 ] + +When binding a udp_sock to a local address and port, UDP uses +two hashes (udptable->hash and udptable->hash2) for collision +detection. The current code switches to "hash2" when +hslot->count > 10. + +"hash2" is keyed by local address and local port. +"hash" is keyed by local port only. + +The issue can be shown in the following bind sequence (pseudo code): + +bind(fd1, "[fd00::1]:8888") +bind(fd2, "[fd00::2]:8888") +bind(fd3, "[fd00::3]:8888") +bind(fd4, "[fd00::4]:8888") +bind(fd5, "[fd00::5]:8888") +bind(fd6, "[fd00::6]:8888") +bind(fd7, "[fd00::7]:8888") +bind(fd8, "[fd00::8]:8888") +bind(fd9, "[fd00::9]:8888") +bind(fd10, "[fd00::10]:8888") + +/* Correctly return -EADDRINUSE because "hash" is used + * instead of "hash2". udp_lib_lport_inuse() detects the + * conflict. + */ +bind(fail_fd, "[::]:8888") + +/* After one more socket is bound to "[fd00::11]:8888", + * hslot->count exceeds 10 and "hash2" is used instead. + */ +bind(fd11, "[fd00::11]:8888") +bind(fail_fd, "[::]:8888") /* succeeds unexpectedly */ + +The same issue applies to the IPv4 wildcard address "0.0.0.0" +and the IPv4-mapped wildcard address "::ffff:0.0.0.0". For +example, if there are existing sockets bound to +"192.168.1.[1-11]:8888", then binding "0.0.0.0:8888" or +"[::ffff:0.0.0.0]:8888" can also miss the conflict when +hslot->count > 10. + +TCP inet_csk_get_port() already has the correct check in +inet_use_bhash2_on_bind(). Rename it to +inet_use_hash2_on_bind() and move it to inet_hashtables.h +so udp.c can reuse it in this fix. + +Fixes: 30fff9231fad ("udp: bind() optimisation") +Reported-by: Andrew Onyshchuk +Signed-off-by: Martin KaFai Lau +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260319181817.1901357-1-martin.lau@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_hashtables.h | 14 ++++++++++++++ + net/ipv4/inet_connection_sock.c | 20 +++----------------- + net/ipv4/udp.c | 2 +- + 3 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 5a979dcab5383..6d936e9f2fd32 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -264,6 +264,20 @@ inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk, + return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)]; + } + ++static inline bool inet_use_hash2_on_bind(const struct sock *sk) ++{ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) { ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ return false; ++ ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ return true; ++ } ++#endif ++ return sk->sk_rcv_saddr != htonl(INADDR_ANY); ++} ++ + struct inet_bind_hashbucket * + inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port); + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 97d57c52b9ad9..d587c5df84389 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -153,20 +153,6 @@ bool inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) + } + EXPORT_SYMBOL(inet_sk_get_local_port_range); + +-static bool inet_use_bhash2_on_bind(const struct sock *sk) +-{ +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) { +- if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) +- return false; +- +- if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) +- return true; +- } +-#endif +- return sk->sk_rcv_saddr != htonl(INADDR_ANY); +-} +- + static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, + kuid_t uid, bool relax, + bool reuseport_cb_ok, bool reuseport_ok) +@@ -258,7 +244,7 @@ static int inet_csk_bind_conflict(const struct sock *sk, + * checks separately because their spinlocks have to be acquired/released + * independently of each other, to prevent possible deadlocks + */ +- if (inet_use_bhash2_on_bind(sk)) ++ if (inet_use_hash2_on_bind(sk)) + return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, + reuseport_cb_ok, reuseport_ok); + +@@ -375,7 +361,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); +- if (inet_use_bhash2_on_bind(sk)) { ++ if (inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false)) + goto next_port; + } +@@ -561,7 +547,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + check_bind_conflict = false; + } + +- if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) { ++ if (check_bind_conflict && inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true)) + goto fail_unlock; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index fbdbb65676e0d..bbb076c6042b2 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -287,7 +287,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + } else { + hslot = udp_hashslot(udptable, net, snum); + spin_lock_bh(&hslot->lock); +- if (hslot->count > 10) { ++ if (inet_use_hash2_on_bind(sk) && hslot->count > 10) { + int exist; + unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; + +-- +2.51.0 + diff --git a/queue-6.19/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch b/queue-6.19/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch new file mode 100644 index 0000000000..9e7e160ba0 --- /dev/null +++ b/queue-6.19/virtio-net-correct-hdr_len-handling-for-tunnel-gso.patch @@ -0,0 +1,80 @@ +From cbdd749a3e3470667d100ea296aa7ce7bc57f7dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 10:18:18 +0800 +Subject: virtio-net: correct hdr_len handling for tunnel gso + +From: Xuan Zhuo + +[ Upstream commit 6c860dc02a8e60b438e26940227dfa641fcdb66a ] + +The commit a2fb4bc4e2a6a03 ("net: implement virtio helpers to handle UDP +GSO tunneling.") introduces support for the UDP GSO tunnel feature in +virtio-net. + +The virtio spec says: + + If the \field{gso_type} has the VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 bit or + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6 bit set, \field{hdr_len} accounts for + all the headers up to and including the inner transport. + +The commit did not update the hdr_len to include the inner transport. + +I observed that the "hdr_len" is 116 for this packet: + + 17:36:18.241105 52:55:00:d1:27:0a > 2e:2c:df:46:a9:e1, ethertype IPv4 (0x0800), length 2912: (tos 0x0, ttl 64, id 45197, offset 0, flags [none], proto UDP (17), length 2898) + 192.168.122.100.50613 > 192.168.122.1.4789: [bad udp cksum 0x8106 -> 0x26a0!] VXLAN, flags [I] (0x08), vni 1 + fa:c3:ba:82:05:ee > ce:85:0c:31:77:e5, ethertype IPv4 (0x0800), length 2862: (tos 0x0, ttl 64, id 14678, offset 0, flags [DF], proto TCP (6), length 2848) + 192.168.3.1.49880 > 192.168.3.2.9898: Flags [P.], cksum 0x9266 (incorrect -> 0xaa20), seq 515667:518463, ack 1, win 64, options [nop,nop,TS val 2990048824 ecr 2798801412], length 2796 + +116 = 14(mac) + 20(ip) + 8(udp) + 8(vxlan) + 14(inner mac) + 20(inner ip) + 32(innner tcp) + +Fixes: a2fb4bc4e2a6a03 ("net: implement virtio helpers to handle UDP GSO tunneling.") +Signed-off-by: Xuan Zhuo +Link: https://patch.msgid.link/20260320021818.111741-3-xuanzhuo@linux.alibaba.com +Acked-by: Michael S. Tsirkin +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/linux/virtio_net.h | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index 361b60c8be680..f36d21b5bc19e 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -224,6 +224,22 @@ static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb, + hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len); + } + ++/* This function must be called after virtio_net_hdr_from_skb(). */ ++static inline void __virtio_net_set_tnl_hdrlen(const struct sk_buff *skb, ++ struct virtio_net_hdr *hdr) ++{ ++ u16 hdr_len; ++ ++ hdr_len = skb_inner_transport_offset(skb); ++ ++ if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4) ++ hdr_len += sizeof(struct udphdr); ++ else ++ hdr_len += inner_tcp_hdrlen(skb); ++ ++ hdr->hdr_len = __cpu_to_virtio16(true, hdr_len); ++} ++ + static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian, +@@ -440,6 +456,9 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + if (ret) + return ret; + ++ if (feature_hdrlen && hdr->hdr_len) ++ __virtio_net_set_tnl_hdrlen(skb, hdr); ++ + if (skb->protocol == htons(ETH_P_IPV6)) + hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6; + else +-- +2.51.0 + diff --git a/queue-6.19/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch b/queue-6.19/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch new file mode 100644 index 0000000000..2eb51d7a2b --- /dev/null +++ b/queue-6.19/virtio-net-correct-hdr_len-handling-for-virtio_net_f.patch @@ -0,0 +1,134 @@ +From 5cc290a259bc94171439a64ec834ecd212f0f5bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 10:18:17 +0800 +Subject: virtio-net: correct hdr_len handling for VIRTIO_NET_F_GUEST_HDRLEN + +From: Xuan Zhuo + +[ Upstream commit 38ec410b99a5ee6566f75650ce3d4fd632940fd0 ] + +The commit be50da3e9d4a ("net: virtio_net: implement exact header length +guest feature") introduces support for the VIRTIO_NET_F_GUEST_HDRLEN +feature in virtio-net. + +This feature requires virtio-net to set hdr_len to the actual header +length of the packet when transmitting, the number of +bytes from the start of the packet to the beginning of the +transport-layer payload. + +However, in practice, hdr_len was being set using skb_headlen(skb), +which is clearly incorrect. This commit fixes that issue. + +Fixes: be50da3e9d4a ("net: virtio_net: implement exact header length guest feature") +Signed-off-by: Xuan Zhuo +Link: https://patch.msgid.link/20260320021818.111741-2-xuanzhuo@linux.alibaba.com +Acked-by: Michael S. Tsirkin +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/tun_vnet.h | 2 +- + drivers/net/virtio_net.c | 6 +++++- + include/linux/virtio_net.h | 34 ++++++++++++++++++++++++++++++---- + 3 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/tun_vnet.h b/drivers/net/tun_vnet.h +index a5f93b6c4482c..fa5cab9d3e55c 100644 +--- a/drivers/net/tun_vnet.h ++++ b/drivers/net/tun_vnet.h +@@ -244,7 +244,7 @@ tun_vnet_hdr_tnl_from_skb(unsigned int flags, + + if (virtio_net_hdr_tnl_from_skb(skb, tnl_hdr, has_tnl_offload, + tun_vnet_is_little_endian(flags), +- vlan_hlen, true)) { ++ vlan_hlen, true, false)) { + struct virtio_net_hdr_v1 *hdr = &tnl_hdr->hash_hdr.hdr; + struct skb_shared_info *sinfo = skb_shinfo(skb); + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index db88dcaefb20b..80f08c228407c 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -3267,8 +3267,12 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan) + struct virtio_net_hdr_v1_hash_tunnel *hdr; + int num_sg; + unsigned hdr_len = vi->hdr_len; ++ bool feature_hdrlen; + bool can_push; + ++ feature_hdrlen = virtio_has_feature(vi->vdev, ++ VIRTIO_NET_F_GUEST_HDRLEN); ++ + pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); + + /* Make sure it's safe to cast between formats */ +@@ -3288,7 +3292,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan) + + if (virtio_net_hdr_tnl_from_skb(skb, hdr, vi->tx_tnl, + virtio_is_little_endian(vi->vdev), 0, +- false)) ++ false, feature_hdrlen)) + return -EPROTO; + + if (vi->mergeable_rx_bufs) +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index 75dabb763c650..361b60c8be680 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -207,6 +207,23 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + return __virtio_net_hdr_to_skb(skb, hdr, little_endian, hdr->gso_type); + } + ++/* This function must be called after virtio_net_hdr_from_skb(). */ ++static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb, ++ struct virtio_net_hdr *hdr, ++ bool little_endian) ++{ ++ u16 hdr_len; ++ ++ hdr_len = skb_transport_offset(skb); ++ ++ if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4) ++ hdr_len += sizeof(struct udphdr); ++ else ++ hdr_len += tcp_hdrlen(skb); ++ ++ hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len); ++} ++ + static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian, +@@ -385,7 +402,8 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + bool tnl_hdr_negotiated, + bool little_endian, + int vlan_hlen, +- bool has_data_valid) ++ bool has_data_valid, ++ bool feature_hdrlen) + { + struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)vhdr; + unsigned int inner_nh, outer_th; +@@ -394,9 +412,17 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, + + tnl_gso_type = skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | + SKB_GSO_UDP_TUNNEL_CSUM); +- if (!tnl_gso_type) +- return virtio_net_hdr_from_skb(skb, hdr, little_endian, +- has_data_valid, vlan_hlen); ++ if (!tnl_gso_type) { ++ ret = virtio_net_hdr_from_skb(skb, hdr, little_endian, ++ has_data_valid, vlan_hlen); ++ if (ret) ++ return ret; ++ ++ if (feature_hdrlen && hdr->hdr_len) ++ __virtio_net_set_hdrlen(skb, hdr, little_endian); ++ ++ return ret; ++ } + + /* Tunnel support not negotiated but skb ask for it. */ + if (!tnl_hdr_negotiated) +-- +2.51.0 + diff --git a/queue-6.19/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch b/queue-6.19/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch new file mode 100644 index 0000000000..42c1414b60 --- /dev/null +++ b/queue-6.19/xfrm-add-missing-extack-for-xfrma_sa_pcpu-in-add_acq.patch @@ -0,0 +1,49 @@ +From ea79e3ac238d02b5f85aea6fc1a79a23a8024ff5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:11 +0100 +Subject: xfrm: add missing extack for XFRMA_SA_PCPU in add_acquire and + allocspi + +From: Sabrina Dubroca + +[ Upstream commit aa8a3f3c67235422a0c3608a8772f69ca3b7b63f ] + +We're returning an error caused by invalid user input without setting +an extack. Add one. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 403b5ecac2c54..3e6477c6082e7 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1850,6 +1850,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + if (pcpu_num >= num_possible_cpus()) { + err = -EINVAL; ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto out_noput; + } + } +@@ -3001,8 +3002,10 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + if (attrs[XFRMA_SA_PCPU]) { + x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]); + err = -EINVAL; +- if (x->pcpu_num >= num_possible_cpus()) ++ if (x->pcpu_num >= num_possible_cpus()) { ++ NL_SET_ERR_MSG(extack, "pCPU number too big"); + goto free_state; ++ } + } + + err = verify_newpolicy_info(&ua->policy, extack); +-- +2.51.0 + diff --git a/queue-6.19/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-6.19/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..24bbb015d1 --- /dev/null +++ b/queue-6.19/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From 82b123d057ed515fcb550a663bd72c36e573d449 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 98b362d518363..a00c4fe1ab0ce 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2264,6 +2264,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-6.19/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch b/queue-6.19/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch new file mode 100644 index 0000000000..8b340b943d --- /dev/null +++ b/queue-6.19/xfrm-fix-the-condition-on-x-pcpu_num-in-xfrm_sa_len.patch @@ -0,0 +1,38 @@ +From 249abf06f2df66556757e1cc88e9630cadf7e2ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:12 +0100 +Subject: xfrm: fix the condition on x->pcpu_num in xfrm_sa_len + +From: Sabrina Dubroca + +[ Upstream commit b57defcf8f109da5ba9cf59b2a736606faf3d846 ] + +pcpu_num = 0 is a valid value. The marker for "unset pcpu_num" which +makes copy_to_user_state_extra not add the XFRMA_SA_PCPU attribute is +UINT_MAX. + +Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 3e6477c6082e7..4dd8341225bce 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -3676,7 +3676,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) + } + if (x->if_id) + l += nla_total_size(sizeof(x->if_id)); +- if (x->pcpu_num) ++ if (x->pcpu_num != UINT_MAX) + l += nla_total_size(sizeof(x->pcpu_num)); + + /* Must count x->lastused as it may become non-zero behind our back. */ +-- +2.51.0 + diff --git a/queue-6.19/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch b/queue-6.19/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch new file mode 100644 index 0000000000..f853cbc52a --- /dev/null +++ b/queue-6.19/xfrm-fix-work-re-schedule-after-cancel-in-xfrm_nat_k.patch @@ -0,0 +1,70 @@ +From 8c2e63eaf5eb4ce13ce973025f0caf27d83e48eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Mar 2026 03:16:29 +0900 +Subject: xfrm: Fix work re-schedule after cancel in + xfrm_nat_keepalive_net_fini() + +From: Hyunwoo Kim + +[ Upstream commit daf8e3b253aa760ff9e96c7768a464bc1d6b3c90 ] + +After cancel_delayed_work_sync() is called from +xfrm_nat_keepalive_net_fini(), xfrm_state_fini() flushes remaining +states via __xfrm_state_delete(), which calls +xfrm_nat_keepalive_state_updated() to re-schedule nat_keepalive_work. + +The following is a simple race scenario: + + cpu0 cpu1 + +cleanup_net() [Round 1] + ops_undo_list() + xfrm_net_exit() + xfrm_nat_keepalive_net_fini() + cancel_delayed_work_sync(nat_keepalive_work); + xfrm_state_fini() + xfrm_state_flush() + xfrm_state_delete(x) + __xfrm_state_delete(x) + xfrm_nat_keepalive_state_updated(x) + schedule_delayed_work(nat_keepalive_work); + rcu_barrier(); + net_complete_free(); + net_passive_dec(net); + llist_add(&net->defer_free_list, &defer_free_list); + +cleanup_net() [Round 2] + rcu_barrier(); + net_complete_free() + kmem_cache_free(net_cachep, net); + nat_keepalive_work() + // on freed net + +To prevent this, cancel_delayed_work_sync() is replaced with +disable_delayed_work_sync(). + +Fixes: f531d13bdfe3 ("xfrm: support sending NAT keepalives in ESP in UDP states") +Signed-off-by: Hyunwoo Kim +Reviewed-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_nat_keepalive.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_nat_keepalive.c b/net/xfrm/xfrm_nat_keepalive.c +index ebf95d48e86c1..1856beee0149b 100644 +--- a/net/xfrm/xfrm_nat_keepalive.c ++++ b/net/xfrm/xfrm_nat_keepalive.c +@@ -261,7 +261,7 @@ int __net_init xfrm_nat_keepalive_net_init(struct net *net) + + int xfrm_nat_keepalive_net_fini(struct net *net) + { +- cancel_delayed_work_sync(&net->xfrm.nat_keepalive_work); ++ disable_delayed_work_sync(&net->xfrm.nat_keepalive_work); + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.19/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch b/queue-6.19/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch new file mode 100644 index 0000000000..e62f722465 --- /dev/null +++ b/queue-6.19/xfrm-iptfs-fix-skb_put-panic-on-non-linear-skb-durin.patch @@ -0,0 +1,80 @@ +From 6b01ec82048b50fbdbf6de2c1eaa61603f8c08ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Mar 2026 15:09:35 +0100 +Subject: xfrm: iptfs: fix skb_put() panic on non-linear skb during reassembly + +From: Fernando Fernandez Mancera + +[ Upstream commit 0b352f83cabfefdaafa806d6471f0eca117dc7d5 ] + +In iptfs_reassem_cont(), IP-TFS attempts to append data to the new inner +packet 'newskb' that is being reassembled. First a zero-copy approach is +tried if it succeeds then newskb becomes non-linear. + +When a subsequent fragment in the same datagram does not meet the +fast-path conditions, a memory copy is performed. It calls skb_put() to +append the data and as newskb is non-linear it triggers +SKB_LINEAR_ASSERT check. + + Oops: invalid opcode: 0000 [#1] SMP NOPTI + [...] + RIP: 0010:skb_put+0x3c/0x40 + [...] + Call Trace: + + iptfs_reassem_cont+0x1ab/0x5e0 [xfrm_iptfs] + iptfs_input_ordered+0x2af/0x380 [xfrm_iptfs] + iptfs_input+0x122/0x3e0 [xfrm_iptfs] + xfrm_input+0x91e/0x1a50 + xfrm4_esp_rcv+0x3a/0x110 + ip_protocol_deliver_rcu+0x1d7/0x1f0 + ip_local_deliver_finish+0xbe/0x1e0 + __netif_receive_skb_core.constprop.0+0xb56/0x1120 + __netif_receive_skb_list_core+0x133/0x2b0 + netif_receive_skb_list_internal+0x1ff/0x3f0 + napi_complete_done+0x81/0x220 + virtnet_poll+0x9d6/0x116e [virtio_net] + __napi_poll.constprop.0+0x2b/0x270 + net_rx_action+0x162/0x360 + handle_softirqs+0xdc/0x510 + __irq_exit_rcu+0xe7/0x110 + irq_exit_rcu+0xe/0x20 + common_interrupt+0x85/0xa0 + + + +Fix this by checking if the skb is non-linear. If it is, linearize it by +calling skb_linearize(). As the initial allocation of newskb originally +reserved enough tailroom for the entire reassembled packet we do not +need to check if we have enough tailroom or extend it. + +Fixes: 5f2b6a909574 ("xfrm: iptfs: add skb-fragment sharing code") +Reported-by: Hao Long +Closes: https://lore.kernel.org/netdev/DGRCO9SL0T5U.JTINSHJQ9KPK@imlonghao.com/ +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_iptfs.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c +index 3b6d7284fc70a..4e270628fc347 100644 +--- a/net/xfrm/xfrm_iptfs.c ++++ b/net/xfrm/xfrm_iptfs.c +@@ -901,6 +901,12 @@ static u32 iptfs_reassem_cont(struct xfrm_iptfs_data *xtfs, u64 seq, + iptfs_skb_can_add_frags(newskb, fragwalk, data, copylen)) { + iptfs_skb_add_frags(newskb, fragwalk, data, copylen); + } else { ++ if (skb_linearize(newskb)) { ++ XFRM_INC_STATS(xs_net(xtfs->x), ++ LINUX_MIB_XFRMINBUFFERERROR); ++ goto abandon; ++ } ++ + /* copy fragment data into newskb */ + if (skb_copy_seq_read(st, data, skb_put(newskb, copylen), + copylen)) { +-- +2.51.0 + diff --git a/queue-6.19/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch b/queue-6.19/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch new file mode 100644 index 0000000000..78291d25d6 --- /dev/null +++ b/queue-6.19/xfrm-prevent-policy_hthresh.work-from-racing-with-ne.patch @@ -0,0 +1,48 @@ +From 5eacd5b27b9a217804170bd4d4d67016e7e9af95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 00:58:44 +0900 +Subject: xfrm: prevent policy_hthresh.work from racing with netns teardown + +From: Minwoo Ra + +[ Upstream commit 29fe3a61bcdce398ee3955101c39f89c01a8a77e ] + +A XFRM_MSG_NEWSPDINFO request can queue the per-net work item +policy_hthresh.work onto the system workqueue. + +The queued callback, xfrm_hash_rebuild(), retrieves the enclosing +struct net via container_of(). If the net namespace is torn down +before that work runs, the associated struct net may already have +been freed, and xfrm_hash_rebuild() may then dereference stale memory. + +xfrm_policy_fini() already flushes policy_hash_work during teardown, +but it does not synchronize policy_hthresh.work. + +Synchronize policy_hthresh.work in xfrm_policy_fini() as well, so the +queued work cannot outlive the net namespace teardown and access a +freed struct net. + +Fixes: 880a6fab8f6b ("xfrm: configure policy hash table thresholds by netlink") +Signed-off-by: Minwoo Ra +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_policy.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 5428185196a1f..c32d34c441ee0 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -4282,6 +4282,8 @@ static void xfrm_policy_fini(struct net *net) + unsigned int sz; + int dir; + ++ disable_work_sync(&net->xfrm.policy_hthresh.work); ++ + flush_work(&net->xfrm.policy_hash_work); + #ifdef CONFIG_XFRM_SUB_POLICY + xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false); +-- +2.51.0 + diff --git a/queue-6.6/af_key-validate-families-in-pfkey_send_migrate.patch b/queue-6.6/af_key-validate-families-in-pfkey_send_migrate.patch new file mode 100644 index 0000000000..960342dc01 --- /dev/null +++ b/queue-6.6/af_key-validate-families-in-pfkey_send_migrate.patch @@ -0,0 +1,84 @@ +From ce2403df5d721bf0f0b58adaaa2091295d0eaa7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Mar 2026 17:02:10 +0000 +Subject: af_key: validate families in pfkey_send_migrate() + +From: Eric Dumazet + +[ Upstream commit eb2d16a7d599dc9d4df391b5e660df9949963786 ] + +syzbot was able to trigger a crash in skb_put() [1] + +Issue is that pfkey_send_migrate() does not check old/new families, +and that set_ipsecrequest() @family argument was truncated, +thus possibly overfilling the skb. + +Validate families early, do not wait set_ipsecrequest(). + +[1] + +skbuff: skb_over_panic: text:ffffffff8a752120 len:392 put:16 head:ffff88802a4ad040 data:ffff88802a4ad040 tail:0x188 end:0x180 dev: + kernel BUG at net/core/skbuff.c:214 ! +Call Trace: + + skb_over_panic net/core/skbuff.c:219 [inline] + skb_put+0x159/0x210 net/core/skbuff.c:2655 + skb_put_zero include/linux/skbuff.h:2788 [inline] + set_ipsecrequest net/key/af_key.c:3532 [inline] + pfkey_send_migrate+0x1270/0x2e50 net/key/af_key.c:3636 + km_migrate+0x155/0x260 net/xfrm/xfrm_state.c:2848 + xfrm_migrate+0x2140/0x2450 net/xfrm/xfrm_policy.c:4705 + xfrm_do_migrate+0x8ff/0xaa0 net/xfrm/xfrm_user.c:3150 + +Fixes: 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") +Reported-by: syzbot+b518dfc8e021988fbd55@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69b5933c.050a0220.248e02.00f2.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 6c4448908afed..4849407da86d6 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3517,7 +3517,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress * + + static int set_ipsecrequest(struct sk_buff *skb, + uint8_t proto, uint8_t mode, int level, +- uint32_t reqid, uint8_t family, ++ uint32_t reqid, sa_family_t family, + const xfrm_address_t *src, const xfrm_address_t *dst) + { + struct sadb_x_ipsecrequest *rq; +@@ -3582,12 +3582,17 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + + /* ipsecrequests */ + for (i = 0, mp = m; i < num_bundles; i++, mp++) { +- /* old locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->old_family); +- /* new locator pair */ +- size_pol += sizeof(struct sadb_x_ipsecrequest) + +- pfkey_sockaddr_pair_size(mp->new_family); ++ int pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->old_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; ++ ++ pair_size = pfkey_sockaddr_pair_size(mp->new_family); ++ if (!pair_size) ++ return -EINVAL; ++ size_pol += sizeof(struct sadb_x_ipsecrequest) + pair_size; + } + + size += sizeof(struct sadb_msg) + size_pol; +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch b/queue-6.6/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch new file mode 100644 index 0000000000..079f883a19 --- /dev/null +++ b/queue-6.6/bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch @@ -0,0 +1,101 @@ +From 155bc7be97f1da714e439ab998bf0433ebe78fb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 20:54:03 +0800 +Subject: Bluetooth: btintel: serialize btintel_hw_error() with + hci_req_sync_lock + +From: Cen Zhang + +[ Upstream commit 94d8e6fe5d0818e9300e514e095a200bd5ff93ae ] + +btintel_hw_error() issues two __hci_cmd_sync() calls (HCI_OP_RESET +and Intel exception-info retrieval) without holding +hci_req_sync_lock(). This lets it race against +hci_dev_do_close() -> btintel_shutdown_combined(), which also runs +__hci_cmd_sync() under the same lock. When both paths manipulate +hdev->req_status/req_rsp concurrently, the close path may free the +response skb first, and the still-running hw_error path hits a +slab-use-after-free in kfree_skb(). + +Wrap the whole recovery sequence in hci_req_sync_lock/unlock so it +is serialized with every other synchronous HCI command issuer. + +Below is the data race report and the kasan report: + + BUG: data-race in __hci_cmd_sync_sk / btintel_shutdown_combined + + read of hdev->req_rsp at net/bluetooth/hci_sync.c:199 + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x114/0x670 drivers/bluetooth/btintel.c:254 + hci_error_reset+0x348/0xa30 net/bluetooth/hci_core.c:1030 + + write/free by task ioctl/22580: + btintel_shutdown_combined+0xd0/0x360 + drivers/bluetooth/btintel.c:3648 + hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246 + hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526 + + BUG: KASAN: slab-use-after-free in + sk_skb_reason_drop+0x43/0x380 net/core/skbuff.c:1202 + Read of size 4 at addr ffff888144a738dc + by task kworker/u17:1/83: + __hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200 + __hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223 + btintel_hw_error+0x186/0x670 drivers/bluetooth/btintel.c:260 + +Fixes: 973bb97e5aee ("Bluetooth: btintel: Add generic function for handling hardware errors") +Signed-off-by: Cen Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 3773cd9d998d5..25fcd00c6a174 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -242,11 +242,13 @@ static void btintel_hw_error(struct hci_dev *hdev, u8 code) + + bt_dev_err(hdev, "Hardware error 0x%2.2x", code); + ++ hci_req_sync_lock(hdev); ++ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reset after hardware error failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + kfree_skb(skb); + +@@ -254,18 +256,21 @@ static void btintel_hw_error(struct hci_dev *hdev, u8 code) + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", + PTR_ERR(skb)); +- return; ++ goto unlock; + } + + if (skb->len != 13) { + bt_dev_err(hdev, "Exception info size mismatch"); + kfree_skb(skb); +- return; ++ goto unlock; + } + + bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); + + kfree_skb(skb); ++ ++unlock: ++ hci_req_sync_unlock(hdev); + } + + int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch b/queue-6.6/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch new file mode 100644 index 0000000000..c74e2aedf3 --- /dev/null +++ b/queue-6.6/bluetooth-btusb-clamp-sco-altsetting-table-indices.patch @@ -0,0 +1,49 @@ +From 24c7cb70ceb77e4000fbfd1eb1e419c8e841f5e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 08:42:45 +0800 +Subject: Bluetooth: btusb: clamp SCO altsetting table indices + +From: Pengpeng Hou + +[ Upstream commit 129fa608b6ad08b8ab7178eeb2ec272c993aaccc ] + +btusb_work() maps the number of active SCO links to USB alternate +settings through a three-entry lookup table when CVSD traffic uses +transparent voice settings. The lookup currently indexes alts[] with +data->sco_num - 1 without first constraining sco_num to the number of +available table entries. + +While the table only defines alternate settings for up to three SCO +links, data->sco_num comes from hci_conn_num() and is used directly. +Cap the lookup to the last table entry before indexing it so the +driver keeps selecting the highest supported alternate setting without +reading past alts[]. + +Fixes: baac6276c0a9 ("Bluetooth: btusb: handle mSBC audio over USB Endpoints") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 168e46ce59976..c51523d780e65 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2314,8 +2314,11 @@ static void btusb_work(struct work_struct *work) + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; ++ unsigned int sco_idx; + +- new_alts = alts[data->sco_num - 1]; ++ sco_idx = min_t(unsigned int, data->sco_num - 1, ++ ARRAY_SIZE(alts) - 1); ++ new_alts = alts[sco_idx]; + } else { + new_alts = data->sco_num; + } +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch b/queue-6.6/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch new file mode 100644 index 0000000000..ff6fafed6d --- /dev/null +++ b/queue-6.6/bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch @@ -0,0 +1,46 @@ +From c2c374acbf11cc490691eb9510499fd06290a3ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 10:51:37 +0000 +Subject: Bluetooth: hci_ll: Fix firmware leak on error path + +From: Anas Iqbal + +[ Upstream commit 31148a7be723aa9f2e8fbd62424825ab8d577973 ] + +Smatch reports: + +drivers/bluetooth/hci_ll.c:587 download_firmware() warn: +'fw' from request_firmware() not released on lines: 544. + +In download_firmware(), if request_firmware() succeeds but the returned +firmware content is invalid (no data or zero size), the function returns +without releasing the firmware, resulting in a resource leak. + +Fix this by calling release_firmware() before returning when +request_firmware() succeeded but the firmware content is invalid. + +Fixes: 371805522f87 ("bluetooth: hci_uart: add LL protocol serdev driver support") +Reviewed-by: Paul Menzel +Signed-off-by: Anas Iqbal +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index 4a0b5c3160c2b..4d987dece2d0c 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev) + if (err || !fw->data || !fw->size) { + bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s", + err, bts_scr_name); ++ if (!err) ++ release_firmware(fw); + return -EINVAL; + } + ptr = (void *)fw->data; +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-hci_sync-remove-remaining-dependencies-of-.patch b/queue-6.6/bluetooth-hci_sync-remove-remaining-dependencies-of-.patch new file mode 100644 index 0000000000..5b07d1f691 --- /dev/null +++ b/queue-6.6/bluetooth-hci_sync-remove-remaining-dependencies-of-.patch @@ -0,0 +1,126 @@ +From e3d51c3e948d430cc26b089e24e30266a9eec0f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Jul 2024 16:52:57 -0400 +Subject: Bluetooth: hci_sync: Remove remaining dependencies of hci_request + +From: Luiz Augusto von Dentz + +[ Upstream commit f2d89775358606c7ab6b6b6c4a02fe1e8cd270b1 ] + +This removes the dependencies of hci_req_init and hci_request_cancel_all +from hci_sync.c. + +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 94d8e6fe5d08 ("Bluetooth: btintel: serialize btintel_hw_error() with hci_req_sync_lock") +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_sync.h | 17 +++++++++++++++++ + net/bluetooth/hci_request.h | 17 ----------------- + net/bluetooth/hci_sync.c | 14 +++++++++++--- + 3 files changed, 28 insertions(+), 20 deletions(-) + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index e2e588b08fe90..e155ab5aa9b4f 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -8,6 +8,23 @@ + #define UINT_PTR(_handle) ((void *)((uintptr_t)_handle)) + #define PTR_UINT(_ptr) ((uintptr_t)((void *)_ptr)) + ++#define HCI_REQ_DONE 0 ++#define HCI_REQ_PEND 1 ++#define HCI_REQ_CANCELED 2 ++ ++#define hci_req_sync_lock(hdev) mutex_lock(&hdev->req_lock) ++#define hci_req_sync_unlock(hdev) mutex_unlock(&hdev->req_lock) ++ ++struct hci_request { ++ struct hci_dev *hdev; ++ struct sk_buff_head cmd_q; ++ ++ /* If something goes wrong when building the HCI request, the error ++ * value is stored in this field. ++ */ ++ int err; ++}; ++ + typedef int (*hci_cmd_sync_work_func_t)(struct hci_dev *hdev, void *data); + typedef void (*hci_cmd_sync_work_destroy_t)(struct hci_dev *hdev, void *data, + int err); +diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h +index c91f2838f5424..b730da4a8b476 100644 +--- a/net/bluetooth/hci_request.h ++++ b/net/bluetooth/hci_request.h +@@ -22,23 +22,6 @@ + + #include + +-#define HCI_REQ_DONE 0 +-#define HCI_REQ_PEND 1 +-#define HCI_REQ_CANCELED 2 +- +-#define hci_req_sync_lock(hdev) mutex_lock(&hdev->req_lock) +-#define hci_req_sync_unlock(hdev) mutex_unlock(&hdev->req_lock) +- +-struct hci_request { +- struct hci_dev *hdev; +- struct sk_buff_head cmd_q; +- +- /* If something goes wrong when building the HCI request, the error +- * value is stored in this field. +- */ +- int err; +-}; +- + void hci_req_init(struct hci_request *req, struct hci_dev *hdev); + void hci_req_purge(struct hci_request *req); + bool hci_req_status_pend(struct hci_dev *hdev); +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 6192f70e4d393..c1c9d82faa658 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -12,7 +12,6 @@ + #include + #include + +-#include "hci_request.h" + #include "hci_codec.h" + #include "hci_debugfs.h" + #include "smp.h" +@@ -147,6 +146,13 @@ static int hci_req_sync_run(struct hci_request *req) + return 0; + } + ++static void hci_request_init(struct hci_request *req, struct hci_dev *hdev) ++{ ++ skb_queue_head_init(&req->cmd_q); ++ req->hdev = hdev; ++ req->err = 0; ++} ++ + /* This function requires the caller holds hdev->req_lock. */ + struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, + const void *param, u8 event, u32 timeout, +@@ -158,7 +164,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen, + + bt_dev_dbg(hdev, "Opcode 0x%4.4x", opcode); + +- hci_req_init(&req, hdev); ++ hci_request_init(&req, hdev); + + hci_cmd_sync_add(&req, opcode, plen, param, event, sk); + +@@ -5227,7 +5233,9 @@ int hci_dev_close_sync(struct hci_dev *hdev) + cancel_delayed_work(&hdev->le_scan_disable); + cancel_delayed_work(&hdev->le_scan_restart); + +- hci_request_cancel_all(hdev); ++ hci_cmd_sync_cancel_sync(hdev, ENODEV); ++ ++ cancel_interleave_scan(hdev); + + if (hdev->adv_instance_timeout) { + cancel_delayed_work_sync(&hdev->adv_instance_expire); +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch b/queue-6.6/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch new file mode 100644 index 0000000000..f3dc1e0243 --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch @@ -0,0 +1,79 @@ +From 93c463bd86d738a380792b88f817fa341d585135 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 20:23:10 +0900 +Subject: Bluetooth: L2CAP: Fix ERTM re-init and zero pdu_len infinite loop + +From: Hyunwoo Kim + +[ Upstream commit 25f420a0d4cfd61d3d23ec4b9c56d9f443d91377 ] + +l2cap_config_req() processes CONFIG_REQ for channels in BT_CONNECTED +state to support L2CAP reconfiguration (e.g. MTU changes). However, +since both CONF_INPUT_DONE and CONF_OUTPUT_DONE are already set from +the initial configuration, the reconfiguration path falls through to +l2cap_ertm_init(), which re-initializes tx_q, srej_q, srej_list, and +retrans_list without freeing the previous allocations and sets +chan->sdu to NULL without freeing the existing skb. This leaks all +previously allocated ERTM resources. + +Additionally, l2cap_parse_conf_req() does not validate the minimum +value of remote_mps derived from the RFC max_pdu_size option. A zero +value propagates to l2cap_segment_sdu() where pdu_len becomes zero, +causing the while loop to never terminate since len is never +decremented, exhausting all available memory. + +Fix the double-init by skipping l2cap_ertm_init() and +l2cap_chan_ready() when the channel is already in BT_CONNECTED state, +while still allowing the reconfiguration parameters to be updated +through l2cap_parse_conf_req(). Also add a pdu_len zero check in +l2cap_segment_sdu() as a safeguard. + +Fixes: 96298f640104 ("Bluetooth: L2CAP: handle l2cap config request during open state") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 47625ea36106f..3da3e9fddd049 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2383,6 +2383,9 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, + /* Remote device may have requested smaller PDUs */ + pdu_len = min_t(size_t, pdu_len, chan->remote_mps); + ++ if (!pdu_len) ++ return -EINVAL; ++ + if (len <= pdu_len) { + sar = L2CAP_SAR_UNSEGMENTED; + sdu_len = 0; +@@ -4281,14 +4284,16 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) { + set_default_fcs(chan); + +- if (chan->mode == L2CAP_MODE_ERTM || +- chan->mode == L2CAP_MODE_STREAMING) +- err = l2cap_ertm_init(chan); ++ if (chan->state != BT_CONNECTED) { ++ if (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_STREAMING) ++ err = l2cap_ertm_init(chan); + +- if (err < 0) +- l2cap_send_disconn_req(chan, -err); +- else +- l2cap_chan_ready(chan); ++ if (err < 0) ++ l2cap_send_disconn_req(chan, -err); ++ else ++ l2cap_chan_ready(chan); ++ } + + goto unlock; + } +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch b/queue-6.6/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch new file mode 100644 index 0000000000..1e11e1cd8e --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch @@ -0,0 +1,105 @@ +From b668d9019aa87355dc5516629cf518d3f5d0a4ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:58:01 -0300 +Subject: Bluetooth: L2CAP: Fix null-ptr-deref on l2cap_sock_ready_cb + +From: Helen Koike + +[ Upstream commit b6552e0503973daf6f23bd6ed9273ef131ee364f ] + +Before using sk pointer, check if it is null. + +Fix the following: + + KASAN: null-ptr-deref in range [0x0000000000000260-0x0000000000000267] + CPU: 0 UID: 0 PID: 5985 Comm: kworker/0:5 Not tainted 7.0.0-rc4-00029-ga989fde763f4 #1 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.17.0-9.fc43 06/10/2025 + Workqueue: events l2cap_info_timeout + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + veth0_macvtap: entered promiscuous mode + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005582615a5008 CR3: 000000007007e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Call Trace: + + __kasan_check_byte+0x12/0x40 + lock_acquire+0x79/0x2e0 + lock_sock_nested+0x48/0x100 + ? l2cap_sock_ready_cb+0x46/0x160 + l2cap_sock_ready_cb+0x46/0x160 + l2cap_conn_start+0x779/0xff0 + ? __pfx_l2cap_conn_start+0x10/0x10 + ? l2cap_info_timeout+0x60/0xa0 + ? __pfx___mutex_lock+0x10/0x10 + l2cap_info_timeout+0x68/0xa0 + ? process_scheduled_works+0xa8d/0x18c0 + process_scheduled_works+0xb6e/0x18c0 + ? __pfx_process_scheduled_works+0x10/0x10 + ? assign_work+0x3d5/0x5e0 + worker_thread+0xa53/0xfc0 + kthread+0x388/0x470 + ? __pfx_worker_thread+0x10/0x10 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x51e/0xb90 + ? __pfx_ret_from_fork+0x10/0x10 + veth1_macvtap: entered promiscuous mode + ? __switch_to+0xc7d/0x1450 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + Modules linked in: + ---[ end trace 0000000000000000 ]--- + batman_adv: batadv0: Interface activated: batadv_slave_0 + batman_adv: batadv0: Interface activated: batadv_slave_1 + netdevsim netdevsim7 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0 + netdevsim netdevsim7 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0 + RIP: 0010:kasan_byte_accessible+0x12/0x30 + Code: 79 ff ff ff 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 c1 ef 03 48 b8 00 00 00 00 00 fc ff df <0f> b6 04 07 3c 08 0f 92 c0 c3 cc cce + ieee80211 phy39: Selected rate control algorithm 'minstrel_ht' + RSP: 0018:ffffc90006e0f808 EFLAGS: 00010202 + RAX: dffffc0000000000 RBX: ffffffff89746018 RCX: 0000000080000001 + RDX: 0000000000000000 RSI: ffffffff89746018 RDI: 000000000000004c + RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 + R10: dffffc0000000000 R11: ffffffff8aae3e70 R12: 0000000000000000 + R13: 0000000000000260 R14: 0000000000000260 R15: 0000000000000001 + FS: 0000000000000000(0000) GS:ffff8880983c2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f7e16139e9c CR3: 000000000e74e000 CR4: 0000000000752ef0 + PKRU: 55555554 + Kernel panic - not syncing: Fatal exception + +Fixes: 54a59aa2b562 ("Bluetooth: Add l2cap_chan->ops->ready()") +Signed-off-by: Helen Koike +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 250cc0bc552e0..1960d35b3be0a 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1665,6 +1665,9 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + lock_sock(sk); + + parent = bt_sk(sk)->parent; +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch b/queue-6.6/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch new file mode 100644 index 0000000000..3f1be929f2 --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch @@ -0,0 +1,50 @@ +From ecb734676b5e5b3d5214a94f1c6c3d5001b4f095 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 17:32:11 +0800 +Subject: Bluetooth: L2CAP: Fix send LE flow credits in ACL link + +From: Zhang Chen + +[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ] + +When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, +l2cap_publish_rx_avail will be called and le flow credits will be sent in +l2cap_chan_rx_avail, even though the link type is ACL. + +The logs in question as follows: +> ACL Data RX: Handle 129 flags 0x02 dlen 12 + L2CAP: Unknown (0x16) ident 4 len 4 + 40 00 ed 05 +< ACL Data TX: Handle 129 flags 0x00 dlen 10 + L2CAP: Command Reject (0x01) ident 4 len 2 + Reason: Command not understood (0x0000) + +Bluetooth: Unknown BR/EDR signaling command 0x16 +Bluetooth: Wrong link type (-22) + +Fixes: ce60b9231b66 ("Bluetooth: compute LE flow credits based on recvbuf space") +Signed-off-by: Zhang Chen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 59cbb8cee6ee7..47625ea36106f 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6553,6 +6553,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + struct l2cap_le_credits pkt; + u16 return_credits = l2cap_le_rx_credits(chan); + ++ if (chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ + if (chan->rx_credits >= return_credits) + return; + +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch b/queue-6.6/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch new file mode 100644 index 0000000000..33b52ca422 --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-validate-pdu-length-before-reading-s.patch @@ -0,0 +1,46 @@ +From 5c9dac4e44d8581c189536e105b838c960faedba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:22:39 +0900 +Subject: Bluetooth: L2CAP: Validate PDU length before reading SDU length in + l2cap_ecred_data_rcv() + +From: Hyunwoo Kim + +[ Upstream commit c65bd945d1c08c3db756821b6bf9f1c4a77b29c6 ] + +l2cap_ecred_data_rcv() reads the SDU length field from skb->data using +get_unaligned_le16() without first verifying that skb contains at least +L2CAP_SDULEN_SIZE (2) bytes. When skb->len is less than 2, this reads +past the valid data in the skb. + +The ERTM reassembly path correctly calls pskb_may_pull() before reading +the SDU length (l2cap_reassemble_sdu, L2CAP_SAR_START case). Apply the +same validation to the Enhanced Credit Based Flow Control data path. + +Fixes: aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 16cc5c878305b..59cbb8cee6ee7 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6636,6 +6636,11 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + if (!chan->sdu) { + u16 sdu_len; + ++ if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE)) { ++ err = -EINVAL; ++ goto failed; ++ } ++ + sdu_len = get_unaligned_le16(skb->data); + skb_pull(skb, L2CAP_SDULEN_SIZE); + +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-remove-3-repeated-macro-definitions.patch b/queue-6.6/bluetooth-remove-3-repeated-macro-definitions.patch new file mode 100644 index 0000000000..042f3cc46f --- /dev/null +++ b/queue-6.6/bluetooth-remove-3-repeated-macro-definitions.patch @@ -0,0 +1,38 @@ +From a0e00593be6e411e94c9444819a46c4db7bef8a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Apr 2024 22:51:50 +0800 +Subject: Bluetooth: Remove 3 repeated macro definitions + +From: Zijun Hu + +[ Upstream commit 94c603c28e59091f698efc5caaddc93c365455ab ] + +Macros HCI_REQ_DONE, HCI_REQ_PEND and HCI_REQ_CANCELED are repeatedly +defined twice with hci_request.h, so remove a copy of definition. + +Signed-off-by: Zijun Hu +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 94d8e6fe5d08 ("Bluetooth: btintel: serialize btintel_hw_error() with hci_req_sync_lock") +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_request.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h +index 0be75cf0efed8..c91f2838f5424 100644 +--- a/net/bluetooth/hci_request.h ++++ b/net/bluetooth/hci_request.h +@@ -29,10 +29,6 @@ + #define hci_req_sync_lock(hdev) mutex_lock(&hdev->req_lock) + #define hci_req_sync_unlock(hdev) mutex_unlock(&hdev->req_lock) + +-#define HCI_REQ_DONE 0 +-#define HCI_REQ_PEND 1 +-#define HCI_REQ_CANCELED 2 +- + struct hci_request { + struct hci_dev *hdev; + struct sk_buff_head cmd_q; +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch b/queue-6.6/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch new file mode 100644 index 0000000000..5d5105728b --- /dev/null +++ b/queue-6.6/bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch @@ -0,0 +1,63 @@ +From a87d46731c378b5681bf19be4534e6a64bb509d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Mar 2026 05:26:16 +0900 +Subject: Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing + sock_hold + +From: Hyunwoo Kim + +[ Upstream commit 598dbba9919c5e36c54fe1709b557d64120cb94b ] + +sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately +releases the lock without holding a reference to the socket. A concurrent +close() can free the socket between the lock release and the subsequent +sk->sk_state access, resulting in a use-after-free. + +Other functions in the same file (sco_sock_timeout(), sco_conn_del()) +correctly use sco_sock_hold() to safely hold a reference under the lock. + +Fix by using sco_sock_hold() to take a reference before releasing the +lock, and adding sock_put() on all exit paths. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 6635d155e360b..56a146515df9e 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -338,7 +338,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + struct sock *sk; + + sco_conn_lock(conn); +- sk = conn->sk; ++ sk = sco_sock_hold(conn); + sco_conn_unlock(conn); + + if (!sk) +@@ -347,11 +347,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) + BT_DBG("sk %p len %u", sk, skb->len); + + if (sk->sk_state != BT_CONNECTED) +- goto drop; ++ goto drop_put; + +- if (!sock_queue_rcv_skb(sk, skb)) ++ if (!sock_queue_rcv_skb(sk, skb)) { ++ sock_put(sk); + return; ++ } + ++drop_put: ++ sock_put(sk); + drop: + kfree_skb(skb); + } +-- +2.51.0 + diff --git a/queue-6.6/can-statistics-add-missing-atomic-access-in-hot-path.patch b/queue-6.6/can-statistics-add-missing-atomic-access-in-hot-path.patch new file mode 100644 index 0000000000..be1ad931ae --- /dev/null +++ b/queue-6.6/can-statistics-add-missing-atomic-access-in-hot-path.patch @@ -0,0 +1,76 @@ +From 505ac79d6d066f0405cb79cdecd15df16204f06f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 18:34:13 +0100 +Subject: can: statistics: add missing atomic access in hot path + +From: Oliver Hartkopp + +[ Upstream commit 46eee1661aa9b49966e6c43d07126fe408edda57 ] + +Commit 80b5f90158d1 ("can: statistics: use atomic access in hot path") +fixed a KCSAN issue in can_receive() but missed to convert the 'matches' +variable used in can_rcv_filter(). + +Fixes: 80b5f90158d1 ("can: statistics: use atomic access in hot path") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260318173413.28235-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/af_can.c | 4 ++-- + net/can/af_can.h | 2 +- + net/can/proc.c | 3 ++- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index cdad0be43e8ff..e0ad55b9af646 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -467,7 +467,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, + + rcv->can_id = can_id; + rcv->mask = mask; +- rcv->matches = 0; ++ atomic_long_set(&rcv->matches, 0); + rcv->func = func; + rcv->data = data; + rcv->ident = ident; +@@ -571,7 +571,7 @@ EXPORT_SYMBOL(can_rx_unregister); + static inline void deliver(struct sk_buff *skb, struct receiver *rcv) + { + rcv->func(skb, rcv->data); +- rcv->matches++; ++ atomic_long_inc(&rcv->matches); + } + + static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb) +diff --git a/net/can/af_can.h b/net/can/af_can.h +index 22f3352c77fec..87887014f5628 100644 +--- a/net/can/af_can.h ++++ b/net/can/af_can.h +@@ -52,7 +52,7 @@ struct receiver { + struct hlist_node list; + canid_t can_id; + canid_t mask; +- unsigned long matches; ++ atomic_long_t matches; + void (*func)(struct sk_buff *skb, void *data); + void *data; + char *ident; +diff --git a/net/can/proc.c b/net/can/proc.c +index 25fdf060e30d0..2f78ea8ac30b0 100644 +--- a/net/can/proc.c ++++ b/net/can/proc.c +@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, + " %-5s %03x %08x %pK %pK %8ld %s\n"; + + seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, +- r->func, r->data, r->matches, r->ident); ++ r->func, r->data, atomic_long_read(&r->matches), ++ r->ident); + } + } + +-- +2.51.0 + diff --git a/queue-6.6/dma-mapping-add-missing-inline-for-dma_free_attrs.patch b/queue-6.6/dma-mapping-add-missing-inline-for-dma_free_attrs.patch new file mode 100644 index 0000000000..f924bd4594 --- /dev/null +++ b/queue-6.6/dma-mapping-add-missing-inline-for-dma_free_attrs.patch @@ -0,0 +1,55 @@ +From 3e6312330c46da1a5b76e33ac2eb076dca7c373c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 02:55:48 +0100 +Subject: dma-mapping: add missing `inline` for `dma_free_attrs` + +From: Miguel Ojeda + +[ Upstream commit 2cdaff22ed26f1e619aa2b43f27bb84f2c6ef8f8 ] + +Under an UML build for an upcoming series [1], I got `-Wstatic-in-inline` +for `dma_free_attrs`: + + BINDGEN rust/bindings/bindings_generated.rs - due to target missing + In file included from rust/helpers/helpers.c:59: + rust/helpers/dma.c:17:2: warning: static function 'dma_free_attrs' is used in an inline function with external linkage [-Wstatic-in-inline] + 17 | dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); + | ^ + rust/helpers/dma.c:12:1: note: use 'static' to give inline function 'rust_helper_dma_free_attrs' internal linkage + 12 | __rust_helper void rust_helper_dma_free_attrs(struct device *dev, size_t size, + | ^ + | static + +The issue is that `dma_free_attrs` was not marked `inline` when it was +introduced alongside the rest of the stubs. + +Thus mark it. + +Fixes: ed6ccf10f24b ("dma-mapping: properly stub out the DMA API for !CONFIG_HAS_DMA") +Closes: https://lore.kernel.org/rust-for-linux/20260322194616.89847-1-ojeda@kernel.org/ [1] +Signed-off-by: Miguel Ojeda +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260325015548.70912-1-ojeda@kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index 608e8296ba206..d5cd7b243b87d 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -219,8 +219,8 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, + { + return NULL; + } +-static void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr, +- dma_addr_t dma_handle, unsigned long attrs) ++static inline void dma_free_attrs(struct device *dev, size_t size, ++ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs) + { + } + static inline void *dmam_alloc_attrs(struct device *dev, size_t size, +-- +2.51.0 + diff --git a/queue-6.6/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch b/queue-6.6/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch new file mode 100644 index 0000000000..1e49795b5d --- /dev/null +++ b/queue-6.6/dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch @@ -0,0 +1,83 @@ +From cb8cebe2b0385ca20be048ce61447778ec591e16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Mar 2026 17:27:49 +0900 +Subject: dma: swiotlb: add KMSAN annotations to swiotlb_bounce() + +From: Shigeru Yoshida + +[ Upstream commit 6f770b73d0311a5b099277653199bb6421c4fed2 ] + +When a device performs DMA to a bounce buffer, KMSAN is unaware of +the write and does not mark the data as initialized. When +swiotlb_bounce() later copies the bounce buffer back to the original +buffer, memcpy propagates the uninitialized shadow to the original +buffer, causing false positive uninit-value reports. + +Fix this by calling kmsan_unpoison_memory() on the bounce buffer +before copying it back in the DMA_FROM_DEVICE path, so that memcpy +naturally propagates initialized shadow to the destination. + +Suggested-by: Alexander Potapenko +Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/ +Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") +Signed-off-by: Shigeru Yoshida +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index e7c3fbd0737ec..2959309c4fb82 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -906,10 +907,19 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + + local_irq_save(flags); + page = pfn_to_page(pfn); +- if (dir == DMA_TO_DEVICE) ++ if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_highmem_page() ++ * could be used here to detect infoleaks, ++ * but callers may map uninitialized buffers ++ * that will be written by the device, ++ * causing false positives. ++ */ + memcpy_from_page(vaddr, page, offset, sz); +- else ++ } else { ++ kmsan_unpoison_memory(vaddr, sz); + memcpy_to_page(page, offset, vaddr, sz); ++ } + local_irq_restore(flags); + + size -= sz; +@@ -918,8 +928,15 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size + offset = 0; + } + } else if (dir == DMA_TO_DEVICE) { ++ /* ++ * Ideally, kmsan_check_memory() could be used here to detect ++ * infoleaks (uninitialized data being sent to device), but ++ * callers may map uninitialized buffers that will be written ++ * by the device, causing false positives. ++ */ + memcpy(vaddr, phys_to_virt(orig_addr), size); + } else { ++ kmsan_unpoison_memory(vaddr, size); + memcpy(phys_to_virt(orig_addr), vaddr, size); + } + } +-- +2.51.0 + diff --git a/queue-6.6/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch b/queue-6.6/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch new file mode 100644 index 0000000000..cdc0b82eb4 --- /dev/null +++ b/queue-6.6/esp-fix-skb-leak-with-espintcp-and-async-crypto.patch @@ -0,0 +1,71 @@ +From 63c35b627fe18189d7281a925fb96d4b0b89827c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:14 +0100 +Subject: esp: fix skb leak with espintcp and async crypto + +From: Sabrina Dubroca + +[ Upstream commit 0c0eef8ccd2413b0a10eb6bbd3442333b1e64dd2 ] + +When the TX queue for espintcp is full, esp_output_tail_tcp will +return an error and not free the skb, because with synchronous crypto, +the common xfrm output code will drop the packet for us. + +With async crypto (esp_output_done), we need to drop the skb when +esp_output_tail_tcp returns an error. + +Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 9 ++++++--- + net/ipv6/esp6.c | 9 ++++++--- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 85e24dc42f2f3..4256c7ee59397 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -233,10 +233,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index be8e2e5b439ed..f3305154745ec 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -269,10 +269,13 @@ static void esp_output_done(void *data, int err) + xfrm_dev_resume(skb); + } else { + if (!err && +- x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) +- esp_output_tail_tcp(x, skb); +- else ++ x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) { ++ err = esp_output_tail_tcp(x, skb); ++ if (err != -EINPROGRESS) ++ kfree_skb(skb); ++ } else { + xfrm_output_resume(skb_to_full_sk(skb), skb, err); ++ } + } + } + +-- +2.51.0 + diff --git a/queue-6.6/ice-use-ice_update_eth_stats-for-representor-stats.patch b/queue-6.6/ice-use-ice_update_eth_stats-for-representor-stats.patch new file mode 100644 index 0000000000..d034e1f0c3 --- /dev/null +++ b/queue-6.6/ice-use-ice_update_eth_stats-for-representor-stats.patch @@ -0,0 +1,100 @@ +From e1eb853ae0eca4e5da2ead4cbeb5ffed36c03813 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Feb 2026 08:53:11 +0100 +Subject: ice: use ice_update_eth_stats() for representor stats + +From: Petr Oros + +[ Upstream commit 2526e440df2725e7328d59b835a164826f179b93 ] + +ice_repr_get_stats64() and __ice_get_ethtool_stats() call +ice_update_vsi_stats() on the VF's src_vsi. This always returns early +because ICE_VSI_DOWN is permanently set for VF VSIs - ice_up() is never +called on them since queues are managed by iavf through virtchnl. + +In __ice_get_ethtool_stats() the original code called +ice_update_vsi_stats() for all VSIs including representors, iterated +over ice_gstrings_vsi_stats[] to populate the data, and then bailed out +with an early return before the per-queue ring stats section. That early +return was necessary because representor VSIs have no rings on the PF +side - the rings belong to the VF driver (iavf), so accessing per-queue +stats would be invalid. + +Move the representor handling to the top of __ice_get_ethtool_stats() +and call ice_update_eth_stats() directly to read the hardware GLV_* +counters. This matches ice_get_vf_stats() which already uses +ice_update_eth_stats() for the same VF VSI in legacy mode. Apply the +same fix to ice_repr_get_stats64(). + +Note that ice_gstrings_vsi_stats[] contains five software ring counters +(rx_buf_failed, rx_page_failed, tx_linearize, tx_busy, tx_restart) that +are always zero for representors since the PF never processes packets on +VF rings. This is pre-existing behavior unchanged by this patch. + +Fixes: 7aae80cef7ba ("ice: add port representor ethtool ops and stats") +Signed-off-by: Petr Oros +Reviewed-by: Aleksandr Loktionov +Tested-by: Patryk Holda +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 14 +++++++++++--- + drivers/net/ethernet/intel/ice/ice_repr.c | 3 ++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 1c91f1ba11889..448ca855df901 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -1528,6 +1528,17 @@ __ice_get_ethtool_stats(struct net_device *netdev, + int i = 0; + char *p; + ++ if (ice_is_port_repr_netdev(netdev)) { ++ ice_update_eth_stats(vsi); ++ ++ for (j = 0; j < ICE_VSI_STATS_LEN; j++) { ++ p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; ++ data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == ++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p; ++ } ++ return; ++ } ++ + ice_update_pf_stats(pf); + ice_update_vsi_stats(vsi); + +@@ -1537,9 +1548,6 @@ __ice_get_ethtool_stats(struct net_device *netdev, + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + +- if (ice_is_port_repr_netdev(netdev)) +- return; +- + /* populate per queue stats */ + rcu_read_lock(); + +diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c +index c686ac0935ebe..23c243d544462 100644 +--- a/drivers/net/ethernet/intel/ice/ice_repr.c ++++ b/drivers/net/ethernet/intel/ice/ice_repr.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2019-2021, Intel Corporation. */ + + #include "ice.h" ++#include "ice_lib.h" + #include "ice_eswitch.h" + #include "ice_devlink.h" + #include "ice_sriov.h" +@@ -57,7 +58,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) + return; + vsi = np->repr->src_vsi; + +- ice_update_vsi_stats(vsi); ++ ice_update_eth_stats(vsi); + eth_stats = &vsi->eth_stats; + + stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast + +-- +2.51.0 + diff --git a/queue-6.6/ionic-fix-persistent-mac-address-override-on-pf.patch b/queue-6.6/ionic-fix-persistent-mac-address-override-on-pf.patch new file mode 100644 index 0000000000..0adcb3b02c --- /dev/null +++ b/queue-6.6/ionic-fix-persistent-mac-address-override-on-pf.patch @@ -0,0 +1,68 @@ +From 8ba1a8613f1dae4773479f6897670897a8314ef3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 19:08:06 +0200 +Subject: ionic: fix persistent MAC address override on PF + +From: Mohammad Heib + +[ Upstream commit cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed ] + +The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes +the ionic firmware to update the LIF's identity in its persistent state. +Since the firmware state is maintained across host warm boots and driver +reloads, any MAC change on the Physical Function (PF) becomes "sticky. + +This is problematic because it causes ethtool -P to report the +user-configured MAC as the permanent factory address, which breaks +system management tools that rely on a stable hardware identity. + +While Virtual Functions (VFs) need this hardware-level programming to +properly handle MAC assignments in guest environments, the PF should +maintain standard transient behavior. This patch gates the +ionic_program_mac call using is_virtfn so that PF MAC changes remain +local to the netdev filters and do not overwrite the firmware's +permanent identity block. + +Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac") +Signed-off-by: Mohammad Heib +Reviewed-by: Simon Horman +Reviewed-by: Brett Creeley +Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 1ac7a40fcc43e..a6a069ba841c8 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -1728,13 +1728,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa) + if (ether_addr_equal(netdev->dev_addr, mac)) + return 0; + +- err = ionic_program_mac(lif, mac); +- if (err < 0) +- return err; ++ /* Only program macs for virtual functions to avoid losing the permanent ++ * Mac across warm reset/reboot. ++ */ ++ if (lif->ionic->pdev->is_virtfn) { ++ err = ionic_program_mac(lif, mac); ++ if (err < 0) ++ return err; + +- if (err > 0) +- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", +- __func__); ++ if (err > 0) ++ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n", ++ __func__); ++ } + + err = eth_prepare_mac_addr_change(netdev, addr); + if (err) +-- +2.51.0 + diff --git a/queue-6.6/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch b/queue-6.6/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch new file mode 100644 index 0000000000..4990c3e58e --- /dev/null +++ b/queue-6.6/ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch @@ -0,0 +1,144 @@ +From a0fa6fdf54075c4df892b365d837540629fb82bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:23:00 +0000 +Subject: ipv6: Don't remove permanent routes with exceptions from + tb6_gc_hlist. + +From: Kuniyuki Iwashima + +[ Upstream commit 4be7b99c253f0c85a255cc1db7127ba3232dfa30 ] + +The cited commit mechanically put fib6_remove_gc_list() +just after every fib6_clean_expires() call. + +When a temporary route is promoted to a permanent route, +there may already be exception routes tied to it. + +If fib6_remove_gc_list() removes the route from tb6_gc_hlist, +such exception routes will no longer be aged. + +Let's replace fib6_remove_gc_list() with a new helper +fib6_may_remove_gc_list() and use fib6_age_exceptions() there. + +Note that net->ipv6 is only compiled when CONFIG_IPV6 is +enabled, so fib6_{add,remove,may_remove}_gc_list() are guarded. + +Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/ip6_fib.h | 21 ++++++++++++++++++++- + net/ipv6/addrconf.c | 4 ++-- + net/ipv6/ip6_fib.c | 6 +++--- + net/ipv6/route.c | 2 +- + 4 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index f4c5b705418c0..05489554019b4 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -512,12 +512,14 @@ void fib6_rt_update(struct net *net, struct fib6_info *rt, + void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + unsigned int flags); + ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now); + void fib6_run_gc(unsigned long expires, struct net *net, bool force); +- + void fib6_gc_cleanup(void); + + int fib6_init(void); + ++#if IS_ENABLED(CONFIG_IPV6) + /* Add the route to the gc list if it is not already there + * + * The callers should hold f6i->fib6_table->tb6_lock. +@@ -550,6 +552,23 @@ static inline void fib6_remove_gc_list(struct fib6_info *f6i) + hlist_del_init(&f6i->gc_link); + } + ++static inline void fib6_may_remove_gc_list(struct net *net, ++ struct fib6_info *f6i) ++{ ++ struct fib6_gc_args gc_args; ++ ++ if (hlist_unhashed(&f6i->gc_link)) ++ return; ++ ++ gc_args.timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_interval); ++ gc_args.more = 0; ++ ++ rcu_read_lock(); ++ fib6_age_exceptions(f6i, &gc_args, jiffies); ++ rcu_read_unlock(); ++} ++#endif ++ + struct ipv6_route_iter { + struct seq_net_private p; + struct fib6_walker w; +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 4958452cd3320..7fcc68dcf144b 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2831,7 +2831,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) + fib6_add_gc_list(rt); + } else { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } + + spin_unlock_bh(&table->tb6_lock); +@@ -4816,7 +4816,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp, + + if (!expires) { + fib6_clean_expires(f6i); +- fib6_remove_gc_list(f6i); ++ fib6_may_remove_gc_list(net, f6i); + } else { + fib6_set_expires(f6i, expires); + fib6_add_gc_list(f6i); +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index bec610819fc1b..7a28807ca4464 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1131,7 +1131,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + return -EEXIST; + if (!(rt->fib6_flags & RTF_EXPIRES)) { + fib6_clean_expires(iter); +- fib6_remove_gc_list(iter); ++ fib6_may_remove_gc_list(info->nl_net, iter); + } else { + fib6_set_expires(iter, rt->expires); + fib6_add_gc_list(iter); +@@ -2311,8 +2311,8 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ +-static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, +- unsigned long now) ++void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) + { + bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; + int old_more = gc_args->more; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 5a6cc828855dc..c5b71baf95e7b 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1035,7 +1035,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + + if (!addrconf_finite_timeout(lifetime)) { + fib6_clean_expires(rt); +- fib6_remove_gc_list(rt); ++ fib6_may_remove_gc_list(net, rt); + } else { + fib6_set_expires(rt, jiffies + HZ * lifetime); + fib6_add_gc_list(rt); +-- +2.51.0 + diff --git a/queue-6.6/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch b/queue-6.6/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch new file mode 100644 index 0000000000..abcaebd607 --- /dev/null +++ b/queue-6.6/ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch @@ -0,0 +1,76 @@ +From 1b62d1028a4656c2c2a21d632c8289fc030231d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 07:22:59 +0000 +Subject: ipv6: Remove permanent routes from tb6_gc_hlist when all exceptions + expire. + +From: Kuniyuki Iwashima + +[ Upstream commit 6af51e9f31336632263c4680b2a3712295103e1f ] + +Commit 5eb902b8e719 ("net/ipv6: Remove expired routes with a +separated list of routes.") introduced a per-table GC list and +changed GC to iterate over that list instead of traversing +the entire route table. + +However, it forgot to add permanent routes to tb6_gc_hlist +when exception routes are added. + +Commit cfe82469a00f ("ipv6: add exception routes to GC list +in rt6_insert_exception") fixed that issue but introduced +another one. + +Even after all exception routes expire, the permanent routes +remain in tb6_gc_hlist, potentially negating the performance +benefits intended by the initial change. + +Let's count gc_args->more before and after rt6_age_exceptions() +and remove the permanent route when the delta is 0. + +Note that the next patch will reuse fib6_age_exceptions(). + +Fixes: cfe82469a00f ("ipv6: add exception routes to GC list in rt6_insert_exception") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Xin Long +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260320072317.2561779-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 6fe867579118b..bec610819fc1b 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -2311,6 +2311,17 @@ static void fib6_flush_trees(struct net *net) + /* + * Garbage collection + */ ++static void fib6_age_exceptions(struct fib6_info *rt, struct fib6_gc_args *gc_args, ++ unsigned long now) ++{ ++ bool may_expire = rt->fib6_flags & RTF_EXPIRES && rt->expires; ++ int old_more = gc_args->more; ++ ++ rt6_age_exceptions(rt, gc_args, now); ++ ++ if (!may_expire && old_more == gc_args->more) ++ fib6_remove_gc_list(rt); ++} + + static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + { +@@ -2333,7 +2344,7 @@ static int fib6_age(struct fib6_info *rt, struct fib6_gc_args *gc_args) + * Note, that clones are aged out + * only if they are not in use now. + */ +- rt6_age_exceptions(rt, gc_args, now); ++ fib6_age_exceptions(rt, gc_args, now); + + return 0; + } +-- +2.51.0 + diff --git a/queue-6.6/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch b/queue-6.6/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch new file mode 100644 index 0000000000..8f3b9747c2 --- /dev/null +++ b/queue-6.6/net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch @@ -0,0 +1,46 @@ +From 0908d976d4a0d8ce7e82a4c52b3ad46d0adeeca8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 17:42:22 +0800 +Subject: net: enetc: fix the output issue of 'ethtool --show-ring' + +From: Wei Fang + +[ Upstream commit 70b439bf06f6a12e491f827fa81a9887a11501f9 ] + +Currently, enetc_get_ringparam() only provides rx_pending and tx_pending, +but 'ethtool --show-ring' no longer displays these fields. Because the +ringparam retrieval path has moved to the new netlink interface, where +rings_fill_reply() emits the *x_pending only if the *x_max_pending values +are non-zero. So rx_max_pending and tx_max_pending to are added to +enetc_get_ringparam() to fix the issue. + +Note that the maximum tx/rx ring size of hardware is 64K, but we haven't +added set_ringparam() to make the ring size configurable. To avoid users +mistakenly believing that the ring size can be increased, so set +the *x_max_pending to priv->*x_bd_count. + +Fixes: e4a1717b677c ("ethtool: provide ring sizes with RINGS_GET request") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20260320094222.706339-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +index 1e3e0073276ec..f641fb4c59980 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +@@ -747,6 +747,8 @@ static void enetc_get_ringparam(struct net_device *ndev, + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + ++ ring->rx_max_pending = priv->rx_bd_count; ++ ring->tx_max_pending = priv->tx_bd_count; + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + +-- +2.51.0 + diff --git a/queue-6.6/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch b/queue-6.6/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch new file mode 100644 index 0000000000..c1dc0f30b4 --- /dev/null +++ b/queue-6.6/net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch @@ -0,0 +1,53 @@ +From e3b3f14543de0247d22ae108d44479ddeb13fa65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 22:06:10 +0200 +Subject: net: fix fanout UAF in packet_release() via NETDEV_UP race + +From: Yochai Eisenrich + +[ Upstream commit 42156f93d123436f2a27c468f18c966b7e5db796 ] + +`packet_release()` has a race window where `NETDEV_UP` can re-register a +socket into a fanout group's `arr[]` array. The re-registration is not +cleaned up by `fanout_release()`, leaving a dangling pointer in the fanout +array. +`packet_release()` does NOT zero `po->num` in its `bind_lock` section. +After releasing `bind_lock`, `po->num` is still non-zero and `po->ifindex` +still matches the bound device. A concurrent `packet_notifier(NETDEV_UP)` +that already found the socket in `sklist` can re-register the hook. +For fanout sockets, this re-registration calls `__fanout_link(sk, po)` +which adds the socket back into `f->arr[]` and increments `f->num_members`, +but does NOT increment `f->sk_ref`. + +The fix sets `po->num` to zero in `packet_release` while `bind_lock` is +held to prevent NETDEV_UP from linking, preventing the race window. + +This bug was found following an additional audit with Claude Code based +on CVE-2025-38617. + +Fixes: ce06b03e60fc ("packet: Add helpers to register/unregister ->prot_hook") +Link: https://blog.calif.io/p/a-race-within-a-race-exploiting-cve +Signed-off-by: Yochai Eisenrich +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260319200610.25101-1-echelonh@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 9620f160be70b..4f2727a42cad1 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3196,6 +3196,7 @@ static int packet_release(struct socket *sock) + + spin_lock(&po->bind_lock); + unregister_prot_hook(sk, false); ++ WRITE_ONCE(po->num, 0); + packet_cached_dev_reset(po); + + if (po->prot_hook.dev) { +-- +2.51.0 + diff --git a/queue-6.6/net-macb-use-the-current-queue-number-for-stats.patch b/queue-6.6/net-macb-use-the-current-queue-number-for-stats.patch new file mode 100644 index 0000000000..a3fac0800c --- /dev/null +++ b/queue-6.6/net-macb-use-the-current-queue-number-for-stats.patch @@ -0,0 +1,95 @@ +From c20f7c567ae22f0c844d12db8d54688669da37c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Mar 2026 20:16:34 +0100 +Subject: net: macb: use the current queue number for stats + +From: Paolo Valerio + +[ Upstream commit 72d96e4e24bbefdcfbc68bdb9341a05d8f5cb6e5 ] + +There's a potential mismatch between the memory reserved for statistics +and the amount of memory written. + +gem_get_sset_count() correctly computes the number of stats based on the +active queues, whereas gem_get_ethtool_stats() indiscriminately copies +data using the maximum number of queues, and in the case the number of +active queues is less than MACB_MAX_QUEUES, this results in a OOB write +as observed in the KASAN splat. + +================================================================== +BUG: KASAN: vmalloc-out-of-bounds in gem_get_ethtool_stats+0x54/0x78 + [macb] +Write of size 760 at addr ffff80008080b000 by task ethtool/1027 + +CPU: [...] +Tainted: [E]=UNSIGNED_MODULE +Hardware name: raspberrypi rpi/rpi, BIOS 2025.10 10/01/2025 +Call trace: + show_stack+0x20/0x38 (C) + dump_stack_lvl+0x80/0xf8 + print_report+0x384/0x5e0 + kasan_report+0xa0/0xf0 + kasan_check_range+0xe8/0x190 + __asan_memcpy+0x54/0x98 + gem_get_ethtool_stats+0x54/0x78 [macb + 926c13f3af83b0c6fe64badb21ec87d5e93fcf65] + dev_ethtool+0x1220/0x38c0 + dev_ioctl+0x4ac/0xca8 + sock_do_ioctl+0x170/0x1d8 + sock_ioctl+0x484/0x5d8 + __arm64_sys_ioctl+0x12c/0x1b8 + invoke_syscall+0xd4/0x258 + el0_svc_common.constprop.0+0xb4/0x240 + do_el0_svc+0x48/0x68 + el0_svc+0x40/0xf8 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + +The buggy address belongs to a 1-page vmalloc region starting at + 0xffff80008080b000 allocated at dev_ethtool+0x11f0/0x38c0 +The buggy address belongs to the physical page: +page: refcount:1 mapcount:0 mapping:0000000000000000 + index:0xffff00000a333000 pfn:0xa333 +flags: 0x7fffc000000000(node=0|zone=0|lastcpupid=0x1ffff) +raw: 007fffc000000000 0000000000000000 dead000000000122 0000000000000000 +raw: ffff00000a333000 0000000000000000 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff80008080b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff80008080b100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff80008080b180: 00 00 00 00 00 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ^ + ffff80008080b200: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 + ffff80008080b280: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 +================================================================== + +Fix it by making sure the copied size only considers the active number of +queues. + +Fixes: 512286bbd4b7 ("net: macb: Added some queue statistics") +Signed-off-by: Paolo Valerio +Reviewed-by: Nicolai Buchwitz +Link: https://patch.msgid.link/20260323191634.2185840-1-pvalerio@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 693688a580022..18dd191526448 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -3255,7 +3255,7 @@ static void gem_get_ethtool_stats(struct net_device *dev, + spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) +- * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ * (GEM_STATS_LEN + QUEUE_STATS_LEN * bp->num_queues)); + spin_unlock_irq(&bp->stats_lock); + } + +-- +2.51.0 + diff --git a/queue-6.6/net-openvswitch-avoid-releasing-netdev-before-teardo.patch b/queue-6.6/net-openvswitch-avoid-releasing-netdev-before-teardo.patch new file mode 100644 index 0000000000..635e82deb6 --- /dev/null +++ b/queue-6.6/net-openvswitch-avoid-releasing-netdev-before-teardo.patch @@ -0,0 +1,128 @@ +From 963dc75bbbb9f38e8e5089241038288d89bb18c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 16:55:51 +0100 +Subject: net: openvswitch: Avoid releasing netdev before teardown completes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +[ Upstream commit 7c770dadfda5cbbde6aa3c4363ed513f1d212bf8 ] + +The patch cited in the Fixes tag below changed the teardown code for +OVS ports to no longer unconditionally take the RTNL. After this change, +the netdev_destroy() callback can proceed immediately to the call_rcu() +invocation if the IFF_OVS_DATAPATH flag is already cleared on the +netdev. + +The ovs_netdev_detach_dev() function clears the flag before completing +the unregistration, and if it gets preempted after clearing the flag (as +can happen on an -rt kernel), netdev_destroy() can complete and the +device can be freed before the unregistration completes. This leads to a +splat like: + +[ 998.393867] Oops: general protection fault, probably for non-canonical address 0xff00000001000239: 0000 [#1] SMP PTI +[ 998.393877] CPU: 42 UID: 0 PID: 55177 Comm: ip Kdump: loaded Not tainted 6.12.0-211.1.1.el10_2.x86_64+rt #1 PREEMPT_RT +[ 998.393886] Hardware name: Dell Inc. PowerEdge R740/0JMK61, BIOS 2.24.0 03/27/2025 +[ 998.393889] RIP: 0010:dev_set_promiscuity+0x8d/0xa0 +[ 998.393901] Code: 00 00 75 d8 48 8b 53 08 48 83 ba b0 02 00 00 00 75 ca 48 83 c4 08 5b c3 cc cc cc cc 48 83 bf 48 09 00 00 00 75 91 48 8b 47 08 <48> 83 b8 b0 02 00 00 00 74 97 eb 81 0f 1f 80 00 00 00 00 90 90 90 +[ 998.393906] RSP: 0018:ffffce5864a5f6a0 EFLAGS: 00010246 +[ 998.393912] RAX: ff00000000ffff89 RBX: ffff894d0adf5a05 RCX: 0000000000000000 +[ 998.393917] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffff894d0adf5a05 +[ 998.393921] RBP: ffff894d19252000 R08: ffff894d19252000 R09: 0000000000000000 +[ 998.393924] R10: ffff894d19252000 R11: ffff894d192521b8 R12: 0000000000000006 +[ 998.393927] R13: ffffce5864a5f738 R14: 00000000ffffffe2 R15: 0000000000000000 +[ 998.393931] FS: 00007fad61971800(0000) GS:ffff894cc0140000(0000) knlGS:0000000000000000 +[ 998.393936] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 998.393940] CR2: 000055df0a2a6e40 CR3: 000000011c7fe003 CR4: 00000000007726f0 +[ 998.393944] PKRU: 55555554 +[ 998.393946] Call Trace: +[ 998.393949] +[ 998.393952] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393961] ? show_trace_log_lvl+0x1b0/0x2f0 +[ 998.393975] ? dp_device_event+0x41/0x80 [openvswitch] +[ 998.394009] ? __die_body.cold+0x8/0x12 +[ 998.394016] ? die_addr+0x3c/0x60 +[ 998.394027] ? exc_general_protection+0x16d/0x390 +[ 998.394042] ? asm_exc_general_protection+0x26/0x30 +[ 998.394058] ? dev_set_promiscuity+0x8d/0xa0 +[ 998.394066] ? ovs_netdev_detach_dev+0x3a/0x80 [openvswitch] +[ 998.394092] dp_device_event+0x41/0x80 [openvswitch] +[ 998.394102] notifier_call_chain+0x5a/0xd0 +[ 998.394106] unregister_netdevice_many_notify+0x51b/0xa60 +[ 998.394110] rtnl_dellink+0x169/0x3e0 +[ 998.394121] ? rt_mutex_slowlock.constprop.0+0x95/0xd0 +[ 998.394125] rtnetlink_rcv_msg+0x142/0x3f0 +[ 998.394128] ? avc_has_perm_noaudit+0x69/0xf0 +[ 998.394130] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 +[ 998.394132] netlink_rcv_skb+0x50/0x100 +[ 998.394138] netlink_unicast+0x292/0x3f0 +[ 998.394141] netlink_sendmsg+0x21b/0x470 +[ 998.394145] ____sys_sendmsg+0x39d/0x3d0 +[ 998.394149] ___sys_sendmsg+0x9a/0xe0 +[ 998.394156] __sys_sendmsg+0x7a/0xd0 +[ 998.394160] do_syscall_64+0x7f/0x170 +[ 998.394162] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 998.394165] RIP: 0033:0x7fad61bf4724 +[ 998.394188] Code: 89 02 b8 ff ff ff ff eb bb 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 80 3d c5 e9 0c 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 89 54 24 1c 48 89 +[ 998.394189] RSP: 002b:00007ffd7e2f7cb8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e +[ 998.394191] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fad61bf4724 +[ 998.394193] RDX: 0000000000000000 RSI: 00007ffd7e2f7d20 RDI: 0000000000000003 +[ 998.394194] RBP: 00007ffd7e2f7d90 R08: 0000000000000010 R09: 000000000000003f +[ 998.394195] R10: 000055df11558010 R11: 0000000000000202 R12: 00007ffd7e2f8380 +[ 998.394196] R13: 0000000069b233d7 R14: 000055df0a256040 R15: 0000000000000000 +[ 998.394200] + +To fix this, reorder the operations in ovs_netdev_detach_dev() to only +clear the flag after completing the other operations, and introduce an +smp_wmb() to make the ordering requirement explicit. The smp_wmb() is +paired with a full smp_mb() in netdev_destroy() to make sure the +call_rcu() invocation does not happen before the unregister operations +are visible. + +Reported-by: Minxi Hou +Tested-by: Minxi Hou +Fixes: 549822767630 ("net: openvswitch: Avoid needlessly taking the RTNL on vport destroy") +Signed-off-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260318155554.1133405-1-toke@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 3c41d53bb9e99..18376e10aeedc 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -144,11 +144,15 @@ static void vport_netdev_free(struct rcu_head *rcu) + void ovs_netdev_detach_dev(struct vport *vport) + { + ASSERT_RTNL(); +- vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + netdev_rx_handler_unregister(vport->dev); + netdev_upper_dev_unlink(vport->dev, + netdev_master_upper_dev_get(vport->dev)); + dev_set_promiscuity(vport->dev, -1); ++ ++ /* paired with smp_mb() in netdev_destroy() */ ++ smp_wmb(); ++ ++ vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; + } + + static void netdev_destroy(struct vport *vport) +@@ -167,6 +171,9 @@ static void netdev_destroy(struct vport *vport) + rtnl_unlock(); + } + ++ /* paired with smp_wmb() in ovs_netdev_detach_dev() */ ++ smp_mb(); ++ + call_rcu(&vport->rcu, vport_netdev_free); + } + +-- +2.51.0 + diff --git a/queue-6.6/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch b/queue-6.6/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch new file mode 100644 index 0000000000..c1ec78cd5c --- /dev/null +++ b/queue-6.6/net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch @@ -0,0 +1,101 @@ +From b0875af1b44366db34fbb60cbdd1e90cce421abf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2026 14:48:47 +0800 +Subject: net/smc: fix double-free of smc_spd_priv when tee() duplicates splice + pipe buffer + +From: Qi Tang + +[ Upstream commit 24dd586bb4cbba1889a50abe74143817a095c1c9 ] + +smc_rx_splice() allocates one smc_spd_priv per pipe_buffer and stores +the pointer in pipe_buffer.private. The pipe_buf_operations for these +buffers used .get = generic_pipe_buf_get, which only increments the page +reference count when tee(2) duplicates a pipe buffer. The smc_spd_priv +pointer itself was not handled, so after tee() both the original and the +cloned pipe_buffer share the same smc_spd_priv *. + +When both pipes are subsequently released, smc_rx_pipe_buf_release() is +called twice against the same object: + + 1st call: kfree(priv) sock_put(sk) smc_rx_update_cons() [correct] + 2nd call: kfree(priv) sock_put(sk) smc_rx_update_cons() [UAF] + +KASAN reports a slab-use-after-free in smc_rx_pipe_buf_release(), which +then escalates to a NULL-pointer dereference and kernel panic via +smc_rx_update_consumer() when it chases the freed priv->smc pointer: + + BUG: KASAN: slab-use-after-free in smc_rx_pipe_buf_release+0x78/0x2a0 + Read of size 8 at addr ffff888004a45740 by task smc_splice_tee_/74 + Call Trace: + + dump_stack_lvl+0x53/0x70 + print_report+0xce/0x650 + kasan_report+0xc6/0x100 + smc_rx_pipe_buf_release+0x78/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + + BUG: kernel NULL pointer dereference, address: 0000000000000020 + RIP: 0010:smc_rx_update_consumer+0x8d/0x350 + Call Trace: + + smc_rx_pipe_buf_release+0x121/0x2a0 + free_pipe_info+0xd4/0x130 + pipe_release+0x142/0x160 + __fput+0x1c6/0x490 + __x64_sys_close+0x4f/0x90 + do_syscall_64+0xa6/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Kernel panic - not syncing: Fatal exception + +Beyond the memory-safety problem, duplicating an SMC splice buffer is +semantically questionable: smc_rx_update_cons() would advance the +consumer cursor twice for the same data, corrupting receive-window +accounting. A refcount on smc_spd_priv could fix the double-free, but +the cursor-accounting issue would still need to be addressed separately. + +The .get callback is invoked by both tee(2) and splice_pipe_to_pipe() +for partial transfers; both will now return -EFAULT. Users who need +to duplicate SMC socket data must use a copy-based read path. + +Fixes: 9014db202cb7 ("smc: add support for splice()") +Signed-off-by: Qi Tang +Link: https://patch.msgid.link/20260318064847.23341-1-tpluszz77@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_rx.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c +index acb14e28cad41..a48f8c93f4b63 100644 +--- a/net/smc/smc_rx.c ++++ b/net/smc/smc_rx.c +@@ -135,9 +135,16 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe, + sock_put(sk); + } + ++static bool smc_rx_pipe_buf_get(struct pipe_inode_info *pipe, ++ struct pipe_buffer *buf) ++{ ++ /* smc_spd_priv in buf->private is not shareable; disallow cloning. */ ++ return false; ++} ++ + static const struct pipe_buf_operations smc_pipe_ops = { + .release = smc_rx_pipe_buf_release, +- .get = generic_pipe_buf_get ++ .get = smc_rx_pipe_buf_get, + }; + + static void smc_rx_spd_release(struct splice_pipe_desc *spd, +-- +2.51.0 + diff --git a/queue-6.6/netfilter-ctnetlink-use-netlink-policy-range-checks.patch b/queue-6.6/netfilter-ctnetlink-use-netlink-policy-range-checks.patch new file mode 100644 index 0000000000..deee03bb0c --- /dev/null +++ b/queue-6.6/netfilter-ctnetlink-use-netlink-policy-range-checks.patch @@ -0,0 +1,127 @@ +From 5750ab933b529b3703a76960049c5d5775a47475 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:08 +0100 +Subject: netfilter: ctnetlink: use netlink policy range checks + +From: David Carlier + +[ Upstream commit 8f15b5071b4548b0aafc03b366eb45c9c6566704 ] + +Replace manual range and mask validations with netlink policy +annotations in ctnetlink code paths, so that the netlink core rejects +invalid values early and can generate extack errors. + +- CTA_PROTOINFO_TCP_STATE: reject values > TCP_CONNTRACK_SYN_SENT2 at + policy level, removing the manual >= TCP_CONNTRACK_MAX check. +- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL/REPLY: reject values > TCP_MAX_WSCALE + (14). The normal TCP option parsing path already clamps to this value, + but the ctnetlink path accepted 0-255, causing undefined behavior when + used as a u32 shift count. +- CTA_FILTER_ORIG_FLAGS/REPLY_FLAGS: use NLA_POLICY_MASK with + CTA_FILTER_F_ALL, removing the manual mask checks. +- CTA_EXPECT_FLAGS: use NLA_POLICY_MASK with NF_CT_EXPECT_MASK, adding + a new mask define grouping all valid expect flags. + +Extracted from a broader nf-next patch by Florian Westphal, scoped to +ctnetlink for the fixes tree. + +Fixes: c8e2078cfe41 ("[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling") +Signed-off-by: David Carlier +Co-developed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + .../uapi/linux/netfilter/nf_conntrack_common.h | 4 ++++ + net/netfilter/nf_conntrack_netlink.c | 16 +++++----------- + net/netfilter/nf_conntrack_proto_tcp.c | 10 +++------- + 3 files changed, 12 insertions(+), 18 deletions(-) + +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 26071021e986f..56b6b60a814f5 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -159,5 +159,9 @@ enum ip_conntrack_expect_events { + #define NF_CT_EXPECT_INACTIVE 0x2 + #define NF_CT_EXPECT_USERSPACE 0x4 + ++#ifdef __KERNEL__ ++#define NF_CT_EXPECT_MASK (NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE | \ ++ NF_CT_EXPECT_USERSPACE) ++#endif + + #endif /* _UAPI_NF_CONNTRACK_COMMON_H */ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index b4761a060e7a0..718526867ffdc 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -883,8 +883,8 @@ struct ctnetlink_filter { + }; + + static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = { +- [CTA_FILTER_ORIG_FLAGS] = { .type = NLA_U32 }, +- [CTA_FILTER_REPLY_FLAGS] = { .type = NLA_U32 }, ++ [CTA_FILTER_ORIG_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), ++ [CTA_FILTER_REPLY_FLAGS] = NLA_POLICY_MASK(NLA_U32, CTA_FILTER_F_ALL), + }; + + static int ctnetlink_parse_filter(const struct nlattr *attr, +@@ -898,17 +898,11 @@ static int ctnetlink_parse_filter(const struct nlattr *attr, + if (ret) + return ret; + +- if (tb[CTA_FILTER_ORIG_FLAGS]) { ++ if (tb[CTA_FILTER_ORIG_FLAGS]) + filter->orig_flags = nla_get_u32(tb[CTA_FILTER_ORIG_FLAGS]); +- if (filter->orig_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + +- if (tb[CTA_FILTER_REPLY_FLAGS]) { ++ if (tb[CTA_FILTER_REPLY_FLAGS]) + filter->reply_flags = nla_get_u32(tb[CTA_FILTER_REPLY_FLAGS]); +- if (filter->reply_flags & ~CTA_FILTER_F_ALL) +- return -EOPNOTSUPP; +- } + + return 0; + } +@@ -2622,7 +2616,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING, + .len = NF_CT_HELPER_NAME_LEN - 1 }, + [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, +- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, ++ [CTA_EXPECT_FLAGS] = NLA_POLICY_MASK(NLA_BE32, NF_CT_EXPECT_MASK), + [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 53d46ebcb5f76..fd080f05eaf93 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -1384,9 +1384,9 @@ static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, + } + + static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = { +- [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 }, +- [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 }, ++ [CTA_PROTOINFO_TCP_STATE] = NLA_POLICY_MAX(NLA_U8, TCP_CONNTRACK_SYN_SENT2), ++ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), ++ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = NLA_POLICY_MAX(NLA_U8, TCP_MAX_WSCALE), + [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) }, + [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) }, + }; +@@ -1413,10 +1413,6 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct) + if (err < 0) + return err; + +- if (tb[CTA_PROTOINFO_TCP_STATE] && +- nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX) +- return -EINVAL; +- + spin_lock_bh(&ct->lock); + if (tb[CTA_PROTOINFO_TCP_STATE]) + ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); +-- +2.51.0 + diff --git a/queue-6.6/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch b/queue-6.6/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch new file mode 100644 index 0000000000..bb9dc915e9 --- /dev/null +++ b/queue-6.6/netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch @@ -0,0 +1,48 @@ +From 39750d1a541c50c0c0ac8dcde87a9679e7222c4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:00 +0100 +Subject: netfilter: ip6t_rt: reject oversized addrnr in rt_mt6_check() + +From: Ren Wei + +[ Upstream commit 9d3f027327c2fa265f7f85ead41294792c3296ed ] + +Reject rt match rules whose addrnr exceeds IP6T_RT_HOPS. + +rt_mt6() expects addrnr to stay within the bounds of rtinfo->addrs[]. +Validate addrnr during rule installation so malformed rules are rejected +before the match logic can use an out-of-range value. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Tested-by: Yuhang Zheng +Signed-off-by: Ren Wei +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter/ip6t_rt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c +index 4ad8b2032f1f9..5561bd9cea818 100644 +--- a/net/ipv6/netfilter/ip6t_rt.c ++++ b/net/ipv6/netfilter/ip6t_rt.c +@@ -157,6 +157,10 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) + pr_debug("unknown flags %X\n", rtinfo->invflags); + return -EINVAL; + } ++ if (rtinfo->addrnr > IP6T_RT_HOPS) { ++ pr_debug("too many addresses specified\n"); ++ return -EINVAL; ++ } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch b/queue-6.6/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch new file mode 100644 index 0000000000..bc9cf0e40b --- /dev/null +++ b/queue-6.6/netfilter-nf_conntrack_expect-skip-expectations-in-o.patch @@ -0,0 +1,46 @@ +From 54547a50d5c1bc923b61a05ba8eeb04ac44648e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:06 +0100 +Subject: netfilter: nf_conntrack_expect: skip expectations in other netns via + proc + +From: Pablo Neira Ayuso + +[ Upstream commit 3db5647984de03d9cae0dcddb509b058351f0ee4 ] + +Skip expectations that do not reside in this netns. + +Similar to e77e6ff502ea ("netfilter: conntrack: do not dump other netns's +conntrack entries via proc"). + +Fixes: 9b03f38d0487 ("netfilter: netns nf_conntrack: per-netns expectations") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_expect.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 81ca348915c98..7bc64eb89bac4 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -627,11 +627,15 @@ static int exp_seq_show(struct seq_file *s, void *v) + { + struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; ++ struct net *net = seq_file_net(s); + struct hlist_node *n = v; + char *delim = ""; + + expect = hlist_entry(n, struct nf_conntrack_expect, hnode); + ++ if (!net_eq(nf_ct_exp_net(expect), net)) ++ return 0; ++ + if (expect->timeout.function) + seq_printf(s, "%ld ", timer_pending(&expect->timeout) + ? (long)(expect->timeout.expires - jiffies)/HZ : 0); +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch b/queue-6.6/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch new file mode 100644 index 0000000000..3a13aad417 --- /dev/null +++ b/queue-6.6/netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch @@ -0,0 +1,93 @@ +From d255dc5780f6392fab5724266d8a82cfb31ceb75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:11:07 +0100 +Subject: netfilter: nf_conntrack_sip: fix use of uninitialized rtp_addr in + process_sdp + +From: Weiming Shi + +[ Upstream commit 6a2b724460cb67caed500c508c2ae5cf012e4db4 ] + +process_sdp() declares union nf_inet_addr rtp_addr on the stack and +passes it to the nf_nat_sip sdp_session hook after walking the SDP +media descriptions. However rtp_addr is only initialized inside the +media loop when a recognized media type with a non-zero port is found. + +If the SDP body contains no m= lines, only inactive media sections +(m=audio 0 ...) or only unrecognized media types, rtp_addr is never +assigned. Despite that, the function still calls hooks->sdp_session() +with &rtp_addr, causing nf_nat_sdp_session() to format the stale stack +value as an IP address and rewrite the SDP session owner and connection +lines with it. + +With CONFIG_INIT_STACK_ALL_ZERO (default on most distributions) this +results in the session-level o= and c= addresses being rewritten to +0.0.0.0 for inactive SDP sessions. Without stack auto-init the +rewritten address is whatever happened to be on the stack. + +Fix this by pre-initializing rtp_addr from the session-level connection +address (caddr) when available, and tracking via a have_rtp_addr flag +whether any valid address was established. Skip the sdp_session hook +entirely when no valid address exists. + +Fixes: 4ab9e64e5e3c ("[NETFILTER]: nf_nat_sip: split up SDP mangling") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_sip.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c +index 657839a58782a..84334537c6067 100644 +--- a/net/netfilter/nf_conntrack_sip.c ++++ b/net/netfilter/nf_conntrack_sip.c +@@ -1040,6 +1040,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + unsigned int port; + const struct sdp_media_type *t; + int ret = NF_ACCEPT; ++ bool have_rtp_addr = false; + + hooks = rcu_dereference(nf_nat_sip_hooks); + +@@ -1056,8 +1057,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + caddr_len = 0; + if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, + SDP_HDR_CONNECTION, SDP_HDR_MEDIA, +- &matchoff, &matchlen, &caddr) > 0) ++ &matchoff, &matchlen, &caddr) > 0) { + caddr_len = matchlen; ++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); ++ have_rtp_addr = true; ++ } + + mediaoff = sdpoff; + for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { +@@ -1091,9 +1095,11 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + &matchoff, &matchlen, &maddr) > 0) { + maddr_len = matchlen; + memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); +- } else if (caddr_len) ++ have_rtp_addr = true; ++ } else if (caddr_len) { + memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); +- else { ++ have_rtp_addr = true; ++ } else { + nf_ct_helper_log(skb, ct, "cannot parse SDP message"); + return NF_DROP; + } +@@ -1125,7 +1131,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, + + /* Update session connection and owner addresses */ + hooks = rcu_dereference(nf_nat_sip_hooks); +- if (hooks && ct->status & IPS_NAT_MASK) ++ if (hooks && ct->status & IPS_NAT_MASK && have_rtp_addr) + ret = hooks->sdp_session(skb, protoff, dataoff, + dptr, datalen, sdpoff, + &rtp_addr); +-- +2.51.0 + diff --git a/queue-6.6/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch b/queue-6.6/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch new file mode 100644 index 0000000000..decedcc00d --- /dev/null +++ b/queue-6.6/netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch @@ -0,0 +1,58 @@ +From ded50bb05148473e982954f76e6cd96abbefcf57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Mar 2026 14:10:58 +0100 +Subject: netfilter: nfnetlink_log: fix uninitialized padding leak in + NFULA_PAYLOAD + +From: Weiming Shi + +[ Upstream commit 52025ebaa29f4eb4ed8bf92ce83a68f24ab7fdf7 ] + +__build_packet_message() manually constructs the NFULA_PAYLOAD netlink +attribute using skb_put() and skb_copy_bits(), bypassing the standard +nla_reserve()/nla_put() helpers. While nla_total_size(data_len) bytes +are allocated (including NLA alignment padding), only data_len bytes +of actual packet data are copied. The trailing nla_padlen(data_len) +bytes (1-3 when data_len is not 4-byte aligned) are never initialized, +leaking stale heap contents to userspace via the NFLOG netlink socket. + +Replace the manual attribute construction with nla_reserve(), which +handles the tailroom check, header setup, and padding zeroing via +__nla_reserve(). The subsequent skb_copy_bits() fills in the payload +data on top of the properly initialized attribute. + +Fixes: df6fb868d611 ("[NETFILTER]: nfnetlink: convert to generic netlink attribute functions") +Reported-by: Xiang Mei +Signed-off-by: Weiming Shi +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 134e05d31061e..aa5fc9bffef0c 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -647,15 +647,11 @@ __build_packet_message(struct nfnl_log_net *log, + + if (data_len) { + struct nlattr *nla; +- int size = nla_attr_size(data_len); + +- if (skb_tailroom(inst->skb) < nla_total_size(data_len)) ++ nla = nla_reserve(inst->skb, NFULA_PAYLOAD, data_len); ++ if (!nla) + goto nla_put_failure; + +- nla = skb_put(inst->skb, nla_total_size(data_len)); +- nla->nla_type = NFULA_PAYLOAD; +- nla->nla_len = size; +- + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + BUG(); + } +-- +2.51.0 + diff --git a/queue-6.6/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch b/queue-6.6/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch new file mode 100644 index 0000000000..154772a898 --- /dev/null +++ b/queue-6.6/nfc-nci-fix-circular-locking-dependency-in-nci_close.patch @@ -0,0 +1,77 @@ +From c50509d397c5f265f01c4a4096afef3ef389a369 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 12:33:34 -0700 +Subject: nfc: nci: fix circular locking dependency in nci_close_device + +From: Jakub Kicinski + +[ Upstream commit 4527025d440ce84bf56e75ce1df2e84cb8178616 ] + +nci_close_device() flushes rx_wq and tx_wq while holding req_lock. +This causes a circular locking dependency because nci_rx_work() +running on rx_wq can end up taking req_lock too: + + nci_rx_work -> nci_rx_data_packet -> nci_data_exchange_complete + -> __sk_destruct -> rawsock_destruct -> nfc_deactivate_target + -> nci_deactivate_target -> nci_request -> mutex_lock(&ndev->req_lock) + +Move the flush of rx_wq after req_lock has been released. +This should safe (I think) because NCI_UP has already been cleared +and the transport is closed, so the work will see it and return +-ENETDOWN. + +NIPA has been hitting this running the nci selftest with a debug +kernel on roughly 4% of the runs. + +Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation") +Reviewed-by: Ian Ray +Link: https://patch.msgid.link/20260317193334.988609-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 1f33da345bea6..e2ffdb06bf9aa 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -575,8 +575,7 @@ static int nci_close_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->rx_q); + skb_queue_purge(&ndev->tx_q); + +- /* Flush RX and TX wq */ +- flush_workqueue(ndev->rx_wq); ++ /* Flush TX wq, RX wq flush can't be under the lock */ + flush_workqueue(ndev->tx_wq); + + /* Reset device */ +@@ -588,13 +587,13 @@ static int nci_close_device(struct nci_dev *ndev) + msecs_to_jiffies(NCI_RESET_TIMEOUT)); + + /* After this point our queues are empty +- * and no works are scheduled. ++ * rx work may be running but will see that NCI_UP was cleared + */ + ndev->ops->close(ndev); + + clear_bit(NCI_INIT, &ndev->flags); + +- /* Flush cmd wq */ ++ /* Flush cmd and tx wq */ + flush_workqueue(ndev->cmd_wq); + + del_timer_sync(&ndev->cmd_timer); +@@ -604,6 +603,9 @@ static int nci_close_device(struct nci_dev *ndev) + + mutex_unlock(&ndev->req_lock); + ++ /* rx_work may take req_lock via nci_deactivate_target */ ++ flush_workqueue(ndev->rx_wq); ++ + return 0; + } + +-- +2.51.0 + diff --git a/queue-6.6/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch b/queue-6.6/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch new file mode 100644 index 0000000000..a4cd3b2538 --- /dev/null +++ b/queue-6.6/openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch @@ -0,0 +1,50 @@ +From 87db3532548fe05e8be9a9503e596683efb46833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 07:42:41 +0000 +Subject: openvswitch: defer tunnel netdev_put to RCU release + +From: Yang Yang + +[ Upstream commit 6931d21f87bc6d657f145798fad0bf077b82486c ] + +ovs_netdev_tunnel_destroy() may run after NETDEV_UNREGISTER already +detached the device. Dropping the netdev reference in destroy can race +with concurrent readers that still observe vport->dev. + +Do not release vport->dev in ovs_netdev_tunnel_destroy(). Instead, let +vport_netdev_free() drop the reference from the RCU callback, matching +the non-tunnel destroy path and avoiding additional synchronization +under RTNL. + +Fixes: a9020fde67a6 ("openvswitch: Move tunnel destroy function to oppenvswitch module.") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319074241.3405262-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/vport-netdev.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c +index 18376e10aeedc..68d38c12427c1 100644 +--- a/net/openvswitch/vport-netdev.c ++++ b/net/openvswitch/vport-netdev.c +@@ -189,8 +189,6 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) + */ + if (vport->dev->reg_state == NETREG_REGISTERED) + rtnl_delete_link(vport->dev, 0, NULL); +- netdev_put(vport->dev, &vport->dev_tracker); +- vport->dev = NULL; + rtnl_unlock(); + + call_rcu(&vport->rcu, vport_netdev_free); +-- +2.51.0 + diff --git a/queue-6.6/openvswitch-validate-mpls-set-set_masked-payload-len.patch b/queue-6.6/openvswitch-validate-mpls-set-set_masked-payload-len.patch new file mode 100644 index 0000000000..780eb56665 --- /dev/null +++ b/queue-6.6/openvswitch-validate-mpls-set-set_masked-payload-len.patch @@ -0,0 +1,50 @@ +From 2a629cf9389aef37030c9cb666ce88bbb2d12167 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 08:02:27 +0000 +Subject: openvswitch: validate MPLS set/set_masked payload length + +From: Yang Yang + +[ Upstream commit 546b68ac893595877ffbd7751e5c55fd1c43ede6 ] + +validate_set() accepted OVS_KEY_ATTR_MPLS as variable-sized payload for +SET/SET_MASKED actions. In action handling, OVS expects fixed-size +MPLS key data (struct ovs_key_mpls). + +Use the already normalized key_len (masked case included) and reject +non-matching MPLS action key sizes. + +Reject invalid MPLS action payload lengths early. + +Fixes: fbdcdd78da7c ("Change in Openvswitch to support MPLS label depth of 3 in ingress direction") +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Tested-by: Ao Zhou +Co-developed-by: Yuan Tan +Signed-off-by: Yuan Tan +Suggested-by: Xin Liu +Signed-off-by: Yang Yang +Reviewed-by: Ilya Maximets +Link: https://patch.msgid.link/20260319080228.3423307-1-n05ec@lzu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/openvswitch/flow_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c +index 1d9a44d6216af..b31abd5508f55 100644 +--- a/net/openvswitch/flow_netlink.c ++++ b/net/openvswitch/flow_netlink.c +@@ -2939,6 +2939,8 @@ static int validate_set(const struct nlattr *a, + case OVS_KEY_ATTR_MPLS: + if (!eth_p_mpls(eth_type)) + return -EINVAL; ++ if (key_len != sizeof(struct ovs_key_mpls)) ++ return -EINVAL; + break; + + case OVS_KEY_ATTR_SCTP: +-- +2.51.0 + diff --git a/queue-6.6/pinctrl-mediatek-common-fix-probe-failure-for-device.patch b/queue-6.6/pinctrl-mediatek-common-fix-probe-failure-for-device.patch new file mode 100644 index 0000000000..5df64ddf9a --- /dev/null +++ b/queue-6.6/pinctrl-mediatek-common-fix-probe-failure-for-device.patch @@ -0,0 +1,49 @@ +From 2cf628f12bd537d60ff716866fbd99cd23bff8d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2026 11:02:06 +0000 +Subject: pinctrl: mediatek: common: Fix probe failure for devices without EINT + +From: Luca Leonardo Scorcia + +[ Upstream commit 8f9f64c8f90dca07d3b9f1d7ce5d34ccd246c9dd ] + +Some pinctrl devices like mt6397 or mt6392 don't support EINT at all, but +the mtk_eint_init function is always called and returns -ENODEV, which +then bubbles up and causes probe failure. + +To address this only call mtk_eint_init if EINT pins are present. + +Tested on Xiaomi Mi Smart Clock x04g (mt6392). + +Fixes: e46df235b4e6 ("pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit") +Signed-off-by: Luca Leonardo Scorcia +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +index 74b15952b742e..7066fab7621e9 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +@@ -1133,9 +1133,12 @@ int mtk_pctrl_init(struct platform_device *pdev, + goto chip_error; + } + +- ret = mtk_eint_init(pctl, pdev); +- if (ret) +- goto chip_error; ++ /* Only initialize EINT if we have EINT pins */ ++ if (data->eint_hw.ap_num > 0) { ++ ret = mtk_eint_init(pctl, pdev); ++ if (ret) ++ goto chip_error; ++ } + + return 0; + +-- +2.51.0 + diff --git a/queue-6.6/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch b/queue-6.6/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch new file mode 100644 index 0000000000..961153e229 --- /dev/null +++ b/queue-6.6/platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch @@ -0,0 +1,45 @@ +From 25589e5fc6f56857268476d6acf2a3e0e8daace3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Mar 2026 06:01:35 -0700 +Subject: platform/olpc: olpc-xo175-ec: Fix overflow error message to print + inlen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alok Tiwari + +[ Upstream commit 2061f7b042f88d372cca79615f8425f3564c0b40 ] + +The command length check validates inlen (> 5), but the error message +incorrectly printed resp_len. Print inlen so the log reflects the +actual command length. + +Fixes: 0c3d931b3ab9e ("Platform: OLPC: Add XO-1.75 EC driver") +Signed-off-by: Alok Tiwari +Acked-by: Lubomir Rintel +Reviewed-by: Randy Dunlap +Link: https://patch.msgid.link/20260310130138.700687-1-alok.a.tiwari@oracle.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/olpc/olpc-xo175-ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c +index 62ccbcb15c744..efe4cee5acfff 100644 +--- a/drivers/platform/olpc/olpc-xo175-ec.c ++++ b/drivers/platform/olpc/olpc-xo175-ec.c +@@ -482,7 +482,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp, + dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len); + + if (inlen > 5) { +- dev_err(dev, "command len %zd too big!\n", resp_len); ++ dev_err(dev, "command len %zd too big!\n", inlen); + return -EOVERFLOW; + } + +-- +2.51.0 + diff --git a/queue-6.6/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch b/queue-6.6/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch new file mode 100644 index 0000000000..14beeb348a --- /dev/null +++ b/queue-6.6/rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch @@ -0,0 +1,48 @@ +From a5802eddf6e96acf1612d2f9ad33aed88a76dad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Mar 2026 00:02:53 +0100 +Subject: rtnetlink: count IFLA_INFO_SLAVE_KIND in if_nlmsg_size + +From: Sabrina Dubroca + +[ Upstream commit ee00a12593ffb69db4dd1a1c00ecb0253376874a ] + +rtnl_link_get_slave_info_data_size counts IFLA_INFO_SLAVE_DATA, but +rtnl_link_slave_info_fill adds both IFLA_INFO_SLAVE_DATA and +IFLA_INFO_SLAVE_KIND. + +Fixes: ba7d49b1f0f8 ("rtnetlink: provide api for getting and setting slave info") +Reviewed-by: Jiri Pirko +Signed-off-by: Sabrina Dubroca +Link: https://patch.msgid.link/049843b532e23cde7ddba263c0bbe35ba6f0d26d.1773919462.git.sd@queasysnail.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 1613563132035..acb3a8e19743c 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -571,11 +571,14 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev) + goto out; + + ops = master_dev->rtnl_link_ops; +- if (!ops || !ops->get_slave_size) ++ if (!ops) ++ goto out; ++ size += nla_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_SLAVE_KIND */ ++ if (!ops->get_slave_size) + goto out; + /* IFLA_INFO_SLAVE_DATA + nested data */ +- size = nla_total_size(sizeof(struct nlattr)) + +- ops->get_slave_size(master_dev, dev); ++ size += nla_total_size(sizeof(struct nlattr)) + ++ ops->get_slave_size(master_dev, dev); + + out: + rcu_read_unlock(); +-- +2.51.0 + diff --git a/queue-6.6/series b/queue-6.6/series index cd2af8ce46..0718966fba 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -30,3 +30,45 @@ alsa-hda-realtek-add-headset-jack-quirk-for-thinkpad.patch objtool-handle-clang-rsp-musical-chairs.patch usb-core-new-quirk-to-handle-devices-with-zero-confi.patch spi-intel-pci-add-support-for-nova-lake-mobile-spi-f.patch +xfrm-call-xdo_dev_state_delete-during-state-update.patch +xfrm-fix-the-usage-of-skb-sk.patch +esp-fix-skb-leak-with-espintcp-and-async-crypto.patch +af_key-validate-families-in-pfkey_send_migrate.patch +dma-swiotlb-add-kmsan-annotations-to-swiotlb_bounce.patch +can-statistics-add-missing-atomic-access-in-hot-path.patch +bluetooth-l2cap-validate-pdu-length-before-reading-s.patch +bluetooth-sco-fix-use-after-free-in-sco_recv_frame-d.patch +bluetooth-hci_ll-fix-firmware-leak-on-error-path.patch +bluetooth-l2cap-fix-null-ptr-deref-on-l2cap_sock_rea.patch +pinctrl-mediatek-common-fix-probe-failure-for-device.patch +ionic-fix-persistent-mac-address-override-on-pf.patch +nfc-nci-fix-circular-locking-dependency-in-nci_close.patch +net-openvswitch-avoid-releasing-netdev-before-teardo.patch +openvswitch-defer-tunnel-netdev_put-to-rcu-release.patch +openvswitch-validate-mpls-set-set_masked-payload-len.patch +net-smc-fix-double-free-of-smc_spd_priv-when-tee-dup.patch +rtnetlink-count-ifla_info_slave_kind-in-if_nlmsg_siz.patch +platform-olpc-olpc-xo175-ec-fix-overflow-error-messa.patch +ice-use-ice_update_eth_stats-for-representor-stats.patch +ipv6-remove-permanent-routes-from-tb6_gc_hlist-when-.patch +ipv6-don-t-remove-permanent-routes-with-exceptions-f.patch +net-fix-fanout-uaf-in-packet_release-via-netdev_up-r.patch +tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch +tcp-rearrange-tests-in-inet_csk_bind_conflict.patch +tcp-optimize-inet_use_bhash2_on_bind.patch +udp-fix-wildcard-bind-conflict-check-when-using-hash.patch +net-enetc-fix-the-output-issue-of-ethtool-show-ring.patch +dma-mapping-add-missing-inline-for-dma_free_attrs.patch +bluetooth-l2cap-fix-send-le-flow-credits-in-acl-link.patch +bluetooth-remove-3-repeated-macro-definitions.patch +bluetooth-hci_sync-remove-remaining-dependencies-of-.patch +bluetooth-btintel-serialize-btintel_hw_error-with-hc.patch +bluetooth-l2cap-fix-ertm-re-init-and-zero-pdu_len-in.patch +bluetooth-btusb-clamp-sco-altsetting-table-indices.patch +tls-purge-async_hold-in-tls_decrypt_async_wait.patch +netfilter-nfnetlink_log-fix-uninitialized-padding-le.patch +netfilter-ip6t_rt-reject-oversized-addrnr-in-rt_mt6_.patch +netfilter-nf_conntrack_expect-skip-expectations-in-o.patch +netfilter-nf_conntrack_sip-fix-use-of-uninitialized-.patch +netfilter-ctnetlink-use-netlink-policy-range-checks.patch +net-macb-use-the-current-queue-number-for-stats.patch diff --git a/queue-6.6/tcp-optimize-inet_use_bhash2_on_bind.patch b/queue-6.6/tcp-optimize-inet_use_bhash2_on_bind.patch new file mode 100644 index 0000000000..140734cfa6 --- /dev/null +++ b/queue-6.6/tcp-optimize-inet_use_bhash2_on_bind.patch @@ -0,0 +1,46 @@ +From 806fe8865ce9a21a3f42ea47a2f435a31293ff4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 12:42:35 +0000 +Subject: tcp: optimize inet_use_bhash2_on_bind() + +From: Eric Dumazet + +[ Upstream commit ca79d80b0b9f42362a893f06413a9fe91811158a ] + +There is no reason to call ipv6_addr_type(). + +Instead, use highly optimized ipv6_addr_any() and ipv6_addr_v4mapped(). + +Signed-off-by: Eric Dumazet +Reviewed-by: Jason Xing +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250302124237.3913746-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index e7751bfab92bb..2274ac267c41a 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -155,12 +155,10 @@ static bool inet_use_bhash2_on_bind(const struct sock *sk) + { + #if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { +- int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); +- +- if (addr_type == IPV6_ADDR_ANY) ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + return false; + +- if (addr_type != IPV6_ADDR_MAPPED) ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) + return true; + } + #endif +-- +2.51.0 + diff --git a/queue-6.6/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch b/queue-6.6/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch new file mode 100644 index 0000000000..1626ee5890 --- /dev/null +++ b/queue-6.6/tcp-rearrange-tests-in-inet_csk_bind_conflict.patch @@ -0,0 +1,93 @@ +From 1da14ba783a9a225e931884f12f95efe81ea214f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 09:18:28 +0900 +Subject: tcp: Rearrange tests in inet_csk_bind_conflict(). + +From: Kuniyuki Iwashima + +[ Upstream commit 58655bc0ad7ccdd5b53319bcc091cb81b6aee7c3 ] + +The following patch adds code in the !inet_use_bhash2_on_bind(sk) +case in inet_csk_bind_conflict(). + +To avoid adding nest and make the change cleaner, this patch +rearranges tests in inet_csk_bind_conflict(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 40 ++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 21 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 4a53c538dcaa1..e7751bfab92bb 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -240,9 +240,10 @@ static int inet_csk_bind_conflict(const struct sock *sk, + const struct inet_bind2_bucket *tb2, /* may be null */ + bool relax, bool reuseport_ok) + { +- bool reuseport_cb_ok; +- struct sock_reuseport *reuseport_cb; + kuid_t uid = sock_i_uid((struct sock *)sk); ++ struct sock_reuseport *reuseport_cb; ++ bool reuseport_cb_ok; ++ struct sock *sk2; + + rcu_read_lock(); + reuseport_cb = rcu_dereference(sk->sk_reuseport_cb); +@@ -250,32 +251,29 @@ static int inet_csk_bind_conflict(const struct sock *sk, + reuseport_cb_ok = !reuseport_cb || READ_ONCE(reuseport_cb->num_closed_socks); + rcu_read_unlock(); + +- /* +- * Unlike other sk lookup places we do not check ++ /* Conflicts with an existing IPV6_ADDR_ANY (if ipv6) or INADDR_ANY (if ++ * ipv4) should have been checked already. We need to do these two ++ * checks separately because their spinlocks have to be acquired/released ++ * independently of each other, to prevent possible deadlocks ++ */ ++ if (inet_use_bhash2_on_bind(sk)) ++ return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, ++ reuseport_cb_ok, reuseport_ok); ++ ++ /* Unlike other sk lookup places we do not check + * for sk_net here, since _all_ the socks listed + * in tb->owners and tb2->owners list belong + * to the same net - the one this bucket belongs to. + */ ++ sk_for_each_bound(sk2, &tb->owners) { ++ if (!inet_bind_conflict(sk, sk2, uid, relax, reuseport_cb_ok, reuseport_ok)) ++ continue; + +- if (!inet_use_bhash2_on_bind(sk)) { +- struct sock *sk2; +- +- sk_for_each_bound(sk2, &tb->owners) +- if (inet_bind_conflict(sk, sk2, uid, relax, +- reuseport_cb_ok, reuseport_ok) && +- inet_rcv_saddr_equal(sk, sk2, true)) +- return true; +- +- return false; ++ if (inet_rcv_saddr_equal(sk, sk2, true)) ++ return true; + } + +- /* Conflicts with an existing IPV6_ADDR_ANY (if ipv6) or INADDR_ANY (if +- * ipv4) should have been checked already. We need to do these two +- * checks separately because their spinlocks have to be acquired/released +- * independently of each other, to prevent possible deadlocks +- */ +- return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok, +- reuseport_ok); ++ return false; + } + + /* Determine if there is a bind conflict with an existing IPV6_ADDR_ANY (if ipv6) or +-- +2.51.0 + diff --git a/queue-6.6/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch b/queue-6.6/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch new file mode 100644 index 0000000000..e2cbcf50a2 --- /dev/null +++ b/queue-6.6/tcp-use-bhash2-for-v4-mapped-v6-non-wildcard-address.patch @@ -0,0 +1,65 @@ +From 33c9efcfd2f1f2e8f3dcfa00d7d29fb535227b46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 09:18:22 +0900 +Subject: tcp: Use bhash2 for v4-mapped-v6 non-wildcard address. + +From: Kuniyuki Iwashima + +[ Upstream commit 5e07e672412bed473122813ab35d4f7d42fd9635 ] + +While checking port availability in bind() or listen(), we used only +bhash for all v4-mapped-v6 addresses. But there is no good reason not +to use bhash2 for v4-mapped-v6 non-wildcard addresses. + +Let's do it by returning true in inet_use_bhash2_on_bind(). Then, we +also need to add a test in inet_bind2_bucket_match_addr_any() so that +::ffff:X.X.X.X will match with 0.0.0.0. + +Note that sk->sk_rcv_saddr is initialised for v4-mapped-v6 sk in +__inet6_bind(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: e537dd15d0d4 ("udp: Fix wildcard bind conflict check when using hash2") +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 7 +++++-- + net/ipv4/inet_hashtables.c | 3 ++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index bd032ac2376ed..4a53c538dcaa1 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -157,8 +157,11 @@ static bool inet_use_bhash2_on_bind(const struct sock *sk) + if (sk->sk_family == AF_INET6) { + int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); + +- return addr_type != IPV6_ADDR_ANY && +- addr_type != IPV6_ADDR_MAPPED; ++ if (addr_type == IPV6_ADDR_ANY) ++ return false; ++ ++ if (addr_type != IPV6_ADDR_MAPPED) ++ return true; + } + #endif + return sk->sk_rcv_saddr != htonl(INADDR_ANY); +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 7292f70176251..ed253aa1f5d3f 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -845,7 +845,8 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const + return ipv6_addr_any(&tb->v6_rcv_saddr) || + ipv6_addr_v4mapped_any(&tb->v6_rcv_saddr); + +- return false; ++ return ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr) && ++ tb->rcv_saddr == 0; + } + + if (sk->sk_family == AF_INET6) +-- +2.51.0 + diff --git a/queue-6.6/tls-purge-async_hold-in-tls_decrypt_async_wait.patch b/queue-6.6/tls-purge-async_hold-in-tls_decrypt_async_wait.patch new file mode 100644 index 0000000000..0f384b5a9e --- /dev/null +++ b/queue-6.6/tls-purge-async_hold-in-tls_decrypt_async_wait.patch @@ -0,0 +1,66 @@ +From f6c4da8ffbb4a024ab9c04f3fe1c11343b179045 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 08:53:23 -0400 +Subject: tls: Purge async_hold in tls_decrypt_async_wait() + +From: Chuck Lever + +[ Upstream commit 84a8335d8300576f1b377ae24abca1d9f197807f ] + +The async_hold queue pins encrypted input skbs while +the AEAD engine references their scatterlist data. Once +tls_decrypt_async_wait() returns, every AEAD operation +has completed and the engine no longer references those +skbs, so they can be freed unconditionally. + +A subsequent patch adds batch async decryption to +tls_sw_read_sock(), introducing a new call site that +must drain pending AEAD operations and release held +skbs. Move __skb_queue_purge(&ctx->async_hold) into +tls_decrypt_async_wait() so the purge is centralized +and every caller -- recvmsg's drain path, the -EBUSY +fallback in tls_do_decryption(), and the new read_sock +batch path -- releases held skbs on synchronization +without each site managing the purge independently. + +This fixes a leak when tls_strp_msg_hold() fails part-way through, +after having added some cloned skbs to the async_hold +queue. tls_decrypt_sg() will then call tls_decrypt_async_wait() to +process all pending decrypts, and drop back to synchronous mode, but +tls_sw_recvmsg() only flushes the async_hold queue when one record has +been processed in "fully-async" mode, which may not be the case here. + +Signed-off-by: Chuck Lever +Reported-by: Yiming Qian +Fixes: b8a6ff84abbc ("tls: wait for pending async decryptions if tls_strp_msg_hold fails") +Link: https://patch.msgid.link/20260324-tls-read-sock-v5-1-5408befe5774@oracle.com +[pabeni@redhat.com: added leak comment] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tls/tls_sw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 410e39e4b79fd..dc57b31a5fe5c 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -246,6 +246,7 @@ static int tls_decrypt_async_wait(struct tls_sw_context_rx *ctx) + crypto_wait_req(-EINPROGRESS, &ctx->async_wait); + atomic_inc(&ctx->decrypt_pending); + ++ __skb_queue_purge(&ctx->async_hold); + return ctx->async_wait.err; + } + +@@ -2191,7 +2192,6 @@ int tls_sw_recvmsg(struct sock *sk, + + /* Wait for all previously submitted records to be decrypted */ + ret = tls_decrypt_async_wait(ctx); +- __skb_queue_purge(&ctx->async_hold); + + if (ret) { + if (err >= 0 || err == -EINPROGRESS) +-- +2.51.0 + diff --git a/queue-6.6/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch b/queue-6.6/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch new file mode 100644 index 0000000000..d4ec3caa5d --- /dev/null +++ b/queue-6.6/udp-fix-wildcard-bind-conflict-check-when-using-hash.patch @@ -0,0 +1,160 @@ +From fc08db09121ef7350bc55e88fdd957a75caa8232 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Mar 2026 11:18:17 -0700 +Subject: udp: Fix wildcard bind conflict check when using hash2 + +From: Martin KaFai Lau + +[ Upstream commit e537dd15d0d4ad989d56a1021290f0c674dd8b28 ] + +When binding a udp_sock to a local address and port, UDP uses +two hashes (udptable->hash and udptable->hash2) for collision +detection. The current code switches to "hash2" when +hslot->count > 10. + +"hash2" is keyed by local address and local port. +"hash" is keyed by local port only. + +The issue can be shown in the following bind sequence (pseudo code): + +bind(fd1, "[fd00::1]:8888") +bind(fd2, "[fd00::2]:8888") +bind(fd3, "[fd00::3]:8888") +bind(fd4, "[fd00::4]:8888") +bind(fd5, "[fd00::5]:8888") +bind(fd6, "[fd00::6]:8888") +bind(fd7, "[fd00::7]:8888") +bind(fd8, "[fd00::8]:8888") +bind(fd9, "[fd00::9]:8888") +bind(fd10, "[fd00::10]:8888") + +/* Correctly return -EADDRINUSE because "hash" is used + * instead of "hash2". udp_lib_lport_inuse() detects the + * conflict. + */ +bind(fail_fd, "[::]:8888") + +/* After one more socket is bound to "[fd00::11]:8888", + * hslot->count exceeds 10 and "hash2" is used instead. + */ +bind(fd11, "[fd00::11]:8888") +bind(fail_fd, "[::]:8888") /* succeeds unexpectedly */ + +The same issue applies to the IPv4 wildcard address "0.0.0.0" +and the IPv4-mapped wildcard address "::ffff:0.0.0.0". For +example, if there are existing sockets bound to +"192.168.1.[1-11]:8888", then binding "0.0.0.0:8888" or +"[::ffff:0.0.0.0]:8888" can also miss the conflict when +hslot->count > 10. + +TCP inet_csk_get_port() already has the correct check in +inet_use_bhash2_on_bind(). Rename it to +inet_use_hash2_on_bind() and move it to inet_hashtables.h +so udp.c can reuse it in this fix. + +Fixes: 30fff9231fad ("udp: bind() optimisation") +Reported-by: Andrew Onyshchuk +Signed-off-by: Martin KaFai Lau +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260319181817.1901357-1-martin.lau@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/inet_hashtables.h | 14 ++++++++++++++ + net/ipv4/inet_connection_sock.c | 20 +++----------------- + net/ipv4/udp.c | 2 +- + 3 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 3ecfeadbfa069..8eeb3708f20ba 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -278,6 +278,20 @@ inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk, + return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)]; + } + ++static inline bool inet_use_hash2_on_bind(const struct sock *sk) ++{ ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) { ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) ++ return false; ++ ++ if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) ++ return true; ++ } ++#endif ++ return sk->sk_rcv_saddr != htonl(INADDR_ANY); ++} ++ + struct inet_bind_hashbucket * + inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port); + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 2274ac267c41a..218bae94f20e4 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -151,20 +151,6 @@ void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) + } + EXPORT_SYMBOL(inet_sk_get_local_port_range); + +-static bool inet_use_bhash2_on_bind(const struct sock *sk) +-{ +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) { +- if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) +- return false; +- +- if (!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) +- return true; +- } +-#endif +- return sk->sk_rcv_saddr != htonl(INADDR_ANY); +-} +- + static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, + kuid_t sk_uid, bool relax, + bool reuseport_cb_ok, bool reuseport_ok) +@@ -254,7 +240,7 @@ static int inet_csk_bind_conflict(const struct sock *sk, + * checks separately because their spinlocks have to be acquired/released + * independently of each other, to prevent possible deadlocks + */ +- if (inet_use_bhash2_on_bind(sk)) ++ if (inet_use_hash2_on_bind(sk)) + return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, + reuseport_cb_ok, reuseport_ok); + +@@ -371,7 +357,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); +- if (inet_use_bhash2_on_bind(sk)) { ++ if (inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false)) + goto next_port; + } +@@ -556,7 +542,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) + check_bind_conflict = false; + } + +- if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) { ++ if (check_bind_conflict && inet_use_hash2_on_bind(sk)) { + if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true)) + goto fail_unlock; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index dc91699ce0328..f301871fa2b1a 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -287,7 +287,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + } else { + hslot = udp_hashslot(udptable, net, snum); + spin_lock_bh(&hslot->lock); +- if (hslot->count > 10) { ++ if (inet_use_hash2_on_bind(sk) && hslot->count > 10) { + int exist; + unsigned int slot2 = udp_sk(sk)->udp_portaddr_hash ^ snum; + +-- +2.51.0 + diff --git a/queue-6.6/xfrm-call-xdo_dev_state_delete-during-state-update.patch b/queue-6.6/xfrm-call-xdo_dev_state_delete-during-state-update.patch new file mode 100644 index 0000000000..31a96630e2 --- /dev/null +++ b/queue-6.6/xfrm-call-xdo_dev_state_delete-during-state-update.patch @@ -0,0 +1,43 @@ +From 08c0ac92e1e9da6f8661b814494da6f1d36df352 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Feb 2026 00:05:13 +0100 +Subject: xfrm: call xdo_dev_state_delete during state update + +From: Sabrina Dubroca + +[ Upstream commit 7d2fc41f91bc69acb6e01b0fa23cd7d0109a6a23 ] + +When we update an SA, we construct a new state and call +xdo_dev_state_add, but never insert it. The existing state is updated, +then we immediately destroy the new state. Since we haven't added it, +we don't go through the standard state delete code, and we're skipping +removing it from the device (but xdo_dev_state_free will get called +when we destroy the temporary state). + +This is similar to commit c5d4d7d83165 ("xfrm: Fix deletion of +offloaded SAs on failure."). + +Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Simon Horman +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_state.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 81e01cdc7a7d5..ca42c9b8cecc3 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2033,6 +2033,7 @@ int xfrm_state_update(struct xfrm_state *x) + + err = 0; + x->km.state = XFRM_STATE_DEAD; ++ xfrm_dev_state_delete(x); + __xfrm_state_put(x); + } + +-- +2.51.0 + diff --git a/queue-6.6/xfrm-fix-the-usage-of-skb-sk.patch b/queue-6.6/xfrm-fix-the-usage-of-skb-sk.patch new file mode 100644 index 0000000000..de8da914c5 --- /dev/null +++ b/queue-6.6/xfrm-fix-the-usage-of-skb-sk.patch @@ -0,0 +1,135 @@ +From 8bc1c46e7aaef7001ca02e81be82aedb265bcd96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 11:46:03 +0100 +Subject: xfrm: Fix the usage of skb->sk + +From: Steffen Klassert + +[ Upstream commit 1620c88887b16940e00dbe57dd38c74eda9bad9e ] + +xfrm assumed to always have a full socket at skb->sk. +This is not always true, so fix it by converting to a +full socket before it is used. + +Signed-off-by: Steffen Klassert +Reviewed-by: Eric Dumazet +Stable-dep-of: 0c0eef8ccd24 ("esp: fix skb leak with espintcp and async crypto") +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4.c | 2 +- + net/ipv6/esp6.c | 2 +- + net/ipv6/xfrm6_output.c | 4 ++-- + net/xfrm/xfrm_interface_core.c | 2 +- + net/xfrm/xfrm_output.c | 7 ++++--- + net/xfrm/xfrm_policy.c | 2 +- + 6 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 2caf6a2a819b2..85e24dc42f2f3 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -236,7 +236,7 @@ static void esp_output_done(void *data, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 2caaab61b9967..be8e2e5b439ed 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -272,7 +272,7 @@ static void esp_output_done(void *data, int err) + x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) + esp_output_tail_tcp(x, skb); + else +- xfrm_output_resume(skb->sk, skb, err); ++ xfrm_output_resume(skb_to_full_sk(skb), skb, err); + } + } + +diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c +index ad07904642cad..ff183bd76c998 100644 +--- a/net/ipv6/xfrm6_output.c ++++ b/net/ipv6/xfrm6_output.c +@@ -82,14 +82,14 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + toobig = skb->len > mtu && !skb_is_gso(skb); + +- if (toobig && xfrm6_local_dontfrag(skb->sk)) { ++ if (toobig && xfrm6_local_dontfrag(sk)) { + xfrm6_local_rxpmtu(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; + } else if (toobig && xfrm6_noneed_fragment(skb)) { + skb->ignore_df = 1; + goto skip_frag; +- } else if (!skb->ignore_df && toobig && skb->sk) { ++ } else if (!skb->ignore_df && toobig && sk) { + xfrm_local_error(skb, mtu); + kfree_skb(skb); + return -EMSGSIZE; +diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c +index ca6db1e960ce6..44e48c58aa324 100644 +--- a/net/xfrm/xfrm_interface_core.c ++++ b/net/xfrm/xfrm_interface_core.c +@@ -507,7 +507,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + skb_dst_set(skb, dst); + skb->dev = tdev; + +- err = dst_output(xi->net, skb->sk, skb); ++ err = dst_output(xi->net, skb_to_full_sk(skb), skb); + if (net_xmit_eval(err) == 0) { + dev_sw_netstats_tx_add(dev, 1, length); + } else { +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 9277dd4ed541a..a5b5d82bd7550 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -841,7 +841,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) + !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { + skb->protocol = htons(ETH_P_IP); + +- if (skb->sk) ++ if (skb->sk && sk_fullsock(skb->sk)) + xfrm_local_error(skb, mtu); + else + icmp_send(skb, ICMP_DEST_UNREACH, +@@ -877,6 +877,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + { + int mtu, ret = 0; + struct dst_entry *dst = skb_dst(skb); ++ struct sock *sk = skb_to_full_sk(skb); + + if (skb->ignore_df) + goto out; +@@ -891,9 +892,9 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) + skb->dev = dst->dev; + skb->protocol = htons(ETH_P_IPV6); + +- if (xfrm6_local_dontfrag(skb->sk)) ++ if (xfrm6_local_dontfrag(sk)) + ipv6_stub->xfrm6_local_rxpmtu(skb, mtu); +- else if (skb->sk) ++ else if (sk) + xfrm_local_error(skb, mtu); + else + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index b516dd15113ed..45851f822ec4a 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2937,7 +2937,7 @@ static void xfrm_policy_queue_process(struct timer_list *t) + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- dst_output(net, skb->sk, skb); ++ dst_output(net, skb_to_full_sk(skb), skb); + } + + out: +-- +2.51.0 +