CVE-2026-43494 is not a remote bug that lets anyone on the internet root every Linux host. It is more specific, and that specificity is exactly why defenders can misread it.
The vulnerability, publicly discussed as PinTheft, sits in the Linux kernel’s Reliable Datagram Sockets code, specifically the RDS zerocopy send path. The kernel bug is an accounting mistake: after a page pin failure, already pinned pages are released, but the count of scatterlist entries is not reset. Later cleanup can release those pages again. On its own, that description sounds like a small kernel cleanup bug. In the public PinTheft chain, it becomes a local privilege escalation because io_uring fixed buffers can keep a stale relationship to a page after the page has been freed and reused as page cache for a SUID-root binary. When that cached page is overwritten with attacker-controlled bytes, the next execution of the SUID binary can run code as root. NVD describes the kernel fix as net/rds: reset op_nents when zerocopy page pin fails, and the public V12 Security write-up describes PinTheft as an RDS zerocopy double-free that can be converted into page-cache overwrite through io_uring fixed buffers. (nvd.nist.gov) (ギットハブ)
That does not mean every Linux server is exposed. The public exploit chain depends on multiple gates: local code execution, RDS and RDS TCP support, module loadability, usable io_uring, a readable SUID-root binary, and kernel behavior compatible with the PoC. V12 reported that, among the common distributions they tested, the required RDS module was default only on Arch Linux; an oss-security follow-up also showed why distribution packaging and module blacklist behavior can change the answer for systems such as Fedora. (ギットハブ) (openwall.com)
That combination gives defenders a clear job: do not panic because the word “root” appears, and do not dismiss the bug because it is “only local.” Treat CVE-2026-43494 as a kernel local privilege escalation that becomes urgent on hosts where untrusted users, containers, CI jobs, student labs, shared shell accounts, web workloads, or semi-trusted agents can execute local code.
The fast read for security teams
| フィールド | Practical meaning |
|---|---|
| CVE | CVE-2026-43494 |
| Public name | PinTheft |
| Vulnerable area | Linux kernel net/rds zerocopy send path |
| Bug type | RDS zerocopy cleanup accounting error leading to a double release of pinned pages |
| Exploit class | Local privilege escalation |
| Attacker position | The attacker needs local code execution first |
| Public exploit status | Public proof-of-concept code exists |
| Main exploit conversion | RDS reference-count corruption plus io_uring fixed buffers |
| Target effect | In-memory page-cache overwrite of a SUID-root binary |
| Key gates | CONFIG_RDS, CONFIG_RDS_TCP, CONFIG_IO_URING, RDS module loadability, kernel.io_uring_disabled=0, readable SUID-root binary |
| Durable remediation | Vendor kernel update, followed by reboot or supported livepatch |
| Compensating controls | Block RDS modules, restrict io_uring, reduce SUID exposure, isolate untrusted local workloads |
The most important operational distinction is between “package vulnerability” and “reachable exploit path.” A scanner may correctly detect a kernel package associated with CVE-2026-43494, but that does not prove that RDS is compiled in, that rds_tcp can be loaded, that io_uring is available to the attacker, or that the public exploit can run on that specific kernel flavor. Tenable’s Nessus plugin, for example, says it relies on package presence as reported by the vendor, while Debian, Ubuntu, SUSE, CloudLinux, and other vendors expose more detailed release and configuration context elsewhere. (Tenable®) (security-tracker.debian.org) (Ubuntu) (suse.com)
What actually broke in the kernel
The root cause is in the RDS zerocopy send path, not in SSH, not in a web server, and not in userland package parsing.
The vulnerable function path involves rds_message_zcopy_from_user(). In the vulnerable error path, the kernel attempts to pin user pages for zerocopy transmission. If iov_iter_get_pages2() fails after some pages have already been pinned, the code releases the pages it already pinned and clears the zcopy notifier. The missing step is resetting rm->data.op_nents, the count that later cleanup uses to decide how many scatterlist entries still need to be released. When rds_message_purge() later runs from the send path, it can walk a non-zero op_nents count and release those page references again. NVD, Ubuntu, Debian, SUSE, and GitHub’s advisory database all describe this same failure pattern: already pinned pages are released after a page-pin failure, but op_nents is not properly cleared, so a later cleanup loop can free them again. (nvd.nist.gov) (Ubuntu) (security-tracker.debian.org) (ギットハブ)
A simplified version of the vulnerable state looks like this:
/*
* Defensive pseudocode for understanding the bug.
* This is not exploit code.
*/
int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *from)
{
while (iov_iter_count(from)) {
ret = iov_iter_get_pages2(from, &page, PAGE_SIZE, 1, &start);
if (ret < 0) {
for (i = 0; i < rm->data.op_nents; i++)
put_page(sg_page(&rm->data.op_sg[i]));
rm->data.op_mmp_znotifier = NULL;
/*
* Vulnerable state:
* op_nents still says entries exist.
* A later purge path may release the same pages again.
*/
return ret;
}
sg_set_page(...);
rm->data.op_nents++;
}
return 0;
}
The upstream fix is conceptually small: when the zerocopy path fails and the already pinned pages are released, the count of entries must be reset so that later cleanup does not act on stale accounting. Small patches are common in kernel security because the security property is often not “this line checks a password,” but “this reference must not outlive the object it describes.” NVD lists the upstream and stable references, while Debian’s tracker points to the mainline commit and fixed versions for specific Debian branches. (nvd.nist.gov) (security-tracker.debian.org)
The bug becomes severe because it occurs around page pinning. Page pins are not ordinary temporary variables. They are part of the kernel’s memory-lifetime model. If reference counts are reduced incorrectly, a page can be freed while another subsystem still believes it owns a valid reference to it. That is the opening PinTheft uses.
Why RDS matters, even though most admins rarely touch it
RDS stands for Reliable Datagram Sockets. It is not Windows Remote Desktop Services, and it is not Amazon Relational Database Service. In the Linux kernel, RDS is a networking protocol family designed for reliable, ordered datagram delivery between nodes in a cluster. The kernel documentation describes RDS as using a single reliable connection between any two cluster nodes so applications can communicate without the connection explosion that would come from maintaining one connection-oriented socket per peer pair. (kernel.org)
That cluster-oriented design explains why many general-purpose servers never intentionally use RDS. It also explains why RDS often appears in security hardening baselines as something to disable unless needed. RDS is mainly relevant to specialized environments such as high-performance computing clusters, Oracle RAC-style deployments, and systems that deliberately rely on the RDS protocol family.
The practical exposure question is not simply “does the kernel source contain RDS code?” It is more specific:
| Question | なぜそれが重要なのか |
|---|---|
Is CONFIG_RDS enabled or built as a module? | Without RDS support, the vulnerable subsystem is unreachable. |
Is CONFIG_RDS_TCP enabled or built as a module? | The public exploit chain uses RDS TCP transport. |
Are rds そして rds_tcp present on disk? | A modular kernel config does not help the attacker if the modules are not packaged. |
| Are the modules already loaded? | Loaded modules remove one important gate. |
| Can an unprivileged user cause module autoload? | Some distributions prevent rare protocol modules from autoloading. |
Is io_uring available? | The public chain uses io_uring fixed buffers to convert the reference-count issue into a page-cache write. |
| Can the attacker reach a readable SUID-root binary? | The public payload model relies on corrupting cached bytes for a SUID executable. |
This is why distribution names alone are not enough. A stock desktop, a cloud image, a custom kernel, an HPC kernel, a hosting kernel, and a container host can have different answers even when they appear to run the “same” Linux version.
The exploit chain at a high level

The public PinTheft exploit chain is useful to understand, but defenders do not need to run it to assess exposure. The chain combines four ideas:
First, RDS supplies the reference-counting error. A failing zerocopy send can cause already pinned pages to be released incorrectly because cleanup accounting remains live after the failure.
セカンドだ、 io_uring supplies a long-lived handle to a user page through fixed buffers. The io_uring_register(2) manual describes registered resources such as user buffers and files as allowing the kernel to take long-term references or mappings so future I/O can avoid repeated setup overhead. (man7.org)
Third, the page allocator and page cache supply reuse. If a page is freed while something still holds a stale page pointer, later allocation can reuse the physical page for a different purpose. In PinTheft, the valuable reuse target is the page cache for a SUID-root executable.
Fourth, SUID supplies the privilege boundary. If a readable SUID-root binary’s cached bytes are replaced in memory with a small payload, the next execution can run those cached bytes with root privileges. V12’s README describes the public PoC as registering an anonymous page as an io_uring fixed buffer, draining its FOLL_PIN references through failing RDS zerocopy sends, freeing the page, reclaiming it as page cache for a SUID-root binary, and then using the stale fixed-buffer pointer to overwrite that page cache before executing the SUID target. (ギットハブ)
The conceptual chain looks like this:
| ステージ | What happens | Defender takeaway |
|---|---|---|
| Local code runs | The attacker can execute an unprivileged process on the host | This is not a remote unauthenticated entry point, but it matters wherever local code is not fully trusted. |
| RDS zerocopy failure is triggered | The bug releases pinned pages while leaving stale cleanup accounting | RDS reachability is the first major gate. |
io_uring fixed buffer retains page relationship | A long-lived registered buffer keeps the exploit useful after the RDS error path | kernel.io_uring_disabled is part of the exposure model. |
| Page references are drained | Repeated failure paths consume pin references | The bug is about page lifetime, not ordinary socket data. |
| Page is reclaimed as page cache | A freed page is reused for a SUID-root binary’s cached file content | Disk state and memory state can diverge. |
| Cached SUID content is overwritten | The stale fixed-buffer relationship writes attacker-controlled bytes into cached executable content | Integrity tooling that only checks disk may miss the transient memory effect. |
| SUID target is executed | The system runs the cached attacker-controlled bytes as root | Local privilege escalation becomes full host compromise. |
There is a reason this bug was named PinTheft. The public explanation says the name refers to stealing FOLL_PIN references until io_uring is left holding a stolen page pointer. (ギットハブ)
Page cache overwrite is the part defenders should not gloss over
Page cache is one of the reasons this vulnerability feels worse than a normal kernel crash bug. Linux caches file contents in memory so repeated reads do not always hit disk. If a kernel bug lets an attacker alter cached file bytes without changing the on-disk file, then two views of “the same file” can diverge: disk verification may look normal while execution observes poisoned cached contents.
Ubuntu’s PinTheft mitigation post states this directly: the vulnerability allows an attacker to replace in-memory contents of arbitrary files, while disk contents are not affected. Ubuntu also notes that programs that read a file, make changes, and write data back could make changes persistent, which matters for incident response and forensic assumptions. (Ubuntu)
The public PoC uses that property against SUID-root executables. SUID binaries are intentionally privileged: they run with the effective user ID of the file owner, often root. If a SUID executable’s cached first page is replaced with attacker-controlled code and then executed, the attacker crosses the local privilege boundary.
This does not mean a normal user can permanently rewrite /usr/bin/su on disk. The exploit class is subtler. It is a memory-backed integrity failure, and that subtlety changes detection:
| チェック | What it can tell you | What it may miss |
|---|---|---|
| Package version | Whether a known fixed kernel package is installed | Whether the running kernel is still old after update |
| File hash on disk | Whether the file stored on disk changed | Whether page cache contains poisoned bytes |
rpm -V または debsums | Whether package-managed files differ from package metadata | Transient in-memory page-cache overwrite |
lsmod | Whether RDS modules are currently loaded | Whether a module can be autoloaded later |
| Kernel config | Whether required features exist | Whether distribution policy blocks use |
| Process telemetry | SUID execution and suspicious child processes | Short-lived exploitation with limited logs |
For a live incident, “disk file looks clean” does not fully rule out memory-state abuse. A reboot can clear page cache state, but rebooting is not a root-cause fix. The kernel still needs to be patched or otherwise protected from the vulnerable path.
Who is actually exposed

A host should be treated as potentially exposed if all of the following are true:
- An attacker can run local unprivileged code.
- The running kernel contains the vulnerable RDS zerocopy code.
- RDS and RDS TCP are compiled in or available as loadable modules.
- について
rdsそしてrds_tcpmodules are loaded or can be loaded. io_uringis enabled for the attacker.- A readable SUID-root binary is available as a target.
- The kernel and architecture line up with the public exploit’s assumptions, or an attacker is capable of adapting the technique.
The last condition matters because public PoC compatibility is not the same as vulnerability existence. CloudLinux, for example, said its Ubuntu 22.04-based product uses the stock Ubuntu 22.04 kernel where the public PoC source does not compile against the 5.15 kernel headers because the PoC expects newer io_uring APIs, while also noting that Ubuntu’s default blocks unprivileged RDS autoload. (CloudLinux Blog)
This is a good model for defensive thinking. A public PoC may fail for several reasons:
| Failure point | Example reason |
|---|---|
| Compile-time mismatch | The kernel headers do not expose APIs the PoC expects. |
| Runtime feature missing | CONFIG_RDS または CONFIG_RDS_TCP is not set. |
| Module unavailable | rds_tcp.ko is not present on disk. |
| Module blocked | A modprobe policy maps rds または rds_tcp への /bin/false. |
io_uring blocked | kernel.io_uring_disabled prevents new rings. |
| SUID target unavailable | No readable SUID-root target is reachable in the attacker’s namespace. |
| Architecture mismatch | The public payload is x86_64-specific even if the technique is broader. |
| Vendor backport | The running kernel includes the fix despite an older-looking version string. |
The right answer is not “PoC fails, ignore the CVE.” It is “PoC failure is a signal that needs classification.” Is the host structurally safe, temporarily mitigated, patched, or merely incompatible with one public implementation?
Distribution status is nuanced
CVE-2026-43494 is a good example of why vendor advisory pages matter more than generic CVE summaries.
Ubuntu published a dedicated PinTheft mitigation post on May 21, 2026. Canonical said the vulnerability was publicly disclosed on May 19, 2026, fixed in the mainline Linux kernel tree, and assigned CVE-2026-43494. Ubuntu assessed the vulnerability as CVSS 3.1 score 7.8, but assigned Ubuntu Priority Medium because Ubuntu’s default configuration disables automatic loading of the affected RDS module through its rare-network protocol blacklist. The same post says Ubuntu kernel images on 20.04 LTS and later contain the vulnerable code, while 16.04 LTS and earlier do not, and that users who explicitly load RDS may be exposing the vulnerable path. (Ubuntu)
CloudLinux reached a different operational result for its own platforms. It said it tested the public PoC across CL7, CL7h, CL8, CL9, CL10, and CloudLinux for Ubuntu 22.04, and confirmed those platforms were not affected in default configuration. For the RHEL-based CloudLinux line, it said RDS is not compiled in. It also noted that CL9 and CL10 set kernel.io_uring_disabled=2, adding a second gate. (CloudLinux Blog)
Debian’s tracker shows why package-specific tracking matters. It lists Debian source package statuses by release: bullseye and bookworm entries are marked vulnerable in the tracker snapshot, trixie security is listed as fixed at 6.12.90-2, and sid is listed as fixed at 7.0.10-1. That is more precise than saying “Debian is vulnerable” or “Debian is fixed.” (security-tracker.debian.org)
SUSE rates the issue as important and shows multiple CVSS interpretations. SUSE’s page lists CVSS v3 base scores of 7.8 from CNA/Linux Kernel and 8.4 from SUSE, and also lists a CVSS v4 score of 7.3. It also shows released package versions for multiple SUSE products and container images. (suse.com) (suse.com)
GitHub’s advisory database lists CVE-2026-43494 as high severity with a CVSS 3.1 score of 7.8, but it also says affected versions and patched versions are unknown because it is not tied to a normal package ecosystem entry. That makes it useful for awareness, but not sufficient for Linux fleet remediation decisions. (ギットハブ)
A practical comparison looks like this:
| ソース | What it is good for | 制限 |
|---|---|---|
| NVD | Canonical CVE description, references, publication and modification dates | NVD enrichment may lag and may not provide a NVD-assigned score immediately |
| Ubuntu advisory and blog | Ubuntu-specific priority, default mitigation, kernel flavor status | Does not automatically apply to custom kernels or non-Ubuntu hosts |
| Debian tracker | Debian release and fixed-version tracking | Does not tell you whether your running kernel was rebooted into |
| SUSE CVE page | SUSE severity, CVSS, fixed package versions | Product-specific; not a general Linux answer |
| GitHub advisory | Broad security visibility and CVSS display | No supported package version mapping for kernel fleets |
| Scanner plugin | Finds hosts that need review | May rely on package presence rather than exploit reachability |
The safest operational habit is to use a scanner to find candidates, a vendor tracker to verify patch state, and host-level checks to decide exploitability.
How to check a Linux host safely
The following commands do not run an exploit. They help you answer whether the public PinTheft chain has the features it needs.
uname -a
uname -r
uname -m
grep -E 'CONFIG_(RDS|RDS_TCP|IO_URING)=' /boot/config-$(uname -r) 2>/dev/null || \
zgrep -E 'CONFIG_(RDS|RDS_TCP|IO_URING)=' /proc/config.gz 2>/dev/null || \
echo "kernel config not readable"
cat /proc/sys/kernel/io_uring_disabled 2>/dev/null || \
echo "kernel.io_uring_disabled sysctl not present"
lsmod | grep -E '^(rds|rds_tcp|rds_rdma)\b' || \
echo "RDS modules not currently loaded"
modprobe -n -v rds 2>&1 | head -5
modprobe -n -v rds_tcp 2>&1 | head -5
Interpret the results carefully:
| 結果 | 意味 |
|---|---|
CONFIG_RDS is not set | The RDS subsystem is not compiled in; the public RDS path is unreachable. |
CONFIG_RDS=m | RDS is modular; check whether the module exists and whether modprobe policy blocks it. |
CONFIG_RDS_TCP=m | RDS TCP is modular; the public chain still needs it loadable. |
CONFIG_IO_URING=y | io_uring is compiled in; now check the sysctl. |
kernel.io_uring_disabled=0 | All processes can create io_uring instances unless other controls apply. |
kernel.io_uring_disabled=1 | Unprivileged access is restricted depending on capabilities and io_uring_group. |
kernel.io_uring_disabled=2 | New io_uring_setup() calls are blocked for all processes on kernels supporting this sysctl. |
install rds /bin/false | A modprobe rule is blocking module load. |
Module not found | The module is not present for the running kernel. |
lsmod shows rds または rds_tcp | RDS code is loaded now; treat as higher urgency if the kernel is vulnerable. |
について kernel.io_uring_disabled values are important. The kernel sysctl documentation says io_uring_disabled=1 requires a process to be privileged or in the configured io_uring_group, while Red Hat’s release documentation describes 0 as normal access, 1 as disabled for unprivileged processes not in the allowed group, and 2 as disabled for all processes. (docs.kernel.org) (docs.redhat.com)
For a quick host-level audit, use a defensive script like this:
#!/usr/bin/env bash
set -euo pipefail
krel="$(uname -r)"
arch="$(uname -m)"
config="/boot/config-$krel"
echo "== Host =="
echo "Kernel: $krel"
echo "Architecture: $arch"
echo
echo "== Kernel feature gates =="
if [[ -r "$config" ]]; then
grep -E 'CONFIG_(RDS|RDS_TCP|IO_URING)=' "$config" || true
elif [[ -r /proc/config.gz ]]; then
zgrep -E 'CONFIG_(RDS|RDS_TCP|IO_URING)=' /proc/config.gz || true
else
echo "Kernel config not readable from $config or /proc/config.gz"
fi
echo
echo "== io_uring policy =="
if [[ -r /proc/sys/kernel/io_uring_disabled ]]; then
printf "kernel.io_uring_disabled="
cat /proc/sys/kernel/io_uring_disabled
else
echo "kernel.io_uring_disabled sysctl not available"
fi
echo
echo "== Loaded RDS modules =="
lsmod | awk '/^(rds|rds_tcp|rds_rdma)/ {print}' || true
echo
echo "== Dry-run module load policy =="
modprobe -n -v rds 2>&1 | head -5 || true
modprobe -n -v rds_tcp 2>&1 | head -5 || true
echo
echo "== Readable SUID-root binaries, first 20 =="
find / -xdev -perm -4000 -type f -readable -print 2>/dev/null | head -20 || true
echo
echo "== Reminder =="
echo "This script does not prove exploitation. It only checks major exposure gates."
Run it as root or with enough permissions to read kernel config and module policy. The script intentionally does not clone, compile, or execute any PoC. Its value is evidence collection: what kernel is running, what features exist, what modules can be loaded, whether io_uring is available, and whether SUID targets are visible.
A simple risk model for triage
A useful triage model has four buckets.
| Bucket | Host condition | アクション |
|---|---|---|
| Structurally not exposed | RDS is not compiled in, or required modules are absent and cannot be loaded | Record evidence, monitor vendor advisories, patch during normal kernel cycle |
| Mitigated but still patch | RDS module load is blocked or io_uring is disabled, but kernel package is still vulnerable | Keep mitigation, schedule kernel update, verify after reboot |
| Potentially exposed | RDS and RDS TCP are available, io_uring is enabled, and untrusted local code can run | Prioritize patching, apply compensating controls immediately, check for suspicious local activity |
| High operational risk | Shared host, CI runner, container host, HPC node, research platform, or shell server with local untrusted users and exposed gates | Emergency patch or isolate, disable RDS if unused, restrict io_uring, rotate and review privileged access after remediation |
The reason to separate “mitigated but still patch” from “structurally not exposed” is audit clarity. Blocking rds with modprobe policy is a compensating control. It is useful. It is not the same as having a kernel that no longer contains the vulnerable bug.
Patching and rebooting
The durable fix is a vendor-supported kernel update. For most production fleets, that means installing the fixed kernel package for the exact distribution, kernel flavor, cloud image, or appliance lineage, then rebooting into the fixed kernel unless a vendor-supported livepatch is available.
Check installed and running versions separately. On Debian or Ubuntu:
uname -r
dpkg -l 'linux-image*' | awk '/^ii/ {print $2, $3}'
apt list --upgradable 2>/dev/null | grep -E '^linux-(image|headers|modules)' || true
On RHEL-family systems:
uname -r
rpm -q kernel kernel-core kernel-modules kernel-modules-extra 2>/dev/null || true
dnf updateinfo list security --available 2>/dev/null | grep -i kernel || true
On SUSE-family systems:
uname -r
rpm -q kernel-default kernel-default-base kernel-rt 2>/dev/null || true
zypper list-patches --category security | grep -i kernel || true
On Arch Linux:
uname -r
pacman -Q linux linux-lts 2>/dev/null || true
pacman -Qu | grep -E '^(linux|linux-lts)\s' || true
Do not stop after installing packages. The running kernel remains the old kernel until the host boots into the new one, unless livepatching has actually applied the relevant fix. That matters for CVE-2026-43494 because the vulnerable code is in the kernel currently executing, not only in files sitting on disk.
For high-risk hosts, the patch sequence should be:
- Identify the running kernel.
- Check the vendor advisory for the exact fixed package.
- Install the update.
- Reboot or apply supported livepatch.
- Confirm
uname -rchanged or livepatch state is verified. - Re-run RDS and
io_uringexposure checks. - Keep temporary controls if RDS is not business-critical.
Temporary mitigation by blocking RDS
If the host does not need RDS, block it. This is the cleanest compensating control because the root bug is in the RDS path. V12, CloudLinux, Ubuntu, and security media all point to RDS availability as a primary exposure gate. (ギットハブ) (CloudLinux Blog) (Ubuntu) (ブリーピングコンピューター)
Use a modprobe policy like this:
sudo modprobe -r rds_tcp rds 2>/dev/null || true
cat <<'EOF' | sudo tee /etc/modprobe.d/disable-rds-pintheft.conf
install rds /bin/false
install rds_tcp /bin/false
blacklist rds
blacklist rds_tcp
EOF
sudo modprobe -n -v rds
sudo modprobe -n -v rds_tcp
After applying it, verify that a dry-run module load shows the blocking rule. Also check that nothing in production genuinely requires RDS. RDS may be rare on typical web, SaaS, CI, and shared-hosting systems, but it is not imaginary. HPC, clustered database, or specialized low-latency environments may have legitimate dependencies.
If RDS is already loaded, unloading it may fail if in use. Do not force-remove kernel modules on production systems without understanding the workload. In that case, prioritize kernel patching and maintenance-window planning.
Temporary mitigation by restricting io_uring
io_uring is not the root cause of CVE-2026-43494, but it is central to the public exploit conversion. If your workloads do not need it, disabling new io_uring instances can shrink the local kernel attack surface.
sudo sysctl -w kernel.io_uring_disabled=2
echo 'kernel.io_uring_disabled = 2' | \
sudo tee /etc/sysctl.d/99-disable-io-uring.conf
sudo sysctl --system
cat /proc/sys/kernel/io_uring_disabled
This control needs testing. Modern databases, storage-heavy workloads, language runtimes, and high-performance applications may use io_uring or attempt to use it before falling back to another I/O path. Red Hat’s documentation explicitly frames the sysctl as a way to prevent new io_uring instances and shrink the kernel attack surface, but operational compatibility still belongs to the local team. (docs.redhat.com)
A balanced rollout pattern is:
| Environment | Suggested approach |
|---|---|
Internet-facing app server with no known io_uring dependency | Disable io_uring, monitor for errors, keep RDS blocked |
| Database host | Test in staging first; look for fallback behavior and latency changes |
| Kubernetes worker | Test node pools separately; watch storage drivers, runtimes, and observability agents |
| CI runner executing untrusted code | Strong candidate for disabling io_uring and blocking RDS immediately |
| HPC or Oracle RAC-like environment | Do not assume RDS is unused; coordinate with platform owners |
If you must leave io_uring enabled, RDS module blocking becomes even more important.
Reducing SUID exposure
The public PinTheft chain targets a readable SUID-root binary. You should not respond to CVE-2026-43494 by randomly removing SUID bits across the fleet, but you should know what SUID surface exists.
find / -xdev -perm -4000 -type f -print 2>/dev/null | sort
For each SUID binary, ask:
| Question | なぜそれが重要なのか |
|---|---|
| Is this binary still needed? | Old SUID utilities often remain after workload changes. |
| Is it package-managed? | Package updates may restore permissions. |
| Can capabilities replace SUID? | Some tools only need a narrow capability, not full root EUID. |
| Is it reachable from containers or restricted shells? | Namespace and filesystem visibility affect exploit targeting. |
| Is execution monitored? | SUID execution is a high-signal event in many environments. |
Do not treat SUID reduction as the primary fix. It is defense-in-depth. The primary fix remains the kernel update or blocking the vulnerable path.
Containers and cloud hosts
Local privilege escalation vulnerabilities are often more serious in cloud and container environments than the word “local” suggests. A public SaaS server may not intentionally give shell accounts to strangers, but it may still execute untrusted code through image builds, CI jobs, customer plugins, notebook environments, data science sandboxes, browser automation, serverless-style workers, or compromised application processes.
Containers share the host kernel. That means a kernel LPE cannot be evaluated only by looking inside the container image. The host kernel config, host module policy, host io_uring sysctl, container seccomp profile, capabilities, namespace setup, and visible filesystem targets all matter.
Ubuntu’s PinTheft post was careful on this point: it said the impact in containerized environments is unclear, noting that an attacker in a container might not be able to escape by itself, but could potentially corrupt data for other containers or the host depending on shared storage and target visibility. (Ubuntu)
For Kubernetes and container platforms, add these checks:
# On the node, not just inside a pod
uname -r
cat /proc/sys/kernel/io_uring_disabled 2>/dev/null || true
lsmod | grep -E '^(rds|rds_tcp|rds_rdma)\b' || true
modprobe -n -v rds_tcp 2>&1 | head -5
# Review seccomp and capabilities for workloads that run untrusted code
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.securityContext.seccompProfile.type}{"\n"}{end}' 2>/dev/null
In container-heavy environments, prioritize nodes that run untrusted workloads: public CI runners, build farms, shared notebook clusters, plugin execution hosts, browser sandbox infrastructure, security labs, and customer-controlled compute.
Detection and investigation
CVE-2026-43494 is not easy to detect purely through file integrity monitoring because the public chain targets in-memory page cache. You should combine configuration evidence, module telemetry, process behavior, and kernel update state.
High-signal events include:
| 信号 | なぜそれが重要なのか |
|---|---|
Unexpected load of rds, rds_tcpあるいは rds_rdma | RDS is uncommon on many general-purpose hosts. |
New io_uring_setup activity from unusual users | The public chain depends on io_uring. |
| Unusual SUID binary execution | The public chain executes a SUID-root target after poisoning cache. |
| SUID binary spawning an unexpected shell | Strong post-exploitation signal. |
| Kernel warnings or oops around RDS or page accounting | May indicate failed attempts or instability. |
| Local users running short-lived binaries from writable directories | Common exploit staging behavior. |
Example auditd rules for temporary monitoring:
sudo auditctl -a always,exit -F arch=b64 -S init_module -S finit_module -k module-load
sudo auditctl -a always,exit -F arch=b64 -S io_uring_setup -k io-uring-setup
sudo auditctl -w /usr/bin/su -p x -k suid-exec
sudo auditctl -w /usr/bin/passwd -p x -k suid-exec
sudo auditctl -w /usr/bin/mount -p x -k suid-exec
sudo auditctl -w /usr/bin/pkexec -p x -k suid-exec
These rules are not magic. They can be noisy, and paths vary by distribution. They are most useful during a response window when you need higher visibility on hosts you cannot patch immediately.
For eBPF or EDR-backed environments, look for the same behavior at a higher level: module load attempts, io_uring_setup, repeated SUID execution, unexpected root shells, and processes that rapidly exercise unusual protocol families. Do not rely on one log source.
If you suspect exploitation, treat the host as compromised. A local kernel LPE gives the attacker root. That means you should preserve evidence, isolate the host, rotate credentials and secrets accessible from the host, review persistence mechanisms, and rebuild where appropriate. A kernel patch removes the vulnerability; it does not undo root-level attacker actions already taken.
Scanner findings and false confidence
Vulnerability scanners are useful for CVE-2026-43494, but only if their output is interpreted as a starting point.
A scanner can tell you that a kernel package is associated with a vulnerable advisory. It may not know:
- Whether the running kernel is the same as the installed kernel package.
- Whether RDS is compiled in.
- Whether
rds_tcpis packaged on that host. - Whether a modprobe blacklist blocks module load.
- Whether
kernel.io_uring_disabledprevents the public chain. - Whether the host runs untrusted local code.
- Whether the vendor has backported a fix without changing the upstream-looking version string.
Tenable’s plugin language illustrates this limitation: it describes Linux or Unix hosts with packages impacted by a vulnerability without a vendor-supplied patch available and notes that Nessus relies on package presence as reported by the vendor. That is valid scanner behavior, but it is not the same as exploitability proof. (Tenable®)
A good remediation ticket for CVE-2026-43494 should include:
| エビデンス | 例 |
|---|---|
| Running kernel | uname -r output |
| Vendor status | Link or reference to Ubuntu, Debian, SUSE, Red Hat, Arch, CloudLinux, or cloud image advisory |
| Kernel config | RDS, RDS TCP, and io_uring values |
| Module policy | modprobe -n -v rds そして rds_tcp output |
io_uring 状態 | /proc/sys/kernel/io_uring_disabled |
| SUID surface | Summary count and notable targets |
| Patch action | Kernel package installed and reboot/livepatch status |
| Compensating controls | RDS block, io_uring restriction, workload isolation |
| Residual risk | Whether untrusted local code can run |
This is also where authorized automated validation can help. For a vulnerability like CVE-2026-43494, the useful automation is not “run public root exploit everywhere.” It is repeatable evidence collection: confirm feature gates, map affected hosts, verify mitigations, preserve command output, and generate a reviewable record for security and operations teams. In an authorized workflow, Penligent can be used to structure this kind of validation and reporting around real host evidence rather than one-off notes, especially when teams need to correlate CVE status, configuration checks, mitigation proof, and retest results across a fleet. The broader product context is available from Penligent’s main site, while its dedicated PinTheft write-up gives a focused technical summary of the same RDS-to-page-cache chain. (寡黙) (寡黙)
Why CVSS alone is not enough
CVE-2026-43494 shows the limits of single-number severity.
GitHub’s advisory page displays a CVSS 3.1 score of 7.8 with local attack vector, low attack complexity, low privileges required, no user interaction, and high confidentiality, integrity, and availability impact. SUSE shows CNA/Linux Kernel CVSS v3 at 7.8 and SUSE’s own v3 score at 8.4, while NVD’s own enrichment may lag behind public vendor scoring. Ubuntu assessed CVSS 3.1 as 7.8 High but assigned Ubuntu Priority Medium because default Ubuntu configuration blocks automatic loading of the affected RDS module. (ギットハブ) (suse.com) (Ubuntu)
Those differences are not contradictions in the casual sense. They answer different questions:
| Scoring view | Question it answers |
|---|---|
| CVSS base score | If the vulnerable path is reachable, how severe are the technical consequences? |
| Vendor priority | How urgent is this for that vendor’s default supported configuration? |
| Scanner severity | How should this plugin or product categorize the finding? |
| Fleet priority | Which of your actual hosts should be remediated first? |
For fleet owners, the last question matters most. A host that runs untrusted CI jobs with RDS loadable and io_uring enabled may deserve emergency treatment. A host where RDS is not compiled in is not in the same category, even if a generic scanner raises a package-based finding.
Related Linux page-cache and local-root CVEs
PinTheft belongs in a broader family of Linux local privilege escalation bugs where memory lifetime, file caching, and privilege boundaries meet. The root causes differ, but the defensive lesson is similar: performance-oriented kernel paths can become privilege-escalation surfaces when local users can manipulate object lifetime or cached file state.
| CVE | Public name | Relevant similarity | Important difference |
|---|---|---|---|
| CVE-2016-5195 | Dirty COW | Local users could gain privileges by abusing incorrect copy-on-write handling for read-only memory mappings | Race in memory management and COW behavior, not RDS or io_uring |
| CVE-2022-0847 | 汚れたパイプ | Unprivileged local users could write to page cache backed by read-only files and escalate privileges | Pipe buffer flag initialization flaw, not RDS zerocopy |
| CVE-2026-31431 | Copy Fail | Linux kernel local privilege escalation through page-cache corruption and SUID-root impact | AF_ALG and splice() path, not RDS and io_uring fixed buffers |
NVD describes Dirty COW as a Linux kernel race condition in copy-on-write handling that allowed local users to gain privileges, and it describes Dirty Pipe as a flaw in pipe buffer initialization that allowed an unprivileged local user to write to page-cache pages backed by read-only files. Ubuntu’s Copy Fail post describes CVE-2026-31431 as a Linux kernel LPE in algif_aead, with CVSS 3.1 score 7.8 and affected Ubuntu releases before 26.04. (nvd.nist.gov) (nvd.nist.gov) (Ubuntu)
The common pattern is not “all these bugs are the same.” They are not. The common pattern is that local kernel attack surface is broader than traditional network exposure. A bug in a rarely used protocol, a crypto socket path, a pipe buffer, or copy-on-write behavior can become a root boundary problem if local untrusted code can trigger the right sequence.
Secure-by-default lessons from PinTheft
CVE-2026-43494 reinforces several hardening lessons that are bigger than one CVE.
Disable rare kernel subsystems unless you need them. RDS may be essential in some clusters, but it is unnecessary on many web servers, CI nodes, desktops, and container hosts. Ubuntu’s default rare-network blacklist and CloudLinux’s decision not to compile RDS in many kernels both show how default-off decisions can materially reduce emergency exposure. (Ubuntu) (CloudLinux Blog)
Restrict unprivileged access to high-risk kernel interfaces. io_uring is powerful and useful, but it has a history of attracting security scrutiny because it exposes complex asynchronous kernel behavior to local processes. The kernel added io_uring_disabled specifically to let administrators and distributions restrict creation of new rings and shrink local attack surface. (lwn.net) (docs.kernel.org)
Treat local code execution as a security boundary. Many environments still think of local user code as low risk. That assumption fails in shared runners, build workers, browser automation hosts, notebook services, plugin systems, university labs, multi-user HPC nodes, and container platforms. A local kernel LPE turns a weak local boundary into host compromise.
Build evidence-driven patch workflows. Kernel CVEs often involve backports, multiple kernel flavors, delayed reboots, custom configs, cloud images, and vendor-specific mitigations. The only reliable workflow is to collect running-kernel evidence and verify the controls actually in effect.
Common mistakes to avoid
Do not assume “RDS” means Windows Remote Desktop Services. In this CVE, RDS means Linux Reliable Datagram Sockets.
Do not assume package presence equals exploitability. Package version is one signal. Kernel config, module loadability, blacklist policy, io_uring status, and local code execution all matter.
Do not assume PoC failure equals safety. Public PoCs can fail because of header mismatch, architecture mismatch, missing APIs, or distro-specific packaging. A failed PoC must be classified, not ignored.
Do not run public root exploits on production systems to “confirm” exposure. For CVE-2026-43494, defenders can collect the relevant gates safely. Running a page-cache corruption exploit can damage system state, alter privileged execution, and create incident-response ambiguity.
Do not rely only on disk integrity checks. Page-cache corruption can be transient and memory-backed.
Do not disable io_uring blindly across critical performance workloads. Test. Some applications will fall back cleanly; others may show warnings or performance impact.
Do not leave compensating controls undocumented. If you block RDS or restrict io_uring, record the command output and retest after reboot or kernel updates.
Practical remediation playbook

For most organizations, the playbook should look like this:
| ステップ | アクション | Evidence to keep |
|---|---|---|
| 1 | Identify all Linux hosts and kernel flavors | Asset inventory and uname -r |
| 2 | Prioritize hosts that run untrusted local code | CI, containers, shared shells, labs, plugin workers |
| 3 | Check RDS, RDS TCP, and io_uring gates | Kernel config, lsmod, modprobe -n, sysctl output |
| 4 | Apply vendor kernel update | Package manager transaction logs |
| 5 | Reboot or verify livepatch | New running kernel or livepatch status |
| 6 | Block RDS if not required | /etc/modprobe.d rule and dry-run output |
| 7 | Restrict io_uring if compatible | Sysctl value and workload validation |
| 8 | Review SUID surface | Inventory and changes |
| 9 | Monitor for suspicious local behavior | Module loads, SUID execution, root shells |
| 10 | Close ticket only after retest | Before and after evidence |
A remediation ticket that says “patched” but still shows the old running kernel is incomplete. A ticket that says “not affected” without RDS and io_uring evidence is weak. A ticket that says “PoC failed” without explaining why is not enough.
よくあるご質問
Is CVE-2026-43494 remotely exploitable?
- No, the public PinTheft chain is a local privilege escalation, not a remote unauthenticated network exploit.
- The attacker needs a way to execute local unprivileged code first.
- It still matters on shared hosts, CI runners, container nodes, research systems, HPC clusters, student labs, and any system where local code is not fully trusted.
- A compromised web application or service account can also turn “local only” into a serious host risk.
Does PinTheft affect every Linux server?
- No.
- The public chain needs RDS and RDS TCP support, module loadability, usable
io_uring, and a readable SUID-root target. - Some distributions or products are protected by default configuration, missing modules, disabled autoload, or disabled
io_uring. - You should verify the running host rather than assume based on distribution name alone.
How do I check whether my host can reach the vulnerable RDS path?
- Check kernel config for
CONFIG_RDSそしてCONFIG_RDS_TCP. - Check whether
rds,rds_tcpあるいはrds_rdmaare loaded withlsmod. - 用途
modprobe -n -v rdsそしてmodprobe -n -v rds_tcpto see whether module load is blocked or possible. - チェック
/proc/sys/kernel/io_uring_disabledto determine whether the publicio_uringpart of the chain is available. - Record the running kernel with
uname -r, not only the installed package version.
Should I disable io_uring everywhere?
- Not automatically.
- Disabling
io_uringcan reduce kernel attack surface and can break or slow workloads that depend on modern async I/O behavior. - CI runners, shared execution nodes, and hosts without known
io_uringdependencies are strong candidates for restriction. - Database, storage, and high-performance application hosts should be tested before a broad rollout.
- もし
io_uringmust remain enabled, blocking unused RDS modules becomes more important.
Is blocking RDS enough?
- Blocking RDS can prevent the public exploit path when RDS is not needed.
- It is a compensating control, not a root-cause patch.
- You should still install the vendor-fixed kernel and reboot or verify livepatch.
- Do not block RDS blindly on hosts that genuinely use it for cluster communication.
Can CVE-2026-43494 be used for container escape?
- Do not assume a universal yes or no.
- Containers share the host kernel, so a host kernel vulnerability can be relevant from inside a container.
- Exploitability depends on namespace setup, seccomp, capabilities, module availability,
io_uring, visible SUID targets, and storage sharing. - Treat container hosts that run untrusted workloads as high-priority for patching and mitigation.
Why do vendors rate the same bug differently?
- CVSS describes technical severity when the vulnerable path is reachable.
- Vendor priority also considers default configuration, module availability, packaging, and supported product context.
- Ubuntu, for example, assessed a high CVSS score but assigned Medium priority because default configuration blocks automatic loading of the affected RDS module.
- SUSE shows its own severity and package-specific fixed versions.
- Your fleet priority should combine vendor guidance with actual host exposure.
Is it safe to validate by running the public PoC?
- Do not run a public root exploit on production systems.
- PinTheft-style page-cache manipulation can alter live privileged execution state and create cleanup risk.
- Use configuration checks, module policy checks, package status, and controlled lab reproduction instead.
- If exploit reproduction is necessary, keep it in an isolated disposable lab that matches the target kernel and distribution conditions.
CVE-2026-43494 is dangerous when its gates line up. It is also narrow enough that disciplined teams can triage it accurately. The right response is not fear and not dismissal. Identify hosts where local untrusted code can run. Verify RDS and RDS TCP reachability. Check io_uring. Patch the running kernel. Reboot or verify livepatch. Block RDS if it is unused. Restrict io_uring where compatible. Keep evidence.
PinTheft is a reminder that modern Linux exploitation is often a subsystem chain, not a single dramatic bug. RDS provides the reference-counting mistake. io_uring provides a long-lived fixed-buffer relationship. Page cache provides the execution target. SUID provides the privilege boundary. Break any required gate and the public chain fails; patch the kernel and the root cause is gone.

