Arch Linux PinTheft patch validation steps
Confirm the Arch-specific attack surface is actually present
Start with the boring part: whether RDS is even loaded. PinTheft needs the Linux kernel RDS subsystem, and the default exposure on Arch Linux is the awkward bit that makes this worth checking in the first place. If rds or rds_tcp are not loaded, the path is already closed for normal local abuse.
Check the loaded modules and the module install rules:
bash
lsmod | grep -E ‘^rds|^rdstcp’
modinfo rds 2>/dev/null
modinfo rdstcp 2>/dev/null
On a hardened host, blocking the modules is cleaner than hoping nobody loads them later. A simple mitigation is to make module loading fail through modprobe policy:
conf
install rds /bin/false
install rds_tcp /bin/false
Place that in /etc/modprobe.d/pintheft.conf and then remove any already loaded modules:
bash
sudo rmmod rds_tcp rds
If rds is already resident, the attack surface exists before anyone touches the exploit path. That is the bit worth fixing first.
Reproduce the patched behaviour without chasing the exploit path
A safe validation pass should look for the patched behaviour, not for a crashy local root trick. The useful question is simple: does the kernel still accept the old sequence of module state and buffer handling, or does it now shut down the conditions that made the double-free possible?
Check whether io_uring is available and whether the host still exposes the basic ingredients that PinTheft depended on. The exploit needed a readable SUID-root binary, x86_64 support for the payload, and io_uring with fixed buffers. If those pieces are absent, the local path shrinks further, though that is not a patch check by itself.
A sane regression pass stays on the host and watches for the patched failure mode. You are looking for:
- no crash in the RDS send path
- no double release of pinned pages
- no stale module state after a failed zerocopy send
- no unexpected behaviour in
io_uringfixed buffer handling
If the patched kernel rejects the old path cleanly, that is the outcome you want. If it still behaves as though the notifier and scatterlist cleanup are out of sync, the fix has not landed cleanly enough for comfort.
Check the module state, kernel build, and mitigation hooks
Patch validation gets messy when the running kernel and the installed kernel do not match, which happens often enough to be irritating. Confirm the exact build you are testing, then check that the fix commit or vendor backport is present in that build. A patched date alone is not enough if the booted kernel is old or the module set came from elsewhere.
Use the host’s own package and boot metadata to verify:
bash
uname -r
cat /proc/version
pacman -Q linux
Then check the mitigation hooks around the module:
bash
grep -R “install rds” /etc/modprobe.d /usr/lib/modprobe.d 2>/dev/null
grep -R “install rds_tcp” /etc/modprobe.d /usr/lib/modprobe.d 2>/dev/null
If the host relies on policy to block the modules, that policy matters as much as the kernel patch. A fixed kernel with an unfettered module load path still leaves room for local abuse. It is a small window, but attackers only need the small ones.
Validate the fix with a safe regression pass on the host
A safe regression pass should be dull. Load the normal system state, confirm the mitigation is active, then exercise only non-destructive checks against the relevant services. Do not use public proof-of-concept exploit code on a production box just to prove a point to yourself. That is how people end up explaining a pager alert at 02:00.
A practical pass looks like this:
- Confirm
rdsandrds_tcpare blocked or absent. - Confirm the running kernel is the patched build.
- Confirm
io_uringstill behaves normally for ordinary workloads. - Confirm no unexpected kernel warnings appear when routine apps run.
- Reboot and re-check module state, since a one-off
rmmodis not a fix.
If the system stays stable, the module stays absent, and the patched kernel build matches the running host, the fix is doing its job. If RDS can still appear on demand, the host still has a local privilege escalation path sitting in the kernel, just waiting for somebody with too much curiosity and not enough sleep.




