summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-01-22 20:13:25 -0800
committerJakub Kicinski <kuba@kernel.org>2026-01-29 17:28:54 -0800
commita010fe8d869635fd15c1d5768ba6a2f48795fa36 (patch)
treec6bd6ce8580482b8cac589d77df6c6d7f9696894 /net
parent7227e984c36b6a95a23f079d01ec5224a5b0e796 (diff)
parent1cac38910ecb881b09f61f57545a771bbe57ba68 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.19-rc8). No adjacent changes, conflicts: drivers/net/ethernet/spacemit/k1_emac.c 2c84959167d64 ("net: spacemit: Check for netif_carrier_ok() in emac_stats_update()") f66086798f91f ("net: spacemit: Remove broken flow control support") https://lore.kernel.org/aXjAqZA3iEWD_DGM@sirena.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/core/filter.c2
-rw-r--r--net/ipv4/tcp_offload.c3
-rw-r--r--net/ipv4/udp_offload.c3
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/tcpv6_offload.c3
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mptcp/pm_kernel.c16
-rw-r--r--net/mptcp/protocol.c13
-rw-r--r--net/nfc/core.c27
-rw-r--r--net/nfc/llcp_commands.c17
-rw-r--r--net/nfc/llcp_core.c4
-rw-r--r--net/nfc/nci/core.c4
13 files changed, 83 insertions, 23 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e355a15bf5ab..1405f1061a54 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -274,7 +274,7 @@ static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)
int ret;
net = dev_net(skb->dev);
-#ifdef HAVE_JUMP_LABEL
+#ifdef CONFIG_JUMP_LABEL
if (!static_key_false(&nf_hooks_needed[NFPROTO_BRIDGE][NF_BR_PRE_ROUTING]))
goto frame_finish;
#endif
diff --git a/net/core/filter.c b/net/core/filter.c
index 616e0520a0bb..bcd73d9bd764 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3353,6 +3353,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
shinfo->gso_type &= ~SKB_GSO_TCPV4;
shinfo->gso_type |= SKB_GSO_TCPV6;
}
+ shinfo->gso_type |= SKB_GSO_DODGY;
}
bpf_skb_change_protocol(skb, ETH_P_IPV6);
@@ -3383,6 +3384,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
shinfo->gso_type &= ~SKB_GSO_TCPV6;
shinfo->gso_type |= SKB_GSO_TCPV4;
}
+ shinfo->gso_type |= SKB_GSO_DODGY;
}
bpf_skb_change_protocol(skb, ETH_P_IP);
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index fdda18b1abda..942a948f1a31 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -107,7 +107,8 @@ static struct sk_buff *tcp4_gso_segment(struct sk_buff *skb,
if (skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) {
struct tcphdr *th = tcp_hdr(skb);
- if (skb_pagelen(skb) - th->doff * 4 == skb_shinfo(skb)->gso_size)
+ if ((skb_pagelen(skb) - th->doff * 4 == skb_shinfo(skb)->gso_size) &&
+ !(skb_shinfo(skb)->gso_type & SKB_GSO_DODGY))
return __tcp4_gso_segment_list(skb, features);
skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 89e0b48b60ae..6b1654c1ad4a 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -514,7 +514,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) {
/* Detect modified geometry and pass those to skb_segment. */
- if (skb_pagelen(gso_skb) - sizeof(*uh) == skb_shinfo(gso_skb)->gso_size)
+ if ((skb_pagelen(gso_skb) - sizeof(*uh) == skb_shinfo(gso_skb)->gso_size) &&
+ !(skb_shinfo(gso_skb)->gso_type & SKB_GSO_DODGY))
return __udp_gso_segment_list(gso_skb, features, is_ipv6);
ret = __skb_linearize(gso_skb);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index c72270582d9c..1a25ecb92695 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -966,7 +966,9 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb)
fl6.daddr = ipv6_hdr(skb)->saddr;
if (saddr)
fl6.saddr = *saddr;
- fl6.flowi6_oif = icmp6_iif(skb);
+ fl6.flowi6_oif = ipv6_addr_loopback(&fl6.daddr) ?
+ skb->dev->ifindex :
+ icmp6_iif(skb);
fl6.fl6_icmp_type = type;
fl6.flowi6_mark = mark;
fl6.flowi6_uid = sock_net_uid(net, NULL);
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
index 46fa2069d321..f2a659cd6183 100644
--- a/net/ipv6/tcpv6_offload.c
+++ b/net/ipv6/tcpv6_offload.c
@@ -168,7 +168,8 @@ static struct sk_buff *tcp6_gso_segment(struct sk_buff *skb,
if (skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST) {
struct tcphdr *th = tcp_hdr(skb);
- if (skb_pagelen(skb) - th->doff * 4 == skb_shinfo(skb)->gso_size)
+ if ((skb_pagelen(skb) - th->doff * 4 == skb_shinfo(skb)->gso_size) &&
+ !(skb_shinfo(skb)->gso_type & SKB_GSO_DODGY))
return __tcp6_gso_segment_list(skb, features);
skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 82a08f49f498..94ebffbdf394 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -8,7 +8,7 @@
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2025 Intel Corporation
+ * Copyright (C) 2018 - 2026 Intel Corporation
*/
#include <linux/delay.h>
@@ -6190,8 +6190,10 @@ ieee80211_parse_adv_t2l(struct ieee80211_sub_if_data *sdata,
return -EINVAL;
}
- link_map_presence = *pos;
- pos++;
+ if (!(control & IEEE80211_TTLM_CONTROL_DEF_LINK_MAP)) {
+ link_map_presence = *pos;
+ pos++;
+ }
if (control & IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT) {
ttlm_info->switch_time = get_unaligned_le16(pos);
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index 57570a44e418..b26675054b0d 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -1294,16 +1294,26 @@ static void __reset_counters(struct pm_nl_pernet *pernet)
int mptcp_pm_nl_flush_addrs_doit(struct sk_buff *skb, struct genl_info *info)
{
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
- LIST_HEAD(free_list);
+ struct list_head free_list;
spin_lock_bh(&pernet->lock);
- list_splice_init(&pernet->endp_list, &free_list);
+ free_list = pernet->endp_list;
+ INIT_LIST_HEAD_RCU(&pernet->endp_list);
__reset_counters(pernet);
pernet->next_id = 1;
bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
spin_unlock_bh(&pernet->lock);
- mptcp_nl_flush_addrs_list(sock_net(skb->sk), &free_list);
+
+ if (free_list.next == &pernet->endp_list)
+ return 0;
+
synchronize_rcu();
+
+ /* Adjust the pointers to free_list instead of pernet->endp_list */
+ free_list.prev->next = &free_list;
+ free_list.next->prev = &free_list;
+
+ mptcp_nl_flush_addrs_list(sock_net(skb->sk), &free_list);
__flush_addrs(&free_list);
return 0;
}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index f505b780f713..8d3233667418 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -821,11 +821,8 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
{
- int err = sock_error(ssk);
int ssk_state;
-
- if (!err)
- return false;
+ int err;
/* only propagate errors on fallen-back sockets or
* on MPC connect
@@ -833,6 +830,10 @@ static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk)))
return false;
+ err = sock_error(ssk);
+ if (!err)
+ return false;
+
/* We need to propagate only transition to CLOSE state.
* Orphaned socket will see such state change via
* subflow_sched_work_if_closed() and that path will properly
@@ -2598,8 +2599,8 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
struct mptcp_sock *msk = mptcp_sk(sk);
struct sk_buff *skb;
- /* The first subflow can already be closed and still in the list */
- if (subflow->close_event_done)
+ /* The first subflow can already be closed or disconnected */
+ if (subflow->close_event_done || READ_ONCE(subflow->local_id) < 0)
return;
subflow->close_event_done = true;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 82f023f37754..f50e5bab35d8 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -1147,14 +1147,14 @@ int nfc_register_device(struct nfc_dev *dev)
EXPORT_SYMBOL(nfc_register_device);
/**
- * nfc_unregister_device - unregister a nfc device in the nfc subsystem
+ * nfc_unregister_rfkill - unregister a nfc device in the rfkill subsystem
*
* @dev: The nfc device to unregister
*/
-void nfc_unregister_device(struct nfc_dev *dev)
+void nfc_unregister_rfkill(struct nfc_dev *dev)
{
- int rc;
struct rfkill *rfk = NULL;
+ int rc;
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
@@ -1175,7 +1175,16 @@ void nfc_unregister_device(struct nfc_dev *dev)
rfkill_unregister(rfk);
rfkill_destroy(rfk);
}
+}
+EXPORT_SYMBOL(nfc_unregister_rfkill);
+/**
+ * nfc_remove_device - remove a nfc device in the nfc subsystem
+ *
+ * @dev: The nfc device to remove
+ */
+void nfc_remove_device(struct nfc_dev *dev)
+{
if (dev->ops->check_presence) {
timer_delete_sync(&dev->check_pres_timer);
cancel_work_sync(&dev->check_pres_work);
@@ -1188,6 +1197,18 @@ void nfc_unregister_device(struct nfc_dev *dev)
device_del(&dev->dev);
mutex_unlock(&nfc_devlist_mutex);
}
+EXPORT_SYMBOL(nfc_remove_device);
+
+/**
+ * nfc_unregister_device - unregister a nfc device in the nfc subsystem
+ *
+ * @dev: The nfc device to unregister
+ */
+void nfc_unregister_device(struct nfc_dev *dev)
+{
+ nfc_unregister_rfkill(dev);
+ nfc_remove_device(dev);
+}
EXPORT_SYMBOL(nfc_unregister_device);
static int __init nfc_init(void)
diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index e2680a3bef79..b652323bc2c1 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -778,8 +778,23 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
if (likely(frag_len > 0))
skb_put_data(pdu, msg_ptr, frag_len);
+ spin_lock(&local->tx_queue.lock);
+
+ if (list_empty(&local->list)) {
+ spin_unlock(&local->tx_queue.lock);
+
+ kfree_skb(pdu);
+
+ len -= remaining_len;
+ if (len == 0)
+ len = -ENXIO;
+ break;
+ }
+
/* No need to check for the peer RW for UI frames */
- skb_queue_tail(&local->tx_queue, pdu);
+ __skb_queue_tail(&local->tx_queue, pdu);
+
+ spin_unlock(&local->tx_queue.lock);
remaining_len -= frag_len;
msg_ptr += frag_len;
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index beeb3b4d28ca..444a3774c8e8 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -316,7 +316,9 @@ static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev)
spin_lock(&llcp_devices_lock);
list_for_each_entry_safe(local, tmp, &llcp_devices, list)
if (local->dev == dev) {
- list_del(&local->list);
+ spin_lock(&local->tx_queue.lock);
+ list_del_init(&local->list);
+ spin_unlock(&local->tx_queue.lock);
spin_unlock(&llcp_devices_lock);
return local;
}
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index fc921cd2cdff..e419e020a70a 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -1303,6 +1303,8 @@ void nci_unregister_device(struct nci_dev *ndev)
{
struct nci_conn_info *conn_info, *n;
+ nfc_unregister_rfkill(ndev->nfc_dev);
+
/* This set_bit is not protected with specialized barrier,
* However, it is fine because the mutex_lock(&ndev->req_lock);
* in nci_close_device() will help to emit one.
@@ -1320,7 +1322,7 @@ void nci_unregister_device(struct nci_dev *ndev)
/* conn_info is allocated with devm_kzalloc */
}
- nfc_unregister_device(ndev->nfc_dev);
+ nfc_remove_device(ndev->nfc_dev);
}
EXPORT_SYMBOL(nci_unregister_device);