Skip to content

Instantly share code, notes, and snippets.

@mrpre
Created February 13, 2026 05:33
Show Gist options
  • Select an option

  • Save mrpre/a94d431c757e8d6f168f4dd1a3749daa to your computer and use it in GitHub Desktop.

Select an option

Save mrpre/a94d431c757e8d6f168f4dd1a3749daa to your computer and use it in GitHub Desktop.
trigger WARN
[ 135.031791] ------------[ cut here ]------------
[ 135.031795] WARNING: net/kcm/kcmsock.c:631 at kcm_write_msgs+0x39b/0x6e0, CPU#1: rep/446
[ 135.031807] Modules linked in:
[ 135.031815] CPU: 1 UID: 0 PID: 446 Comm: rep Tainted: G W 6.19.0-rc8+ #139 PREEMPT_RT
[ 135.031822] Tainted: [W]=WARN
[ 135.031825] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 135.031828] RIP: 0010:kcm_write_msgs+0x39b/0x6e0
[ 135.031845] Code: ff ff e8 d8 8e c5 ff ba 02 00 00 00 4c 89 e6 31 ff e8 e9 1f c6 ff 49 83 87 b8 01 00 00 01 e9 55 fe ff ff 4c 8b 8d 60 ff ff ff <0f> 0b bb ea ff ff ff e9 97 fe ff ff 48 86
[ 135.031849] RSP: 0018:ffffd0dfc182b9f0 EFLAGS: 00010246
[ 135.031854] RAX: 0000000000000000 RBX: 0000000000088000 RCX: 0000000000000000
[ 135.031858] RDX: ffff8cba40e72540 RSI: 0000000000000000 RDI: ffffd0dfc182ba90
[ 135.031861] RBP: ffffd0dfc182bac0 R08: 0000000000000000 R09: ffff8cba49a9b780
[ 135.031864] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8cba4679ff00
[ 135.031866] R13: ffffd0dfc182ba28 R14: ffff8cba4679fe00 R15: ffff8cba485f2640
[ 135.031868] FS: 00007f6e01b03740(0000) GS:ffff8cbad4350000(0000) knlGS:0000000000000000
[ 135.031872] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 135.031874] CR2: 00005631188082a8 CR3: 0000000109ac2004 CR4: 0000000000770ef0
[ 135.031883] PKRU: 55555554
[ 135.031885] Call Trace:
[ 135.031887] <TASK>
[ 135.031926] kcm_sendmsg+0xab0/0xcf0
[ 135.031935] ? aa_sk_perm+0x85/0x360
[ 135.031964] sock_write_iter+0x1a8/0x1b0
[ 135.031986] vfs_write+0x41f/0x570
[ 135.032006] ksys_write+0xda/0x100
[ 135.032016] __x64_sys_write+0x19/0x30
[ 135.032020] x64_sys_call+0x79/0x26b0
[ 135.032026] do_syscall_64+0x89/0x510
[ 135.032033] ? do_syscall_64+0x1cb/0x510
[ 135.032046] ? find_held_lock+0x31/0x90
[ 135.032064] ? rcu_read_unlock+0x1c/0x80
[ 135.032094] ? lock_release+0xcd/0x280
[ 135.032111] ? find_held_lock+0x31/0x90
[ 135.032115] ? exc_page_fault+0x94/0x260
[ 135.032136] ? lock_release+0xcd/0x280
[ 135.032150] ? irqentry_exit+0x17f/0x790
[ 135.032162] ? clear_bhb_loop+0x50/0xa0
[ 135.032167] ? clear_bhb_loop+0x50/0xa0
[ 135.032174] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 135.032176] RIP: 0033:0x7f6e01c225a4
[ 135.032181] Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d a5 ea 0e 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 49
[ 135.032183] RSP: 002b:00007fff6f1e3288 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[ 135.032187] RAX: ffffffffffffffda RBX: 00007fff6f1e3478 RCX: 00007f6e01c225a4
[ 135.032188] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000006
[ 135.032190] RBP: 00007fff6f1e3350 R08: 00007f6e01d09b20 R09: 0000000000000000
[ 135.032191] R10: 0000000000000001 R11: 0000000000000202 R12: 0000000000000001
[ 135.032193] R13: 0000000000000000 R14: 00005630fa428d28 R15: 00007f6e01d5e000
[ 135.032214] </TASK>
[ 135.032215] irq event stamp: 10955
[ 135.032217] hardirqs last enabled at (10957): [<ffffffffa4a70c94>] vprintk_store+0x664/0x720
[ 135.032223] hardirqs last disabled at (10958): [<ffffffffa4a70a9e>] vprintk_store+0x46e/0x720
[ 135.032231] softirqs last enabled at (10852): [<ffffffffa49a251b>] __local_bh_enable_ip+0x14b/0x190
[ 135.032236] softirqs last disabled at (10846): [<ffffffffa5903452>] release_sock+0x22/0xe0
[ 135.032240] ---[ end trace 0000000000000000 ]---
[ 135.032244] KCM: Hard failure on kcm_write_msgs
// CONFIG_AF_KCM=y
// gcc -o kcm_zero_frag_repro kcm_zero_frag_repro.c && ./kcm_zero_frag_repro
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <netinet/in.h>
#include <linux/kcm.h>
#include <linux/bpf.h>
#include <sys/syscall.h>
#ifndef AF_KCM
#define AF_KCM 41
#endif
#ifndef SIOCKCMATTACH
#define SIOCKCMATTACH (0x89E0 + 0)
#endif
#define NFRAGS 17 /* MAX_SKB_FRAGS */
#define FRAG_SZ 32768 /* page frag allocator max */
// I use Claude to generate such BPF inst ....
// KCM requires a BPF prog to parse message boundaries,
// returning the message length. Return INT_MAX to treat all
// data as one msg.
static int bpf_accept_all(void)
{
struct bpf_insn {
__u8 code; __u8 dst_reg:4; __u8 src_reg:4;
__s16 off; __s32 imm;
} insns[] = {
{ 0xb7, 0, 0, 0, 0x7fffffff }, /* r0 = INT_MAX */
{ 0x95, 0, 0, 0, 0 }, /* exit */
};
char log[4096] = {};
union bpf_attr attr = {
.prog_type = 1,
.insns = (unsigned long)insns,
.insn_cnt = 2,
.license = (unsigned long)"GPL",
.log_buf = NULL,
.log_size = 0,
.log_level = 0,
};
return syscall(__NR_bpf, 5, &attr, sizeof(attr));
}
int main(void)
{
int cfd, afd, lfd, kcm, bpf, ret;
int one = 1;
struct sockaddr_in sa = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
};
socklen_t slen = sizeof(sa);
long pgsz = sysconf(_SC_PAGESIZE);
size_t good = (size_t)NFRAGS * FRAG_SZ;
size_t total = good + pgsz;
int bufsz = total * 2;
// create tcp
lfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bind(lfd, (void *)&sa, sizeof(sa));
getsockname(lfd, (void *)&sa, &slen);
listen(lfd, 1);
cfd = socket(AF_INET, SOCK_STREAM, 0);
connect(cfd, (void *)&sa, sizeof(sa));
afd = accept(lfd, NULL, NULL);
close(lfd);
setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz));
// create kcm
bpf = bpf_accept_all();
kcm = socket(AF_KCM, SOCK_SEQPACKET, 0);
setsockopt(kcm, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz));
struct kcm_attach att = { .fd = cfd, .bpf_fd = bpf };
ioctl(kcm, SIOCKCMATTACH, &att);
// mmap good+1page, then unmap the last page.
char *buf = mmap(NULL, total, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
memset(buf, 'X', good);
munmap(buf + good, pgsz);
struct iovec iov = { buf, total };
struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
ret = sendmsg(kcm, &msg, 0);
printf("sendmsg=%d (expect partial ~%zu)\n", ret, good);
// zero-length write on SEQPACKET implies EOR, triggers the warn
write(kcm, NULL, 0);
printf("check dmesg for WARNING at kcm\n");
close(kcm);
close(cfd);
close(afd);
close(bpf);
munmap(buf, good);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment