From: Greg Kroah-Hartman Date: Mon, 6 Oct 2025 10:08:08 +0000 (+0200) Subject: 5.15-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8b5df7c8f2f23f13b36007857ee1d7fcb276204;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: kvm-arm64-fix-softirq-masking-in-fpsimd-register-saving-sequence.patch udp-fix-memory-accounting-leak.patch --- diff --git a/queue-5.15/kvm-arm64-fix-softirq-masking-in-fpsimd-register-saving-sequence.patch b/queue-5.15/kvm-arm64-fix-softirq-masking-in-fpsimd-register-saving-sequence.patch new file mode 100644 index 0000000000..e78083a892 --- /dev/null +++ b/queue-5.15/kvm-arm64-fix-softirq-masking-in-fpsimd-register-saving-sequence.patch @@ -0,0 +1,89 @@ +From will@kernel.org Mon Oct 6 11:59:13 2025 +From: Will Deacon +Date: Fri, 3 Oct 2025 19:39:17 +0100 +Subject: KVM: arm64: Fix softirq masking in FPSIMD register saving sequence +To: stable@vger.kernel.org +Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, Will Deacon , Ard Biesheuvel , Lee Jones , Sasha Levin , Kenneth Van Alstyne +Message-ID: <20251003183917.4209-1-will@kernel.org> + +From: Will Deacon + +Stable commit 23249dade24e ("KVM: arm64: Fix kernel BUG() due to bad +backport of FPSIMD/SVE/SME fix") fixed a kernel BUG() caused by a bad +backport of upstream commit fbc7e61195e2 ("KVM: arm64: Unconditionally +save+flush host FPSIMD/SVE/SME state") by ensuring that softirqs are +disabled/enabled across the fpsimd register save operation. + +Unfortunately, although this fixes the original issue, it can now lead +to deadlock when re-enabling softirqs causes pending softirqs to be +handled with locks already held: + + | BUG: spinlock recursion on CPU#7, CPU 3/KVM/57616 + | lock: 0xffff3045ef850240, .magic: dead4ead, .owner: CPU 3/KVM/57616, .owner_cpu: 7 + | CPU: 7 PID: 57616 Comm: CPU 3/KVM Tainted: G O 6.1.152 #1 + | Hardware name: SoftIron SoftIron Platform Mainboard/SoftIron Platform Mainboard, BIOS 1.31 May 11 2023 + | Call trace: + | dump_backtrace+0xe4/0x110 + | show_stack+0x20/0x30 + | dump_stack_lvl+0x6c/0x88 + | dump_stack+0x18/0x34 + | spin_dump+0x98/0xac + | do_raw_spin_lock+0x70/0x128 + | _raw_spin_lock+0x18/0x28 + | raw_spin_rq_lock_nested+0x18/0x28 + | update_blocked_averages+0x70/0x550 + | run_rebalance_domains+0x50/0x70 + | handle_softirqs+0x198/0x328 + | __do_softirq+0x1c/0x28 + | ____do_softirq+0x18/0x28 + | call_on_irq_stack+0x30/0x48 + | do_softirq_own_stack+0x24/0x30 + | do_softirq+0x74/0x90 + | __local_bh_enable_ip+0x64/0x80 + | fpsimd_save_and_flush_cpu_state+0x5c/0x68 + | kvm_arch_vcpu_put_fp+0x4c/0x88 + | kvm_arch_vcpu_put+0x28/0x88 + | kvm_sched_out+0x38/0x58 + | __schedule+0x55c/0x6c8 + | schedule+0x60/0xa8 + +Take a tiny step towards the upstream fix in 9b19700e623f ("arm64: +fpsimd: Drop unneeded 'busy' flag") by additionally disabling hardirqs +while saving the fpsimd registers. + +Cc: Ard Biesheuvel +Cc: Lee Jones +Cc: Sasha Levin +Cc: # 5.15.y +Fixes: 23249dade24e ("KVM: arm64: Fix kernel BUG() due to bad backport of FPSIMD/SVE/SME fix") +Reported-by: Kenneth Van Alstyne +Link: https://lore.kernel.org/r/010001999bae0958-4d80d25d-8dda-4006-a6b9-798f3e774f6c-000000@email.amazonses.com +Signed-off-by: Will Deacon +Acked-by: Ard Biesheuvel +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/fpsimd.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -1300,13 +1300,17 @@ static void fpsimd_flush_cpu_state(void) + */ + void fpsimd_save_and_flush_cpu_state(void) + { ++ unsigned long flags; ++ + if (!system_supports_fpsimd()) + return; + WARN_ON(preemptible()); +- get_cpu_fpsimd_context(); ++ local_irq_save(flags); ++ __get_cpu_fpsimd_context(); + fpsimd_save(); + fpsimd_flush_cpu_state(); +- put_cpu_fpsimd_context(); ++ __put_cpu_fpsimd_context(); ++ local_irq_restore(flags); + } + + #ifdef CONFIG_KERNEL_MODE_NEON diff --git a/queue-5.15/series b/queue-5.15/series index e75a3b90f8..1be5384e07 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -3,3 +3,5 @@ scsi-target-target_core_configfs-add-length-check-to-avoid-buffer-overflow.patch media-b2c2-fix-use-after-free-causing-by-irq_check_work-in-flexcop_pci_remove.patch media-rc-fix-races-with-imon_disconnect.patch media-uvcvideo-mark-invalid-entities-with-id-uvc_invalid_entity_id.patch +kvm-arm64-fix-softirq-masking-in-fpsimd-register-saving-sequence.patch +udp-fix-memory-accounting-leak.patch diff --git a/queue-5.15/udp-fix-memory-accounting-leak.patch b/queue-5.15/udp-fix-memory-accounting-leak.patch new file mode 100644 index 0000000000..7d6855508f --- /dev/null +++ b/queue-5.15/udp-fix-memory-accounting-leak.patch @@ -0,0 +1,168 @@ +From df207de9d9e7a4d92f8567e2c539d9c8c12fd99d Mon Sep 17 00:00:00 2001 +From: Kuniyuki Iwashima +Date: Tue, 1 Apr 2025 11:44:43 -0700 +Subject: udp: Fix memory accounting leak. + +From: Kuniyuki Iwashima + +commit df207de9d9e7a4d92f8567e2c539d9c8c12fd99d upstream. + +Matt Dowling reported a weird UDP memory usage issue. + +Under normal operation, the UDP memory usage reported in /proc/net/sockstat +remains close to zero. However, it occasionally spiked to 524,288 pages +and never dropped. Moreover, the value doubled when the application was +terminated. Finally, it caused intermittent packet drops. + +We can reproduce the issue with the script below [0]: + + 1. /proc/net/sockstat reports 0 pages + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 0 + + 2. Run the script till the report reaches 524,288 + + # python3 test.py & sleep 5 + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 3 mem 524288 <-- (INT_MAX + 1) >> PAGE_SHIFT + + 3. Kill the socket and confirm the number never drops + + # pkill python3 && sleep 5 + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 524288 + + 4. (necessary since v6.0) Trigger proto_memory_pcpu_drain() + + # python3 test.py & sleep 1 && pkill python3 + + 5. The number doubles + + # cat /proc/net/sockstat | grep UDP: + UDP: inuse 1 mem 1048577 + +The application set INT_MAX to SO_RCVBUF, which triggered an integer +overflow in udp_rmem_release(). + +When a socket is close()d, udp_destruct_common() purges its receive +queue and sums up skb->truesize in the queue. This total is calculated +and stored in a local unsigned integer variable. + +The total size is then passed to udp_rmem_release() to adjust memory +accounting. However, because the function takes a signed integer +argument, the total size can wrap around, causing an overflow. + +Then, the released amount is calculated as follows: + + 1) Add size to sk->sk_forward_alloc. + 2) Round down sk->sk_forward_alloc to the nearest lower multiple of + PAGE_SIZE and assign it to amount. + 3) Subtract amount from sk->sk_forward_alloc. + 4) Pass amount >> PAGE_SHIFT to __sk_mem_reduce_allocated(). + +When the issue occurred, the total in udp_destruct_common() was 2147484480 +(INT_MAX + 833), which was cast to -2147482816 in udp_rmem_release(). + +At 1) sk->sk_forward_alloc is changed from 3264 to -2147479552, and +2) sets -2147479552 to amount. 3) reverts the wraparound, so we don't +see a warning in inet_sock_destruct(). However, udp_memory_allocated +ends up doubling at 4). + +Since commit 3cd3399dd7a8 ("net: implement per-cpu reserves for +memory_allocated"), memory usage no longer doubles immediately after +a socket is close()d because __sk_mem_reduce_allocated() caches the +amount in udp_memory_per_cpu_fw_alloc. However, the next time a UDP +socket receives a packet, the subtraction takes effect, causing UDP +memory usage to double. + +This issue makes further memory allocation fail once the socket's +sk->sk_rmem_alloc exceeds net.ipv4.udp_rmem_min, resulting in packet +drops. + +To prevent this issue, let's use unsigned int for the calculation and +call sk_forward_alloc_add() only once for the small delta. + +Note that first_packet_length() also potentially has the same problem. + +[0]: +from socket import * + +SO_RCVBUFFORCE = 33 +INT_MAX = (2 ** 31) - 1 + +s = socket(AF_INET, SOCK_DGRAM) +s.bind(('', 0)) +s.setsockopt(SOL_SOCKET, SO_RCVBUFFORCE, INT_MAX) + +c = socket(AF_INET, SOCK_DGRAM) +c.connect(s.getsockname()) + +data = b'a' * 100 + +while True: + c.send(data) + +Fixes: f970bd9e3a06 ("udp: implement memory accounting helpers") +Reported-by: Matt Dowling +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250401184501.67377-3-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +[ Yifei: resolve minor conflicts ] +Signed-off-by: Yifei Liu +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/udp.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1459,12 +1459,12 @@ static bool udp_skb_has_head_state(struc + } + + /* fully reclaim rmem/fwd memory allocated for skb */ +-static void udp_rmem_release(struct sock *sk, int size, int partial, +- bool rx_queue_lock_held) ++static void udp_rmem_release(struct sock *sk, unsigned int size, ++ int partial, bool rx_queue_lock_held) + { + struct udp_sock *up = udp_sk(sk); + struct sk_buff_head *sk_queue; +- int amt; ++ unsigned int amt; + + if (likely(partial)) { + up->forward_deficit += size; +@@ -1484,10 +1484,8 @@ static void udp_rmem_release(struct sock + if (!rx_queue_lock_held) + spin_lock(&sk_queue->lock); + +- +- sk->sk_forward_alloc += size; +- amt = (sk->sk_forward_alloc - partial) & ~(SK_MEM_QUANTUM - 1); +- sk->sk_forward_alloc -= amt; ++ amt = (size + sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1); ++ sk->sk_forward_alloc += size - amt; + + if (amt) + __sk_mem_reduce_allocated(sk, amt >> SK_MEM_QUANTUM_SHIFT); +@@ -1671,7 +1669,7 @@ EXPORT_SYMBOL_GPL(skb_consume_udp); + + static struct sk_buff *__first_packet_length(struct sock *sk, + struct sk_buff_head *rcvq, +- int *total) ++ unsigned int *total) + { + struct sk_buff *skb; + +@@ -1704,8 +1702,8 @@ static int first_packet_length(struct so + { + struct sk_buff_head *rcvq = &udp_sk(sk)->reader_queue; + struct sk_buff_head *sk_queue = &sk->sk_receive_queue; ++ unsigned int total = 0; + struct sk_buff *skb; +- int total = 0; + int res; + + spin_lock_bh(&rcvq->lock);