From 01e2c38f6b4c7c09669c7a68eeaeadad1a8ce514 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 26 Oct 2024 03:36:46 -0400 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...fix-potential-memory-leak-in-be_xmit.patch | 61 ++++ ...-fix-use-after-free-in-taprio_change.patch | 45 +++ ...ix-potential-memory-leak-in-sun3_825.patch | 37 ++ .../net-usb-usbnet-fix-name-regression.patch | 46 +++ ...x-clock-fix-unbalanced-locking-in-pc.patch | 58 ++++ .../r8169-avoid-unsolicited-interrupts.patch | 49 +++ queue-5.10/series | 8 + ...-dst-lookup-parameters-into-a-struct.patch | 325 ++++++++++++++++++ ...protocols-rules-criteria-when-perfor.patch | 99 ++++++ 9 files changed, 728 insertions(+) create mode 100644 queue-5.10/be2net-fix-potential-memory-leak-in-be_xmit.patch create mode 100644 queue-5.10/net-sched-fix-use-after-free-in-taprio_change.patch create mode 100644 queue-5.10/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch create mode 100644 queue-5.10/net-usb-usbnet-fix-name-regression.patch create mode 100644 queue-5.10/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch create mode 100644 queue-5.10/r8169-avoid-unsolicited-interrupts.patch create mode 100644 queue-5.10/xfrm-extract-dst-lookup-parameters-into-a-struct.patch create mode 100644 queue-5.10/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch diff --git a/queue-5.10/be2net-fix-potential-memory-leak-in-be_xmit.patch b/queue-5.10/be2net-fix-potential-memory-leak-in-be_xmit.patch new file mode 100644 index 00000000000..fe1cd0c1a7f --- /dev/null +++ b/queue-5.10/be2net-fix-potential-memory-leak-in-be_xmit.patch @@ -0,0 +1,61 @@ +From 408f56c6252f4ccfd141304089e12b8c8b6df147 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Oct 2024 22:48:02 +0800 +Subject: be2net: fix potential memory leak in be_xmit() + +From: Wang Hai + +[ Upstream commit e4dd8bfe0f6a23acd305f9b892c00899089bd621 ] + +The be_xmit() returns NETDEV_TX_OK without freeing skb +in case of be_xmit_enqueue() fails, add dev_kfree_skb_any() to fix it. + +Fixes: 760c295e0e8d ("be2net: Support for OS2BMC.") +Signed-off-by: Wang Hai +Reviewed-by: Simon Horman +Reviewed-by: Kalesh AP +Message-ID: <20241015144802.12150-1-wanghai38@huawei.com> +Signed-off-by: Andrew Lunn +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/emulex/benet/be_main.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index edd4dd73b3e32..f018379d13509 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1382,10 +1382,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) + be_get_wrb_params_from_skb(adapter, skb, &wrb_params); + + wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params); +- if (unlikely(!wrb_cnt)) { +- dev_kfree_skb_any(skb); +- goto drop; +- } ++ if (unlikely(!wrb_cnt)) ++ goto drop_skb; + + /* if os2bmc is enabled and if the pkt is destined to bmc, + * enqueue the pkt a 2nd time with mgmt bit set. +@@ -1394,7 +1392,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) + BE_WRB_F_SET(wrb_params.features, OS2BMC, 1); + wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params); + if (unlikely(!wrb_cnt)) +- goto drop; ++ goto drop_skb; + else + skb_get(skb); + } +@@ -1408,6 +1406,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) + be_xmit_flush(adapter, txo); + + return NETDEV_TX_OK; ++drop_skb: ++ dev_kfree_skb_any(skb); + drop: + tx_stats(txo)->tx_drv_drops++; + /* Flush the already enqueued tx requests */ +-- +2.43.0 + diff --git a/queue-5.10/net-sched-fix-use-after-free-in-taprio_change.patch b/queue-5.10/net-sched-fix-use-after-free-in-taprio_change.patch new file mode 100644 index 00000000000..8976f1ab477 --- /dev/null +++ b/queue-5.10/net-sched-fix-use-after-free-in-taprio_change.patch @@ -0,0 +1,45 @@ +From d93ac17726daa144a86efea8000f5c77a0016f85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2024 08:13:38 +0300 +Subject: net: sched: fix use-after-free in taprio_change() + +From: Dmitry Antipov + +[ Upstream commit f504465970aebb2467da548f7c1efbbf36d0f44b ] + +In 'taprio_change()', 'admin' pointer may become dangling due to sched +switch / removal caused by 'advance_sched()', and critical section +protected by 'q->current_entry_lock' is too small to prevent from such +a scenario (which causes use-after-free detected by KASAN). Fix this +by prefer 'rcu_replace_pointer()' over 'rcu_assign_pointer()' to update +'admin' immediately before an attempt to schedule freeing. + +Fixes: a3d43c0d56f1 ("taprio: Add support adding an admin schedule") +Reported-by: syzbot+b65e0af58423fc8a73aa@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b65e0af58423fc8a73aa +Acked-by: Vinicius Costa Gomes +Signed-off-by: Dmitry Antipov +Link: https://patch.msgid.link/20241018051339.418890-1-dmantipov@yandex.ru +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/sch_taprio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c +index 04ed23b5f21b4..16ab7b1480661 100644 +--- a/net/sched/sch_taprio.c ++++ b/net/sched/sch_taprio.c +@@ -1590,7 +1590,8 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, + + taprio_start_sched(sch, start, new_admin); + +- rcu_assign_pointer(q->admin_sched, new_admin); ++ admin = rcu_replace_pointer(q->admin_sched, new_admin, ++ lockdep_rtnl_is_held()); + if (admin) + call_rcu(&admin->rcu, taprio_free_sched_cb); + +-- +2.43.0 + diff --git a/queue-5.10/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch b/queue-5.10/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch new file mode 100644 index 00000000000..3d61ea2eece --- /dev/null +++ b/queue-5.10/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch @@ -0,0 +1,37 @@ +From 14fc2725589e5c094d46152c0111b146b793ebdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Oct 2024 22:41:48 +0800 +Subject: net/sun3_82586: fix potential memory leak in sun3_82586_send_packet() + +From: Wang Hai + +[ Upstream commit 2cb3f56e827abb22c4168ad0c1bbbf401bb2f3b8 ] + +The sun3_82586_send_packet() returns NETDEV_TX_OK without freeing skb +in case of skb->len being too long, add dev_kfree_skb() to fix it. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Hai +Reviewed-by: Simon Horman +Message-ID: <20241015144148.7918-1-wanghai38@huawei.com> +Signed-off-by: Andrew Lunn +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/i825xx/sun3_82586.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c +index 83a6114afbf90..3278e2126dc29 100644 +--- a/drivers/net/ethernet/i825xx/sun3_82586.c ++++ b/drivers/net/ethernet/i825xx/sun3_82586.c +@@ -1015,6 +1015,7 @@ sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) + if(skb->len > XMIT_BUFF_SIZE) + { + printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); ++ dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + +-- +2.43.0 + diff --git a/queue-5.10/net-usb-usbnet-fix-name-regression.patch b/queue-5.10/net-usb-usbnet-fix-name-regression.patch new file mode 100644 index 00000000000..8fda8b81dd9 --- /dev/null +++ b/queue-5.10/net-usb-usbnet-fix-name-regression.patch @@ -0,0 +1,46 @@ +From b3caa93b42448ce3263caf5fec46a327a61aa871 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Oct 2024 09:18:37 +0200 +Subject: net: usb: usbnet: fix name regression + +From: Oliver Neukum + +[ Upstream commit 8a7d12d674ac6f2147c18f36d1e15f1a48060edf ] + +The fix for MAC addresses broke detection of the naming convention +because it gave network devices no random MAC before bind() +was called. This means that the check for the local assignment bit +was always negative as the address was zeroed from allocation, +instead of from overwriting the MAC with a unique hardware address. + +The correct check for whether bind() has altered the MAC is +done with is_zero_ether_addr + +Signed-off-by: Oliver Neukum +Reported-by: Greg Thelen +Diagnosed-by: John Sperbeck +Fixes: bab8eb0dd4cb9 ("usbnet: modern method to get random MAC") +Link: https://patch.msgid.link/20241017071849.389636-1-oneukum@suse.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/usb/usbnet.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 669cd20cfe00a..b3d363ebea26e 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -1717,7 +1717,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + // can rename the link if it knows better. + if ((dev->driver_info->flags & FLAG_ETHER) != 0 && + ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 || +- (net->dev_addr [0] & 0x02) == 0)) ++ /* somebody touched it*/ ++ !is_zero_ether_addr(net->dev_addr))) + strscpy(net->name, "eth%d", sizeof(net->name)); + /* WLAN devices should always be named "wlan%d" */ + if ((dev->driver_info->flags & FLAG_WLAN) != 0) +-- +2.43.0 + diff --git a/queue-5.10/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch b/queue-5.10/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch new file mode 100644 index 00000000000..724ab47a629 --- /dev/null +++ b/queue-5.10/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch @@ -0,0 +1,58 @@ +From e269d6c2a8614f2ec167a69296b2f11770ddc3cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2024 18:07:48 +0800 +Subject: posix-clock: posix-clock: Fix unbalanced locking in + pc_clock_settime() + +From: Jinjie Ruan + +[ Upstream commit 6e62807c7fbb3c758d233018caf94dfea9c65dbd ] + +If get_clock_desc() succeeds, it calls fget() for the clockid's fd, +and get the clk->rwsem read lock, so the error path should release +the lock to make the lock balance and fput the clockid's fd to make +the refcount balance and release the fd related resource. + +However the below commit left the error path locked behind resulting in +unbalanced locking. Check timespec64_valid_strict() before +get_clock_desc() to fix it, because the "ts" is not changed +after that. + +Fixes: d8794ac20a29 ("posix-clock: Fix missing timespec64 check in pc_clock_settime()") +Acked-by: Richard Cochran +Signed-off-by: Jinjie Ruan +Acked-by: Anna-Maria Behnsen +[pabeni@redhat.com: fixed commit message typo] +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + kernel/time/posix-clock.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c +index 8127673bfc45e..05e73d209aa87 100644 +--- a/kernel/time/posix-clock.c ++++ b/kernel/time/posix-clock.c +@@ -290,6 +290,9 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) + struct posix_clock_desc cd; + int err; + ++ if (!timespec64_valid_strict(ts)) ++ return -EINVAL; ++ + err = get_clock_desc(id, &cd); + if (err) + return err; +@@ -299,9 +302,6 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) + goto out; + } + +- if (!timespec64_valid_strict(ts)) +- return -EINVAL; +- + if (cd.clk->ops.clock_settime) + err = cd.clk->ops.clock_settime(cd.clk, ts); + else +-- +2.43.0 + diff --git a/queue-5.10/r8169-avoid-unsolicited-interrupts.patch b/queue-5.10/r8169-avoid-unsolicited-interrupts.patch new file mode 100644 index 00000000000..33738128336 --- /dev/null +++ b/queue-5.10/r8169-avoid-unsolicited-interrupts.patch @@ -0,0 +1,49 @@ +From cdb125f008f95152dcfbd8d1c4296504737e3273 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2024 11:08:16 +0200 +Subject: r8169: avoid unsolicited interrupts + +From: Heiner Kallweit + +[ Upstream commit 10ce0db787004875f4dba068ea952207d1d8abeb ] + +It was reported that after resume from suspend a PCI error is logged +and connectivity is broken. Error message is: +PCI error (cmd = 0x0407, status_errs = 0x0000) +The message seems to be a red herring as none of the error bits is set, +and the PCI command register value also is normal. Exception handling +for a PCI error includes a chip reset what apparently brakes connectivity +here. The interrupt status bit triggering the PCI error handling isn't +actually used on PCIe chip versions, so it's not clear why this bit is +set by the chip. Fix this by ignoring this bit on PCIe chip versions. + +Fixes: 0e4851502f84 ("r8169: merge with version 8.001.00 of Realtek's r8168 driver") +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219388 +Tested-by: Atlas Yu +Signed-off-by: Heiner Kallweit +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/78e2f535-438f-4212-ad94-a77637ac6c9c@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index e9296d63450d8..3aa1dda3406cd 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -4650,7 +4650,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) + if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask)) + return IRQ_NONE; + +- if (unlikely(status & SYSErr)) { ++ /* At least RTL8168fp may unexpectedly set the SYSErr bit */ ++ if (unlikely(status & SYSErr && ++ tp->mac_version <= RTL_GIGA_MAC_VER_06)) { + rtl8169_pcierr_interrupt(tp->dev); + goto out; + } +-- +2.43.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 5a0a320596e..974cf298f49 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -30,3 +30,11 @@ asoc-fsl_sai-enable-fifo-continue-on-error-fcont-bit.patch arm64-force-position-independent-veneers.patch jfs-fix-sanity-check-in-dbmount.patch tracing-consider-the-null-character-when-validating-.patch +xfrm-extract-dst-lookup-parameters-into-a-struct.patch +xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch +net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch +be2net-fix-potential-memory-leak-in-be_xmit.patch +net-usb-usbnet-fix-name-regression.patch +net-sched-fix-use-after-free-in-taprio_change.patch +r8169-avoid-unsolicited-interrupts.patch +posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch diff --git a/queue-5.10/xfrm-extract-dst-lookup-parameters-into-a-struct.patch b/queue-5.10/xfrm-extract-dst-lookup-parameters-into-a-struct.patch new file mode 100644 index 00000000000..46b1be92ec8 --- /dev/null +++ b/queue-5.10/xfrm-extract-dst-lookup-parameters-into-a-struct.patch @@ -0,0 +1,325 @@ +From d3cece7317a8ae6446881914a4fb08a9bbb952a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Sep 2024 17:07:09 -0700 +Subject: xfrm: extract dst lookup parameters into a struct + +From: Eyal Birger + +[ Upstream commit e509996b16728e37d5a909a5c63c1bd64f23b306 ] + +Preparation for adding more fields to dst lookup functions without +changing their signatures. + +Signed-off-by: Eyal Birger +Signed-off-by: Steffen Klassert +Stable-dep-of: b84697210343 ("xfrm: respect ip protocols rules criteria when performing dst lookups") +Signed-off-by: Sasha Levin +--- + include/net/xfrm.h | 26 +++++++++++++------------- + net/ipv4/xfrm4_policy.c | 38 ++++++++++++++++---------------------- + net/ipv6/xfrm6_policy.c | 28 +++++++++++++--------------- + net/xfrm/xfrm_device.c | 11 ++++++++--- + net/xfrm/xfrm_policy.c | 35 +++++++++++++++++++++++------------ + 5 files changed, 73 insertions(+), 65 deletions(-) + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index 6fbaf304648f6..142967e456b18 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -321,20 +321,23 @@ struct xfrm_if_cb { + void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb); + void xfrm_if_unregister_cb(void); + ++struct xfrm_dst_lookup_params { ++ struct net *net; ++ int tos; ++ int oif; ++ xfrm_address_t *saddr; ++ xfrm_address_t *daddr; ++ u32 mark; ++}; ++ + struct net_device; + struct xfrm_type; + struct xfrm_dst; + struct xfrm_policy_afinfo { + struct dst_ops *dst_ops; +- struct dst_entry *(*dst_lookup)(struct net *net, +- int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- u32 mark); +- int (*get_saddr)(struct net *net, int oif, +- xfrm_address_t *saddr, +- xfrm_address_t *daddr, +- u32 mark); ++ struct dst_entry *(*dst_lookup)(const struct xfrm_dst_lookup_params *params); ++ int (*get_saddr)(xfrm_address_t *saddr, ++ const struct xfrm_dst_lookup_params *params); + int (*fill_dst)(struct xfrm_dst *xdst, + struct net_device *dev, + const struct flowi *fl); +@@ -1658,10 +1661,7 @@ static inline int xfrm_user_policy(struct sock *sk, int optname, + } + #endif + +-struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- int family, u32 mark); ++struct dst_entry *__xfrm_dst_lookup(int family, const struct xfrm_dst_lookup_params *params); + + struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp); + +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index 4548a91acdc89..d1c2619e03740 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -17,47 +17,41 @@ + #include + #include + +-static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, +- int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- u32 mark) ++static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4, ++ const struct xfrm_dst_lookup_params *params) + { + struct rtable *rt; + + memset(fl4, 0, sizeof(*fl4)); +- fl4->daddr = daddr->a4; +- fl4->flowi4_tos = tos; +- fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif); +- fl4->flowi4_mark = mark; +- if (saddr) +- fl4->saddr = saddr->a4; +- +- rt = __ip_route_output_key(net, fl4); ++ fl4->daddr = params->daddr->a4; ++ fl4->flowi4_tos = params->tos; ++ fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(params->net, ++ params->oif); ++ fl4->flowi4_mark = params->mark; ++ if (params->saddr) ++ fl4->saddr = params->saddr->a4; ++ ++ rt = __ip_route_output_key(params->net, fl4); + if (!IS_ERR(rt)) + return &rt->dst; + + return ERR_CAST(rt); + } + +-static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- u32 mark) ++static struct dst_entry *xfrm4_dst_lookup(const struct xfrm_dst_lookup_params *params) + { + struct flowi4 fl4; + +- return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark); ++ return __xfrm4_dst_lookup(&fl4, params); + } + +-static int xfrm4_get_saddr(struct net *net, int oif, +- xfrm_address_t *saddr, xfrm_address_t *daddr, +- u32 mark) ++static int xfrm4_get_saddr(xfrm_address_t *saddr, ++ const struct xfrm_dst_lookup_params *params) + { + struct dst_entry *dst; + struct flowi4 fl4; + +- dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark); ++ dst = __xfrm4_dst_lookup(&fl4, params); + if (IS_ERR(dst)) + return -EHOSTUNREACH; + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 492b9692c0dc0..40183fdf7da0e 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -23,23 +23,21 @@ + #include + #include + +-static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- u32 mark) ++static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *params) + { + struct flowi6 fl6; + struct dst_entry *dst; + int err; + + memset(&fl6, 0, sizeof(fl6)); +- fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif); +- fl6.flowi6_mark = mark; +- memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr)); +- if (saddr) +- memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr)); ++ fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(params->net, ++ params->oif); ++ fl6.flowi6_mark = params->mark; ++ memcpy(&fl6.daddr, params->daddr, sizeof(fl6.daddr)); ++ if (params->saddr) ++ memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr)); + +- dst = ip6_route_output(net, NULL, &fl6); ++ dst = ip6_route_output(params->net, NULL, &fl6); + + err = dst->error; + if (dst->error) { +@@ -50,15 +48,14 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif, + return dst; + } + +-static int xfrm6_get_saddr(struct net *net, int oif, +- xfrm_address_t *saddr, xfrm_address_t *daddr, +- u32 mark) ++static int xfrm6_get_saddr(xfrm_address_t *saddr, ++ const struct xfrm_dst_lookup_params *params) + { + struct dst_entry *dst; + struct net_device *dev; + struct inet6_dev *idev; + +- dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark); ++ dst = xfrm6_dst_lookup(params); + if (IS_ERR(dst)) + return -EHOSTUNREACH; + +@@ -68,7 +65,8 @@ static int xfrm6_get_saddr(struct net *net, int oif, + return -EHOSTUNREACH; + } + dev = idev->dev; +- ipv6_dev_get_saddr(dev_net(dev), dev, &daddr->in6, 0, &saddr->in6); ++ ipv6_dev_get_saddr(dev_net(dev), dev, ¶ms->daddr->in6, 0, ++ &saddr->in6); + dst_release(dst); + return 0; + } +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index 8b8e957a69c36..4d13f7a372ab6 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -241,6 +241,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + + dev = dev_get_by_index(net, xuo->ifindex); + if (!dev) { ++ struct xfrm_dst_lookup_params params; ++ + if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { + saddr = &x->props.saddr; + daddr = &x->id.daddr; +@@ -249,9 +251,12 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + daddr = &x->props.saddr; + } + +- dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, +- x->props.family, +- xfrm_smark_get(0, x)); ++ memset(¶ms, 0, sizeof(params)); ++ params.net = net; ++ params.saddr = saddr; ++ params.daddr = daddr; ++ params.mark = xfrm_smark_get(0, x); ++ dst = __xfrm_dst_lookup(x->props.family, ¶ms); + if (IS_ERR(dst)) + return 0; + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 39910d4eff62b..a7f8da5241ae5 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -251,10 +251,8 @@ static const struct xfrm_if_cb *xfrm_if_get_cb(void) + return rcu_dereference(xfrm_if_cb); + } + +-struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif, +- const xfrm_address_t *saddr, +- const xfrm_address_t *daddr, +- int family, u32 mark) ++struct dst_entry *__xfrm_dst_lookup(int family, ++ const struct xfrm_dst_lookup_params *params) + { + const struct xfrm_policy_afinfo *afinfo; + struct dst_entry *dst; +@@ -263,7 +261,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif, + if (unlikely(afinfo == NULL)) + return ERR_PTR(-EAFNOSUPPORT); + +- dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark); ++ dst = afinfo->dst_lookup(params); + + rcu_read_unlock(); + +@@ -277,6 +275,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, + xfrm_address_t *prev_daddr, + int family, u32 mark) + { ++ struct xfrm_dst_lookup_params params; + struct net *net = xs_net(x); + xfrm_address_t *saddr = &x->props.saddr; + xfrm_address_t *daddr = &x->id.daddr; +@@ -291,7 +290,14 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, + daddr = x->coaddr; + } + +- dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark); ++ params.net = net; ++ params.saddr = saddr; ++ params.daddr = daddr; ++ params.tos = tos; ++ params.oif = oif; ++ params.mark = mark; ++ ++ dst = __xfrm_dst_lookup(family, ¶ms); + + if (!IS_ERR(dst)) { + if (prev_saddr != saddr) +@@ -2344,15 +2350,15 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) + } + + static int +-xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local, +- xfrm_address_t *remote, unsigned short family, u32 mark) ++xfrm_get_saddr(unsigned short family, xfrm_address_t *saddr, ++ const struct xfrm_dst_lookup_params *params) + { + int err; + const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); + + if (unlikely(afinfo == NULL)) + return -EINVAL; +- err = afinfo->get_saddr(net, oif, local, remote, mark); ++ err = afinfo->get_saddr(saddr, params); + rcu_read_unlock(); + return err; + } +@@ -2381,9 +2387,14 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, + remote = &tmpl->id.daddr; + local = &tmpl->saddr; + if (xfrm_addr_any(local, tmpl->encap_family)) { +- error = xfrm_get_saddr(net, fl->flowi_oif, +- &tmp, remote, +- tmpl->encap_family, 0); ++ struct xfrm_dst_lookup_params params; ++ ++ memset(¶ms, 0, sizeof(params)); ++ params.net = net; ++ params.oif = fl->flowi_oif; ++ params.daddr = remote; ++ error = xfrm_get_saddr(tmpl->encap_family, &tmp, ++ ¶ms); + if (error) + goto fail; + local = &tmp; +-- +2.43.0 + diff --git a/queue-5.10/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch b/queue-5.10/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch new file mode 100644 index 00000000000..0ebd1a48d1e --- /dev/null +++ b/queue-5.10/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch @@ -0,0 +1,99 @@ +From 5faadc7886a4de0de7f8fe278160d9f4c83cd8a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Sep 2024 17:07:10 -0700 +Subject: xfrm: respect ip protocols rules criteria when performing dst lookups + +From: Eyal Birger + +[ Upstream commit b8469721034300bbb6dec5b4bf32492c95e16a0c ] + +The series in the "fixes" tag added the ability to consider L4 attributes +in routing rules. + +The dst lookup on the outer packet of encapsulated traffic in the xfrm +code was not adapted to this change, thus routing behavior that relies +on L4 information is not respected. + +Pass the ip protocol information when performing dst lookups. + +Fixes: a25724b05af0 ("Merge branch 'fib_rules-support-sport-dport-and-proto-match'") +Signed-off-by: Eyal Birger +Tested-by: Antony Antony +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + include/net/xfrm.h | 2 ++ + net/ipv4/xfrm4_policy.c | 2 ++ + net/ipv6/xfrm6_policy.c | 3 +++ + net/xfrm/xfrm_policy.c | 15 +++++++++++++++ + 4 files changed, 22 insertions(+) + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index 142967e456b18..798df30c2d253 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -328,6 +328,8 @@ struct xfrm_dst_lookup_params { + xfrm_address_t *saddr; + xfrm_address_t *daddr; + u32 mark; ++ __u8 ipproto; ++ union flowi_uli uli; + }; + + struct net_device; +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index d1c2619e03740..5d8e38f4ecc07 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -30,6 +30,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4, + fl4->flowi4_mark = params->mark; + if (params->saddr) + fl4->saddr = params->saddr->a4; ++ fl4->flowi4_proto = params->ipproto; ++ fl4->uli = params->uli; + + rt = __ip_route_output_key(params->net, fl4); + if (!IS_ERR(rt)) +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 40183fdf7da0e..f5ef5e4c88df1 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -37,6 +37,9 @@ static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *p + if (params->saddr) + memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr)); + ++ fl6.flowi4_proto = params->ipproto; ++ fl6.uli = params->uli; ++ + dst = ip6_route_output(params->net, NULL, &fl6); + + err = dst->error; +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index a7f8da5241ae5..a1a662a55c2ae 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -296,6 +296,21 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, + params.tos = tos; + params.oif = oif; + params.mark = mark; ++ params.ipproto = x->id.proto; ++ if (x->encap) { ++ switch (x->encap->encap_type) { ++ case UDP_ENCAP_ESPINUDP: ++ params.ipproto = IPPROTO_UDP; ++ params.uli.ports.sport = x->encap->encap_sport; ++ params.uli.ports.dport = x->encap->encap_dport; ++ break; ++ case TCP_ENCAP_ESPINTCP: ++ params.ipproto = IPPROTO_TCP; ++ params.uli.ports.sport = x->encap->encap_sport; ++ params.uli.ports.dport = x->encap->encap_dport; ++ break; ++ } ++ } + + dst = __xfrm_dst_lookup(family, ¶ms); + +-- +2.43.0 + -- 2.47.2