In the Linux kernel, the following vulnerability has been resolved: tun: Fix memory leak for detached NAPI queue. syzkaller reported [0] memory leaks of sk and skb related to the TUN device with no repro, but we can reproduce it easily with: struct ifreq ifr = {} int fdtun, fdtmp; char buf[4] = {}; fdtun = openat(ATFDCWD, "/dev/net/tun", OWRONLY, 0); ifr.ifrflags = IFFTUN | IFFNAPI | IFFMULTIQUEUE; ioctl(fdtun, TUNSETIFF, &ifr); ifr.ifrflags = IFFDETACHQUEUE; ioctl(fdtun, TUNSETQUEUE, &ifr); fdtmp = socket(AFPACKET, SOCKPACKET, 0); ifr.ifrflags = IFFUP; ioctl(fdtmp, SIOCSIFFLAGS, &ifr); write(fdtun, buf, sizeof(buf)); close(fdtun); If we enable NAPI and multi-queue on a TUN device, we can put skb into tfile->sk.skwritequeue after the queue is detached. We should prevent it by checking tfile->detached before queuing skb. Note this must be done under tfile->sk.skwritequeue.lock because write() and ioctl(IFFDETACHQUEUE) can run concurrently. Otherwise, there would be a small race window: write() ioctl(IFFDETACH_QUEUE) - tun_get_user- __tundetach |- if (tfile->detached) |- tundisable_queue | -> false |- tfile->detached = tun | - tun_queue_purge |- spin_lock_bh(&queue->lock)- __skbqueuetail(queue, skb) Another solution is to call tunqueuepurge() when closing and reattaching the detached queue, but it could paper over another problems. Also, we do the same kind of test for IFFNAPIFRAGS. [0]: unreferenced object 0xffff88801edbc800 (size 2048): comm "syz-executor.1", pid 33269, jiffies 4295743834 (age 18.756s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ backtrace: [<000000008c16ea3d>] __dokmallocnode mm/slab_common.c:965 [inline] [<000000008c16ea3d>] __kmalloc+0x4a/0x130 mm/slabcommon.c:979 [<000000003addde56>] kmalloc include/linux/slab.h:563 [inline] [<000000003addde56>] skprot_alloc+0xef/0x1b0 net/core/sock.c:2035 [<000000003e20621f>] skalloc+0x36/0x2f0 net/core/sock.c:2088 [<0000000028e43843>] tunchropen+0x3d/0x190 drivers/net/tun.c:3438 [<000000001b0f1f28>] miscopen+0x1a6/0x1f0 drivers/char/misc.c:165 [<000000004376f706>] chrdevopen+0x111/0x300 fs/chardev.c:414 [<00000000614d379f>] dodentryopen+0x2f9/0x750 fs/open.c:920 [<000000008eb24774>] doopen fs/namei.c:3636 [inline] [<000000008eb24774>] pathopenat+0x143f/0x1a30 fs/namei.c:3791 [<00000000955077b5>] dofilpopen+0xce/0x1c0 fs/namei.c:3818 [<00000000b78973b0>] dosysopenat2+0xf0/0x260 fs/open.c:1356 [<00000000057be699>] dosysopen fs/open.c:1372 [inline] [<00000000057be699>] __dosysopenat fs/open.c:1388 [inline] [<00000000057be699>] __sesysopenat fs/open.c:1383 [inline] [<00000000057be699>] __x64sysopenat+0x83/0xf0 fs/open.c:1383 [<00000000a7d2182d>] dosyscallx64 arch/x86/entry/common.c:50 [inline] [<00000000a7d2182d>] dosyscall64+0x3c/0x90 arch/x86/entry/common.c:80 [<000000004cc4e8c4>] entrySYSCALL64afterhwframe+0x72/0xdc unreferenced object 0xffff88802f671700 (size 240): comm "syz-executor.1", pid 33269, jiffies 4295743854 (age 18.736s) hex dump (first 32 bytes): 68 c9 db 1e 80 88 ff ff 68 c9 db 1e 80 88 ff ff h.......h....... 00 c0 7b 2f 80 88 ff ff 00 c8 db 1e 80 88 ff ff ..{/............ backtrace: [<00000000e9d9fdb6>] __allocskb+0x223/0x250 net/core/skbuff.c:644 [<000000002c3e4e0b>] allocskb include/linux/skbuff.h:1288 [inline] [<000000002c3e4e0b>] allocskbwithfrags+0x6f/0x350 net/core/skbuff.c:6378 [<00000000825f98d7>] sockallocsendpskb+0x3ac/0x3e0 net/core/sock.c:2729 [<00000000e9eb3df3>] tunallocskb drivers/net/tun.c:1529 [inline] [< ---truncated---