Security1 publisher3 min readPublished
Disabling unprivileged user namespaces stops three of four new Linux local-root bugs
Fixes are in for four Linux local-root bugs found in code more than a decade old. Turning off unprivileged user namespaces closes three of them. The fourth stays open.
The Watch · Security desk

What happened
- Four Linux local-privilege-escalation vulnerabilities were disclosed together: DirtyAH6 (CVE-2026-80844), TUNderflow (CVE-2026-81000), PPPoEject (CVE-2026-68121) and DiagSpill (CVE-2026-74469).
- DirtyAH6, TUNderflow and PPPoEject all need unprivileged user namespaces to reach local root, while DiagSpill reaches it without one.
- Fixes went in after a mid-July report to [email protected], and the writeup plus proof-of-concept code publish on September 18 at 6am UTC under a linux-distros embargo.
Compiled by The WatchSomething wrong?How this is made
Why it matters
- decision The unprivileged user namespace setting now has a coverage number on this batch: off, it removes three local paths and leaves one. That is a partial control operators can size.
- exposure A host running IPsec AH in transport mode can be crashed by someone holding no local account at all, so DirtyAH6 does not belong in the queue behind the local-only bugs.
- cost After 06:00 UTC on September 18, the cost of attacking an unpatched host drops to running published code, and the patch window closes for everyone who has not shipped the kernel update.
- precedent One harness delivered four kernel LPEs in a single coordinated release, so the next disclosure from the same tooling should be planned for as a batch of CVEs across several subsystems.
DirtyAH6 is the one to read first. `ipv6_rearrange_rthdr()` took the number of addresses from `hdrlen`, then moved an address pointer by `segments - segments_left` without first checking that `segments_left` was no larger than `segments` [9]. A raw IPv6 `HDRINCL` packet with `hdrlen=2` and `segments_left=255` moved the pointer back 4,064 bytes and handed the same 4,064-byte length to `memmove()` [10]. At 16 bytes per IPv6 address, that displacement is 254 addresses [18].
With AH in transport mode, the same bug becomes a remote crash or denial of service, and with memory grooming performed on the target the researcher turned it into remote root in the lab [11]. The researcher wrote that getting to root with remote-only grooming looks extremely difficult but is not a priori impossible [12].
TUNderflow is an integer underflow. `tun_set_headroom()` stored receive headroom straight into `tun->align`, while `tun_get_user()` used the same value to decide how much packet data to keep in the head [13]. A `netkit` device with 4,096 bytes of configured headroom, under a VXLAN device and an Open vSwitch datapath, passed 4,160 bytes to a raw TUN port; `SKB_MAX_HEAD(4160)` underflowed, the negative `good_linear` became a huge `size_t`, `prepad + linear` and `len - linear` wrapped, and `tun_alloc_skb()` left `skb->data` 64 bytes beyond its 4,096-byte allocation [14]. The overshoot is exactly what the chain added on top of the configured headroom [19].
In PPPoEject, `pppoe_sendmsg()` held a pointer into the `skb` head across `dev_hard_header()`, where a device callback can call `pskb_expand_head()` and free that head [15]. Blocking the payload copy on FUSE while adding the first GRE or IP6GRE port to an empty `team` or `bonding` device triggered the reallocation [16].
DiagSpill is the outlier. It needs no user namespace [3], and it is the second of the two bugs with a remote condition [4]. The post describes `sctp_diag` building a Netlink reply with one `sockaddr_storage` per peer transport [17]; the exploitation detail comes with the writeup and proof-of-concept code on September 18 [6].
So the hardening call is bounded. Switching off unprivileged user namespaces takes away the local path for DirtyAH6, TUNderflow and PPPoEject, three of the four [20]. DiagSpill's local path does not use a namespace, and neither does the AH6 remote path [3][11].
All four came out of one harness: graph-based tracking of security-relevant kernel objects, as used in CIFSwitch, combined with the tooling from OVSwrap that lets agents reason geometrically about memory state [8]. The underlying bugs had been in the tree for 10 to 21 years [2]. Report to public code runs about nine weeks [21], and the post credits Stefan Klassert, Xin Long, Paolo Abeni, Willem de Bruijn and Greg KH among the maintainers who handled patching and coordination [7].
What to watch
- Whether distribution kernels carry all four fixes before the proof-of-concept code publishes at 06:00 UTC on September 18.
- Whether anyone reproduces DirtyAH6 remote root with grooming performed entirely over the network, which the researcher called extremely difficult.
- What conditions DiagSpill's remote path actually requires, since it is the one LPE here that no user namespace setting blocks.