DF-4454 / fix_iter1_panic.txt
FIX VALIDATION ITERATION 1 — patched-kernel panic (author's fix bug, NOT the original bug) The first version of fix.diff had a use-after-free of the *client* in evdev_dtor(): it called evdev_unref(client->ec_evdev) AFTER kfree(client), reading the ec_evdev field from freed client memory. Closing the stale fd (kill -9 of the PoC) panicked: Fatal user address access from kernel mode from evdev_uaf at ffffffff809cc5e0 Fatal trap 12: page fault while in kernel mode cpuid = 2; lapic id = 2 fault virtual address = 0x2b0 fault code = supervisor read data, page not present instruction pointer = 0x8:0xffffffff809cc5e0 stack pointer = 0x10:0xfffff8011868d600 frame pointer = 0x10:0xfffff8011868d618 code segment = base 0x0, limit 0xfffff, type 0x1b processor eflags = interrupt enabled, resume, IOPL = 0 current process = 894 kernel: type 12 trap, code=0 Stopped at evdev_unref: movl 0x2b0(%rdi),%eax (0x2b0 is offsetof(struct evdev_dev, ev_refs); rdi==NULL because the freed client block read back zeros.) Fix iteration 2 captures `struct evdev_dev *evdev = client->ec_evdev` BEFORE kfree(client). The positive result of this iteration: on the patched kernel the stale write(2) aborted immediately with ENODEV after device_del (baseline: full 64 MB write succeeded through the dangling pointer), and no magic events crossed to the re-added device (the reader blocked with zero events, baseline: 2-19 magic events per run).