Skip to content

PinTheft (PSA-2026-00022-1) — detection + mitigation

PinTheft is a local privilege-escalation chain that combines a double-free in the Linux kernel’s RDS (Reliable Datagram Sockets) module with an io_uring fixed-buffer overwrite to escalate any unprivileged user to root. Disclosed as PSA-2026-00022-1 on 2026-05-19; affects every current Proxmox kernel and most stock Linux distributions with the rds modules built. No upstream patched kernel is in distro repos yet at the time of this writing.

LayerWhat
InventoryAgent ships /proc/modules per inventory cycle to POST /api/v1/kernel-modules. Schema 103.
DetectionPer-tenant seeded rule kernel_module_suspicious matches rds, rds_tcp, rds_rdma against the loaded set. Hits raise a detected_events row with severity critical.
MitigationOperator-triggered, TOTP-gated Emergency Action pintheft_mitigate. Wrapper script drops /etc/modprobe.d/pintheft.conf (with install <mod> /bin/false + blacklist) and rmmod any currently loaded RDS modules. Idempotent.

Per the human-in-the-loop principle, monsys does not automatically unload modules. The detection fires; the operator reviews the detection event; the operator signs an EAT via TOTP; the agent executes.

Why this is safe to ship as a default rule

Section titled “Why this is safe to ship as a default rule”

On Ubuntu 24.04 the blacklist-rare-network.conf shipped with the distro already neuters socket(AF_RDS, ...) auto-loading via alias net-pf-21 off. An unprivileged attacker can therefore not load the module via the syscall trick — but a hostile cron job, a buggy installer, or an admin who runs modprobe rds for unrelated reasons can. The detection covers all those cases by polling /proc/modules. The mitigation closes off the install directive path that blacklist-rare-network.conf does not.

Note: the PinTheft mitigation does not need to wait for a patched kernel — RDS is unused on every Belgian/EU production server I’ve audited. If the operator needs RDS for legitimate reasons (some IBM DB2 RAC clusters and a tiny set of HPC setups), keep the detection on and accept the alert as an informed exception.

The seed row (per tenant, automatically inserted on mig 103 apply):

{
"module_names": ["rds", "rds_tcp", "rds_rdma"],
"advisory": "PSA-2026-00022-1",
"description": "rds + io_uring double-free chain → local privilege escalation. Unload and blacklist if unused."
}

The same rule kind (kernel_module_suspicious) will be reused for future kernel-LPE disclosures — only module_names changes per CVE.

{
"kind": "pintheft_mitigate"
}

No parameters: this action always blacklists rds, rds_tcp, rds_rdma. The wrapper at /usr/local/sbin/monsys-pintheft-mitigate is the only path with sudo NOPASSWD; it writes /etc/modprobe.d/pintheft.conf and calls rmmod for each currently loaded module. Output (stdout + stderr) is captured and shipped back to the hub as the EAT result for the audit log.

After the EAT lands:

Terminal window
lsmod | grep -E '^rds|^rds_tcp|^rds_rdma' # should be empty
sudo modprobe -nv rds # should print "install /bin/false"
cat /etc/modprobe.d/pintheft.conf # should contain blacklist+install lines

The next agent inventory cycle re-ships /proc/modules. With RDS absent the detection rule no longer matches, and the previous open detected_events row is auto-aged (the in-line dedup window stays at 24h; closing the open finding is operator-driven via dashboard ack).

ISO 27001 A.8.7 (Protection against malware) — auto-evaluated by counting unacknowledged kernel_module_suspicious events per tenant. The control row was added to compliance_framework_controls in mig 103.