From: Greg Kroah-Hartman Date: Tue, 16 Jun 2026 07:01:03 +0000 (+0530) Subject: 6.1-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=159458ead0b5ea74b8d2b4e7279e2cfe6ec55071;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: batman-adv-stop-tp_meter-sessions-during-mesh-teardown.patch batman-adv-tp_meter-fix-tp_num-leak-on-kmalloc-failure.patch blk-cgroup-fix-null-deref-caused-by-blkg_policy_data-being-installed-before-init.patch ipvs-skip-ipv6-extension-headers-for-csum-checks.patch --- diff --git a/queue-6.1/batman-adv-stop-tp_meter-sessions-during-mesh-teardown.patch b/queue-6.1/batman-adv-stop-tp_meter-sessions-during-mesh-teardown.patch new file mode 100644 index 0000000000..827083123c --- /dev/null +++ b/queue-6.1/batman-adv-stop-tp_meter-sessions-during-mesh-teardown.patch @@ -0,0 +1,235 @@ +From 3d3cf6a7314aca4df0a6dde28ce784a2a30d0166 Mon Sep 17 00:00:00 2001 +From: Jiexun Wang +Date: Mon, 27 Apr 2026 14:43:34 +0800 +Subject: batman-adv: stop tp_meter sessions during mesh teardown + +From: Jiexun Wang + +commit 3d3cf6a7314aca4df0a6dde28ce784a2a30d0166 upstream. + +TP meter sessions remain linked on bat_priv->tp_list after the netlink +request has already finished. When the mesh interface is removed, +batadv_mesh_free() currently tears down the mesh without first draining +these sessions. + +A running sender thread or a late incoming tp_meter packet can then keep +processing against a mesh instance which is already shutting down. +Synchronize tp_meter with the mesh lifetime by stopping all active +sessions from batadv_mesh_free() and waiting for sender threads to exit +before teardown continues. + +Fixes: 33a3bb4a3345 ("batman-adv: throughput meter implementation") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Co-developed-by: Luxing Yin +Signed-off-by: Luxing Yin +Signed-off-by: Jiexun Wang +Signed-off-by: Ren Wei +Signed-off-by: Sven Eckelmann +[ Context ] +Signed-off-by: Sven Eckelmann +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/main.c | 1 + net/batman-adv/tp_meter.c | 94 +++++++++++++++++++++++++++++++++++++--------- + net/batman-adv/tp_meter.h | 1 + net/batman-adv/types.h | 4 + + 4 files changed, 82 insertions(+), 18 deletions(-) + +--- a/net/batman-adv/main.c ++++ b/net/batman-adv/main.c +@@ -262,6 +262,7 @@ void batadv_mesh_free(struct net_device + atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); + + batadv_purge_outstanding_packets(bat_priv, NULL); ++ batadv_tp_stop_all(bat_priv); + + batadv_gw_node_free(bat_priv); + +--- a/net/batman-adv/tp_meter.c ++++ b/net/batman-adv/tp_meter.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -365,23 +366,38 @@ static void batadv_tp_vars_put(struct ba + } + + /** +- * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer +- * @bat_priv: the bat priv with all the soft interface information +- * @tp_vars: the private data of the current TP meter session to cleanup ++ * batadv_tp_list_detach() - remove tp session from mesh session list once ++ * @tp_vars: the private data of the current TP meter session + */ +-static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv, +- struct batadv_tp_vars *tp_vars) ++static void batadv_tp_list_detach(struct batadv_tp_vars *tp_vars) + { +- cancel_delayed_work(&tp_vars->finish_work); ++ bool detached = false; + + spin_lock_bh(&tp_vars->bat_priv->tp_list_lock); +- hlist_del_rcu(&tp_vars->list); ++ if (!hlist_unhashed(&tp_vars->list)) { ++ hlist_del_init_rcu(&tp_vars->list); ++ detached = true; ++ } + spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock); + ++ if (!detached) ++ return; ++ ++ atomic_dec(&tp_vars->bat_priv->tp_num); ++ + /* drop list reference */ + batadv_tp_vars_put(tp_vars); ++} + +- atomic_dec(&tp_vars->bat_priv->tp_num); ++/** ++ * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer ++ * @tp_vars: the private data of the current TP meter session to cleanup ++ */ ++static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars) ++{ ++ cancel_delayed_work_sync(&tp_vars->finish_work); ++ ++ batadv_tp_list_detach(tp_vars); + + /* kill the timer and remove its reference */ + timer_shutdown_sync(&tp_vars->timer); +@@ -883,7 +899,8 @@ out: + batadv_orig_node_put(orig_node); + + batadv_tp_sender_end(bat_priv, tp_vars); +- batadv_tp_sender_cleanup(bat_priv, tp_vars); ++ batadv_tp_sender_cleanup(tp_vars); ++ complete(&tp_vars->finished); + + batadv_tp_vars_put(tp_vars); + +@@ -915,7 +932,8 @@ static void batadv_tp_start_kthread(stru + batadv_tp_vars_put(tp_vars); + + /* cleanup of failed tp meter variables */ +- batadv_tp_sender_cleanup(bat_priv, tp_vars); ++ batadv_tp_sender_cleanup(tp_vars); ++ complete(&tp_vars->finished); + return; + } + +@@ -1021,6 +1039,7 @@ void batadv_tp_start(struct batadv_priv + tp_vars->start_time = jiffies; + + init_waitqueue_head(&tp_vars->more_bytes); ++ init_completion(&tp_vars->finished); + + spin_lock_init(&tp_vars->unacked_lock); + INIT_LIST_HEAD(&tp_vars->unacked_list); +@@ -1127,14 +1146,7 @@ static void batadv_tp_receiver_shutdown( + "Shutting down for inactivity (more than %dms) from %pM\n", + BATADV_TP_RECV_TIMEOUT, tp_vars->other_end); + +- spin_lock_bh(&tp_vars->bat_priv->tp_list_lock); +- hlist_del_rcu(&tp_vars->list); +- spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock); +- +- /* drop list reference */ +- batadv_tp_vars_put(tp_vars); +- +- atomic_dec(&bat_priv->tp_num); ++ batadv_tp_list_detach(tp_vars); + + spin_lock_bh(&tp_vars->unacked_lock); + list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { +@@ -1498,6 +1510,52 @@ out: + } + + /** ++ * batadv_tp_stop_all() - stop all currently running tp meter sessions ++ * @bat_priv: the bat priv with all the mesh interface information ++ */ ++void batadv_tp_stop_all(struct batadv_priv *bat_priv) ++{ ++ struct batadv_tp_vars *tp_vars[BATADV_TP_MAX_NUM]; ++ struct batadv_tp_vars *tp_var; ++ size_t count = 0; ++ size_t i; ++ ++ spin_lock_bh(&bat_priv->tp_list_lock); ++ hlist_for_each_entry(tp_var, &bat_priv->tp_list, list) { ++ if (WARN_ON_ONCE(count >= BATADV_TP_MAX_NUM)) ++ break; ++ ++ if (!kref_get_unless_zero(&tp_var->refcount)) ++ continue; ++ ++ tp_vars[count++] = tp_var; ++ } ++ spin_unlock_bh(&bat_priv->tp_list_lock); ++ ++ for (i = 0; i < count; i++) { ++ tp_var = tp_vars[i]; ++ ++ switch (tp_var->role) { ++ case BATADV_TP_SENDER: ++ batadv_tp_sender_shutdown(tp_var, ++ BATADV_TP_REASON_CANCEL); ++ wake_up(&tp_var->more_bytes); ++ wait_for_completion(&tp_var->finished); ++ break; ++ case BATADV_TP_RECEIVER: ++ batadv_tp_list_detach(tp_var); ++ if (timer_shutdown_sync(&tp_var->timer)) ++ batadv_tp_vars_put(tp_var); ++ break; ++ } ++ ++ batadv_tp_vars_put(tp_var); ++ } ++ ++ synchronize_net(); ++} ++ ++/** + * batadv_tp_meter_init() - initialize global tp_meter structures + */ + void __init batadv_tp_meter_init(void) +--- a/net/batman-adv/tp_meter.h ++++ b/net/batman-adv/tp_meter.h +@@ -17,6 +17,7 @@ void batadv_tp_start(struct batadv_priv + u32 test_length, u32 *cookie); + void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst, + u8 return_value); ++void batadv_tp_stop_all(struct batadv_priv *bat_priv); + void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb); + + #endif /* _NET_BATMAN_ADV_TP_METER_H_ */ +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1405,6 +1406,9 @@ struct batadv_tp_vars { + /** @finish_work: work item for the finishing procedure */ + struct delayed_work finish_work; + ++ /** @finished: completion signaled when a sender thread exits */ ++ struct completion finished; ++ + /** @test_length: test length in milliseconds */ + u32 test_length; + diff --git a/queue-6.1/batman-adv-tp_meter-fix-tp_num-leak-on-kmalloc-failure.patch b/queue-6.1/batman-adv-tp_meter-fix-tp_num-leak-on-kmalloc-failure.patch new file mode 100644 index 0000000000..b8d94aec60 --- /dev/null +++ b/queue-6.1/batman-adv-tp_meter-fix-tp_num-leak-on-kmalloc-failure.patch @@ -0,0 +1,52 @@ +From ce425dd05d0fe7594930a0fb103634f35ac47bb6 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Wed, 6 May 2026 22:20:49 +0200 +Subject: batman-adv: tp_meter: fix tp_num leak on kmalloc failure + +From: Sven Eckelmann + +commit ce425dd05d0fe7594930a0fb103634f35ac47bb6 upstream. + +When batadv_tp_start() or batadv_tp_init_recv() fail to allocate a new +tp_vars object, the previously incremented bat_priv->tp_num counter is +never decremented. This causes tp_num to drift upward on each allocation +failure. Since only BATADV_TP_MAX_NUM sessions can be started and the count +is never reduced for these failed allocations, it causes to an exhaustion +of throughput meter sessions. In worst case, no new throughput meter +session can be started until the mesh interface is removed. + +The error handling must decrement tp_num releasing the lock and aborting +the creation of an throughput meter session + +Cc: stable@kernel.org +Fixes: 33a3bb4a3345 ("batman-adv: throughput meter implementation") +Signed-off-by: Sven Eckelmann +[ Context ] +Signed-off-by: Sven Eckelmann +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/tp_meter.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/net/batman-adv/tp_meter.c ++++ b/net/batman-adv/tp_meter.c +@@ -991,6 +991,7 @@ void batadv_tp_start(struct batadv_priv + + tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); + if (!tp_vars) { ++ atomic_dec(&bat_priv->tp_num); + spin_unlock_bh(&bat_priv->tp_list_lock); + batadv_dbg(BATADV_DBG_TP_METER, bat_priv, + "Meter: %s cannot allocate list elements\n", +@@ -1367,8 +1368,10 @@ batadv_tp_init_recv(struct batadv_priv * + } + + tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); +- if (!tp_vars) ++ if (!tp_vars) { ++ atomic_dec(&bat_priv->tp_num); + goto out_unlock; ++ } + + ether_addr_copy(tp_vars->other_end, icmp->orig); + tp_vars->role = BATADV_TP_RECEIVER; diff --git a/queue-6.1/blk-cgroup-fix-null-deref-caused-by-blkg_policy_data-being-installed-before-init.patch b/queue-6.1/blk-cgroup-fix-null-deref-caused-by-blkg_policy_data-being-installed-before-init.patch new file mode 100644 index 0000000000..f454eb160e --- /dev/null +++ b/queue-6.1/blk-cgroup-fix-null-deref-caused-by-blkg_policy_data-being-installed-before-init.patch @@ -0,0 +1,166 @@ +From ec14a87ee1999b19d8b7ed0fa95fea80644624ae Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 16 Aug 2023 09:56:23 -1000 +Subject: blk-cgroup: Fix NULL deref caused by blkg_policy_data being installed before init + +From: Tejun Heo + +commit ec14a87ee1999b19d8b7ed0fa95fea80644624ae upstream. + +blk-iocost sometimes causes the following crash: + + BUG: kernel NULL pointer dereference, address: 00000000000000e0 + ... + RIP: 0010:_raw_spin_lock+0x17/0x30 + Code: be 01 02 00 00 e8 79 38 39 ff 31 d2 89 d0 5d c3 0f 1f 00 0f 1f 44 00 00 55 48 89 e5 65 ff 05 48 d0 34 7e b9 01 00 00 00 31 c0 0f b1 0f 75 02 5d c3 89 c6 e8 ea 04 00 00 5d c3 0f 1f 84 00 00 + RSP: 0018:ffffc900023b3d40 EFLAGS: 00010046 + RAX: 0000000000000000 RBX: 00000000000000e0 RCX: 0000000000000001 + RDX: ffffc900023b3d20 RSI: ffffc900023b3cf0 RDI: 00000000000000e0 + RBP: ffffc900023b3d40 R08: ffffc900023b3c10 R09: 0000000000000003 + R10: 0000000000000064 R11: 000000000000000a R12: ffff888102337000 + R13: fffffffffffffff2 R14: ffff88810af408c8 R15: ffff8881070c3600 + FS: 00007faaaf364fc0(0000) GS:ffff88842fdc0000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00000000000000e0 CR3: 00000001097b1000 CR4: 0000000000350ea0 + Call Trace: + + ioc_weight_write+0x13d/0x410 + cgroup_file_write+0x7a/0x130 + kernfs_fop_write_iter+0xf5/0x170 + vfs_write+0x298/0x370 + ksys_write+0x5f/0xb0 + __x64_sys_write+0x1b/0x20 + do_syscall_64+0x3d/0x80 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +This happens because iocg->ioc is NULL. The field is initialized by +ioc_pd_init() and never cleared. The NULL deref is caused by +blkcg_activate_policy() installing blkg_policy_data before initializing it. + +blkcg_activate_policy() was doing the following: + +1. Allocate pd's for all existing blkg's and install them in blkg->pd[]. +2. Initialize all pd's. +3. Online all pd's. + +blkcg_activate_policy() only grabs the queue_lock and may release and +re-acquire the lock as allocation may need to sleep. ioc_weight_write() +grabs blkcg->lock and iterates all its blkg's. The two can race and if +ioc_weight_write() runs during #1 or between #1 and #2, it can encounter a +pd which is not initialized yet, leading to crash. + +The crash can be reproduced with the following script: + + #!/bin/bash + + echo +io > /sys/fs/cgroup/cgroup.subtree_control + systemd-run --unit touch-sda --scope dd if=/dev/sda of=/dev/null bs=1M count=1 iflag=direct + echo 100 > /sys/fs/cgroup/system.slice/io.weight + bash -c "echo '8:0 enable=1' > /sys/fs/cgroup/io.cost.qos" & + sleep .2 + echo 100 > /sys/fs/cgroup/system.slice/io.weight + +with the following patch applied: + +> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +> index fc49be622e05..38d671d5e10c 100644 +> --- a/block/blk-cgroup.c +> +++ b/block/blk-cgroup.c +> @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol) +> pd->online = false; +> } +> +> + if (system_state == SYSTEM_RUNNING) { +> + spin_unlock_irq(&q->queue_lock); +> + ssleep(1); +> + spin_lock_irq(&q->queue_lock); +> + } +> + +> /* all allocated, init in the same order */ +> if (pol->pd_init_fn) +> list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) + +I don't see a reason why all pd's should be allocated, initialized and +onlined together. The only ordering requirement is that parent blkgs to be +initialized and onlined before children, which is guaranteed from the +walking order. Let's fix the bug by allocating, initializing and onlining pd +for each blkg and holding blkcg->lock over initialization and onlining. This +ensures that an installed blkg is always fully initialized and onlined +removing the the race window. + +Signed-off-by: Tejun Heo +Reported-by: Breno Leitao +Fixes: 9d179b865449 ("blkcg: Fix multiple bugs in blkcg_activate_policy()") +Link: https://lore.kernel.org/r/ZN0p5_W-Q9mAHBVY@slm.duckdns.org +Signed-off-by: Jens Axboe +Signed-off-by: Robert Garcia +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-cgroup.c | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -1407,7 +1407,7 @@ int blkcg_activate_policy(struct request + retry: + spin_lock_irq(&q->queue_lock); + +- /* blkg_list is pushed at the head, reverse walk to allocate parents first */ ++ /* blkg_list is pushed at the head, reverse walk to initialize parents first */ + list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) { + struct blkg_policy_data *pd; + +@@ -1445,21 +1445,20 @@ retry: + goto enomem; + } + +- blkg->pd[pol->plid] = pd; ++ spin_lock(&blkg->blkcg->lock); ++ + pd->blkg = blkg; + pd->plid = pol->plid; +- pd->online = false; +- } ++ blkg->pd[pol->plid] = pd; + +- /* all allocated, init in the same order */ +- if (pol->pd_init_fn) +- list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) +- pol->pd_init_fn(blkg->pd[pol->plid]); ++ if (pol->pd_init_fn) ++ pol->pd_init_fn(pd); + +- list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) { + if (pol->pd_online_fn) +- pol->pd_online_fn(blkg->pd[pol->plid]); +- blkg->pd[pol->plid]->online = true; ++ pol->pd_online_fn(pd); ++ pd->online = true; ++ ++ spin_unlock(&blkg->blkcg->lock); + } + + __set_bit(pol->plid, q->blkcg_pols); +@@ -1476,14 +1475,19 @@ out: + return ret; + + enomem: +- /* alloc failed, nothing's initialized yet, free everything */ ++ /* alloc failed, take down everything */ + spin_lock_irq(&q->queue_lock); + list_for_each_entry(blkg, &q->blkg_list, q_node) { + struct blkcg *blkcg = blkg->blkcg; ++ struct blkg_policy_data *pd; + + spin_lock(&blkcg->lock); +- if (blkg->pd[pol->plid]) { +- pol->pd_free_fn(blkg->pd[pol->plid]); ++ pd = blkg->pd[pol->plid]; ++ if (pd) { ++ if (pd->online && pol->pd_offline_fn) ++ pol->pd_offline_fn(pd); ++ pd->online = false; ++ pol->pd_free_fn(pd); + blkg->pd[pol->plid] = NULL; + } + spin_unlock(&blkcg->lock); diff --git a/queue-6.1/ipvs-skip-ipv6-extension-headers-for-csum-checks.patch b/queue-6.1/ipvs-skip-ipv6-extension-headers-for-csum-checks.patch new file mode 100644 index 0000000000..f82fb0b42b --- /dev/null +++ b/queue-6.1/ipvs-skip-ipv6-extension-headers-for-csum-checks.patch @@ -0,0 +1,195 @@ +From 05cfe9863ef049d98141dc2969eefde72fb07625 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Sat, 14 Feb 2026 16:58:49 +0200 +Subject: ipvs: skip ipv6 extension headers for csum checks + +From: Julian Anastasov + +commit 05cfe9863ef049d98141dc2969eefde72fb07625 upstream. + +Protocol checksum validation fails for IPv6 if there are extension +headers before the protocol header. iph->len already contains its +offset, so use it to fix the problem. + +Fixes: 2906f66a5682 ("ipvs: SCTP Trasport Loadbalancing Support") +Fixes: 0bbdd42b7efa ("IPVS: Extend protocol DNAT/SNAT and state handlers") +Signed-off-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Nazar Kalashnikov +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipvs/ip_vs_proto_sctp.c | 18 ++++++------------ + net/netfilter/ipvs/ip_vs_proto_tcp.c | 21 +++++++-------------- + net/netfilter/ipvs/ip_vs_proto_udp.c | 20 +++++++------------- + 3 files changed, 20 insertions(+), 39 deletions(-) + +--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c ++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c +@@ -10,7 +10,8 @@ + #include + + static int +-sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp); ++sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int sctphoff); + + static int + sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, +@@ -108,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, s + int ret; + + /* Some checks before mangling */ +- if (!sctp_csum_check(cp->af, skb, pp)) ++ if (!sctp_csum_check(cp->af, skb, pp, sctphoff)) + return 0; + + /* Call application helper if needed */ +@@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, s + int ret; + + /* Some checks before mangling */ +- if (!sctp_csum_check(cp->af, skb, pp)) ++ if (!sctp_csum_check(cp->af, skb, pp, sctphoff)) + return 0; + + /* Call application helper if needed */ +@@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, s + } + + static int +-sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) ++sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int sctphoff) + { +- unsigned int sctphoff; + struct sctphdr *sh; + __le32 cmp, val; + +-#ifdef CONFIG_IP_VS_IPV6 +- if (af == AF_INET6) +- sctphoff = sizeof(struct ipv6hdr); +- else +-#endif +- sctphoff = ip_hdrlen(skb); +- + sh = (struct sctphdr *)(skb->data + sctphoff); + cmp = sh->checksum; + val = sctp_compute_cksum(skb, sctphoff); +--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c ++++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c +@@ -29,7 +29,8 @@ + #include + + static int +-tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp); ++tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int tcphoff); + + static int + tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, +@@ -166,7 +167,7 @@ tcp_snat_handler(struct sk_buff *skb, st + int ret; + + /* Some checks before mangling */ +- if (!tcp_csum_check(cp->af, skb, pp)) ++ if (!tcp_csum_check(cp->af, skb, pp, tcphoff)) + return 0; + + /* Call application helper if needed */ +@@ -244,7 +245,7 @@ tcp_dnat_handler(struct sk_buff *skb, st + int ret; + + /* Some checks before mangling */ +- if (!tcp_csum_check(cp->af, skb, pp)) ++ if (!tcp_csum_check(cp->af, skb, pp, tcphoff)) + return 0; + + /* +@@ -301,17 +302,9 @@ tcp_dnat_handler(struct sk_buff *skb, st + + + static int +-tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) ++tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int tcphoff) + { +- unsigned int tcphoff; +- +-#ifdef CONFIG_IP_VS_IPV6 +- if (af == AF_INET6) +- tcphoff = sizeof(struct ipv6hdr); +- else +-#endif +- tcphoff = ip_hdrlen(skb); +- + switch (skb->ip_summed) { + case CHECKSUM_NONE: + skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); +@@ -322,7 +315,7 @@ tcp_csum_check(int af, struct sk_buff *s + if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + skb->len - tcphoff, +- ipv6_hdr(skb)->nexthdr, ++ IPPROTO_TCP, + skb->csum)) { + IP_VS_DBG_RL_PKT(0, af, pp, skb, 0, + "Failed checksum for"); +--- a/net/netfilter/ipvs/ip_vs_proto_udp.c ++++ b/net/netfilter/ipvs/ip_vs_proto_udp.c +@@ -25,7 +25,8 @@ + #include + + static int +-udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp); ++udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int udphoff); + + static int + udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, +@@ -155,7 +156,7 @@ udp_snat_handler(struct sk_buff *skb, st + int ret; + + /* Some checks before mangling */ +- if (!udp_csum_check(cp->af, skb, pp)) ++ if (!udp_csum_check(cp->af, skb, pp, udphoff)) + return 0; + + /* +@@ -238,7 +239,7 @@ udp_dnat_handler(struct sk_buff *skb, st + int ret; + + /* Some checks before mangling */ +- if (!udp_csum_check(cp->af, skb, pp)) ++ if (!udp_csum_check(cp->af, skb, pp, udphoff)) + return 0; + + /* +@@ -297,17 +298,10 @@ udp_dnat_handler(struct sk_buff *skb, st + + + static int +-udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) ++udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ++ unsigned int udphoff) + { + struct udphdr _udph, *uh; +- unsigned int udphoff; +- +-#ifdef CONFIG_IP_VS_IPV6 +- if (af == AF_INET6) +- udphoff = sizeof(struct ipv6hdr); +- else +-#endif +- udphoff = ip_hdrlen(skb); + + uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph); + if (uh == NULL) +@@ -325,7 +319,7 @@ udp_csum_check(int af, struct sk_buff *s + if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + skb->len - udphoff, +- ipv6_hdr(skb)->nexthdr, ++ IPPROTO_UDP, + skb->csum)) { + IP_VS_DBG_RL_PKT(0, af, pp, skb, 0, + "Failed checksum for"); diff --git a/queue-6.1/series b/queue-6.1/series index b6d5ef9912..8044c1d894 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -487,3 +487,7 @@ mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.pat rdma-umem-fix-kernel-doc-warnings.patch rdma-move-dma-block-iterator-logic-into-dedicated-files.patch rdma-umem-fix-truncation-for-block-sizes-4g.patch +ipvs-skip-ipv6-extension-headers-for-csum-checks.patch +blk-cgroup-fix-null-deref-caused-by-blkg_policy_data-being-installed-before-init.patch +batman-adv-stop-tp_meter-sessions-during-mesh-teardown.patch +batman-adv-tp_meter-fix-tp_num-leak-on-kmalloc-failure.patch