
Research artifacts for file-notification side-channel attacks on Linux, Windows, and macOS, demonstrating inotify/FSEvents leakage, keystroke timing, and website fingerprinting.
This repository contains the (still in review!) artifacts for the paper "File Notification Attacks: Templating and Exploiting Side-Channel Leakage from the File-Notification Systems on Linux, Windows, and macOS", accepted at CCS '26.
Visit the website with demos at: https://inoti.fyi/
Read the paper at: https://snee.la/pdf/pubs/file-notification-attacks.pdf or http://inoti.fyi/pubs/file-notification-attacks.pdf
As a part of artifact evaluation at CCS'26 (still ongoing!), we shipped a Debian 13 + KDE Plasma 6 VM with a pre-patched kernel. This VM was not used to produce the paper's evaluation results and is not intended to reproduce their exact magnitude. This repository may be updated to incorporate reviews and feedback from our artifact evaluators. We will make the VM publicly accessible when our artifact evaluation is completed.
We employed Claude (Opus 4.8) for wrapping our code into decently well-documented and high-performant artifacts (for example, the Windows one was a bit laggy). However, the code, scripts, makefiles it generated were based on
The instructions for testing Linux code below is specific to running commands in
the VM. Please look at the code instead in Linux/.
The VM exists purely for convenience, so that mounting each attack does not require a from-scratch environment setup or kernel downgrade. The underlying mechanism demonstrated in the VM is identical to the one described in the paper, but please note that we did not use the VM to produce the numbers reported in the paper. Absolute timings may differ due to the virtualized environment and underlying hardware.
Findings are reproduced inside a Debian 13 VM (linux-vm/), installed from the
official live Debian ISO with KDE Plasma 6 (Wayland) installed with a kernel
that predates the fsnotify
fix.
inotify-tools, Qt6 dev headers, and pkexec are installed. Nothing else is
upgraded, and the kernel is never touched after install. Please DO NOT run
apt upgrade or attempt to upgrade the kernel. This VM image is
deliberately old, is not up to date, and does not have the latest security
patches. This VM image is only meant for quick validation and testing!
The code, attacks, and demonstrations located within the VM are mirrored in
Linux/.
Note: We mention as which user to run the commands at the top of each
command block. There is the [host], which is the host machine which runs the
VM, [user] which is the victim of the attacks in the VM, and [spyuser] which
requires to be set up and will be the attacker in most Linux attacks.
The disk image is shipped as linux-vm-upload.qcow2, compressed with zstd.
Rename it to linux-vm.qcow2 before running run.sh (which expects that
filename):
# Run As: [host]
cd linux-vm/
mv linux-vm-upload.qcow2 linux-vm.qcow2
./run.sh
Reading zstd-compressed qcow2 requires qemu-img/qemu-system-x86_64 version
5.2 or newer (2020+), check with qemu-img --version. If you're stuck on an
older QEMU and it fails to open the image, decompress it into a flat qcow2
first:
qemu-img convert -O qcow2 linux-vm-upload.qcow2 linux-vm.qcow2
4 cores, 4GB RAM, GUI display. Logins are:
root, password password,user, password password,spyuser, password password (do not login as spyuser!)The supplied VM already runs a vulnerable, pre-patched kernel
(6.12.43+deb13-amd64), so no downgrade is needed to use it. You will need QEMU
to run this image (which has a GUI). The artifact lives at
/home/user/Linux-File-Notification-Attacks inside the VM.
One command sets things up fresh in the VM: (i) an unprivileged spyuser
account (non-sudo), (ii) its own copy of the artifact directory (a separate
unprivileged account cannot traverse into user's home directory otherwise),
(iii) and every script made executable in both copies.
# In the VM, Run As: [user]
sudo bash ~/Linux-File-Notification-Attacks/setup_attacks.sh
Every attack below runs as spyuser (su - spyuser, password password),
except auth-ui-redress, which runs as user (explained below).
Proves file-operation notifications are delivered on files that cannot be read directly, as long as their parent directory is readable.
# Run As: [spyuser]
# To switch to spyuser, in a new terminal type `su - spyuser`. The password
# is `password`.
cd ~/Linux-File-Notification-Attacks/unreadable-file-bypass
./watch-syslog.sh
Leave it running, then generate a log line from another terminal as user:
# Run As: [user]
logger "hello"
This Debian 13 image has no rsyslog, so there is no /var/log/syslog file as
shown in the paper. The script falls back to watching
/var/log/journal/<machine-id>/ instead. This is the same idea, as the
.journal files being monitored are owned by root (user) and
systemd-journal (group), neither of which are spyuser.
Measures inotify's notification delay.
# Run As: [user], ensure numpy is installed (or pip3)
sudo apt install python3-numpy
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/temporal-resolution
./run.sh
watcher opens an inotify watch on a test file and timestamps every IN_ACCESS
it receives. accessor reads that same file 1000 times with a random 5-10ms
delay between reads, timestamping each read itself. stats.py diffs the two
timestamp recordings and prints the average/stddev/min delay between the read
happening and the notification arriving, i.e. the temporal resolution of
inotify.
Not the full attack from the paper, but just the filtering proof-of-concept
primitive that the attack is built on: for every key pressed anywhere on the
system, print one timestamped notification, without ever reading /dev/input
directly.
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/inter-keystroke-timing
make
./find-keyboard.sh
Type in any window (maybe a new terminal as user). Each keystroke prints one
KEYPRESS line. The suppression window (which we heuristically chose for this
demonstration is 130ms) merges several IN_ACCESS events generated by a single
physical key press. In practice, we have noticed that this window is different
for different hardware (e.g., mechanical keyboards, typing styles).
If auto-detection picks the wrong device (or none), check
/proc/bus/input/devices and run it directly with ./build/keystroke-notify /dev/input event4.