Use-after-free of shared udev event dictionary in udev_event_externalize (multi-reader)
| Field | Value |
|---|---|
| ID | DF-0055 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-416 Use After Free |
| File | sys/kern/kern_udev.c |
| Lines | 571 (release), 540 (clean predicate), 566 (re-deref) |
| Area | kern |
| Confidence | certain |
| Discovered | 2026-06-29 |
| Reported | pending |
Summary
The udev event queue replicates every event to all openers via a per-softc
marker system. udev_event_externalize() calls
prop_object_release(ev->ev.ev_dict) (:571) the first time any reader
externalizes an event, freeing the shared proplib dictionary while the event
remains on udev_evq. The field is never NULLed, so
udev_clean_events_locked() (:540, predicate ev_dict != NULL) treats the
freed event as still-live and refuses to reap it. The next reader's marker-walk
finds the same event (dangling, non-NULL ev_dict, so the skip loop does not
skip it) and calls udev_event_externalize() again, which passes the freed
pointer into prop_dictionary_setβprop_object_retain(freed) (:566) β a
use-after-free on a kernel proplib object. Gated by /dev/udev 0600 root:wheel
(:1039-1041).
Root cause
/* udev_event_externalize :566-571 */
if (prop_dictionary_set(dict, "evdict", ev->ev.ev_dict) == false) { ... }
prop_object_release(ev->ev.ev_dict); /* :571 frees the shared dict; never NULLed */
/* udev_clean_events_locked :539-540 */
while ((ev = TAILQ_FIRST(&udev_evq)) && ev->ev.ev_dict != NULL) { /* dangling != NULL -> not reaped */
After the first reader's externalize: the temp dict's retain (+1) and the
event's release (-1) leave the dict at refcount 1 (held by temp); when temp is
released (:575), the dict hits 0 and is freed. ev->ev.ev_dict is now
dangling. The second reader's externalize (:566) passes the dangling pointer
to prop_dictionary_set β UAF.
Threat model & preconditions
- Attacker position: root or wheel (via
/dev/udev0600). - Privileges gained or impact: kernel heap corruption β reliable local kernel panic (DoS); with heap grooming, potential further exploitation (the freed proplib object is reused by the allocator). No direct confidentiality/integrity impact beyond corruption.
- Required config or capabilities:
/dev/udevaccess (root/wheel); device attach/detach activity generating events. - Reachability: two readers (two fds/processes) on
/dev/udev, both initiated, reading while events are generated.
Proof of concept
PoC source: findings/poc/DF-0055/udev_uaf.c
Build & run (root/wheel, disposable VM)
cc -o udev_uaf findings/poc/DF-0055/udev_uaf.c ./udev_uaf # trigger device events (USB/disk attach/detach) in parallel
Expected output
Kernel panic (heap corruption) when the second reader hits an event whose dict the first reader already externalized.
Impact
Kernel UAF reachable by root/wheel via two concurrent readers + device events. Medium (UAF = potential corruption/DoS; root/wheel prerequisite bounds the privilege gain).
Recommended fix
Move the final prop_object_release to udev_clean_events_locked (which owns
the single release + NULL), and remove the release from
udev_event_externalize so each reader borrows the dict (net-zero retain):
--- a/sys/kern/kern_udev.c
+++ b/sys/kern/kern_udev.c
@@ -540 +540,3 @@
ev->ev.ev_dict != NULL) {
+ prop_object_release(ev->ev.ev_dict);
+ ev->ev.ev_dict = NULL;
TAILQ_REMOVE(&udev_evq, ev, link);
@@ -571
- prop_object_release(ev->ev.ev_dict);
References
sys/kern/kern_udev.c:566,571β the release-without-NULL in externalize.sys/kern/kern_udev.c:539-540β theev_dict != NULLclean predicate.- CWE-416 Use After Free.
Timeline
- 2026-06-29 Discovered during automated file-by-file audit of
sys/kern/kern_udev.c. - pending Reported to DragonFlyBSD security contact.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0055 Β· 18 files| File | Type | Description | Size | |
|---|---|---|---|---|
| udev_uaf.c | trigger-source | two-forked /dev/udev readers + tap create/destroy event generator; deterministic UAF trigger | 5.6 KB | view raw |
| build.sh | build-script | cc -O2 -o udev_uaf udev_uaf.c | 263 B | view raw |
| run.sh | run-script | ./udev_uaf (root only, disposable VM) | 576 B | view raw |
| build.log | build-log | final successful PoC build output | 718 B | view raw |
| run.log | run-log | RUN 1 (decisive baseline): double-free panic 'memory chunk is already free' | 1.5 KB | view raw |
| run.2.log | run-log | RUN 2 (baseline confirmation): refcount-underflow panic 'ocnt != 0' | 1.4 KB | view raw |
| run.3.log | run-log | RUN 3 (baseline confirmation): identical to RUN 2 | 1.3 KB | view raw |
| run.baseline.log | run-log | Phase-8 baseline re-reproduction on unpatched #0 (panic, guest DOWN) | 1.5 KB | view raw |
| panic.txt | panic-signature | all baseline serial-console panic dumps from dfbsd-qemu/boot.log | 3.8 KB | view raw |
| env.txt | environment | uname, cc version, /dev/udev perms, securelevel, kldstat | 1.4 KB | view raw |
| VERDICT.md | verdict | full narrative: mechanism walkthrough, exploit-chain assessment, PoC changes, fix validation | 11.1 KB | β raw |
| fix.diff | suggested-fix | git-apply-able: move release to clean_events + NULL field, remove from externalize | 1.1 KB | view raw |
| README.md | readme | build/run/expected + bug summary | 3.5 KB | β raw |
| fix_build.log | build-log | Phase-8 full nativekernel build output of the single-fix kernel (rc=0, 35573 lines) | 5.6 MB | β download |
| fix_run.log | run-log | Phase-8 PoC on patched #1 kernel: 3/3 runs no-panic, boot.log+dmesg clean | 5.2 KB | view raw |
| dmesg.txt | dmesg | clean dmesg excerpt on patched kernel after 3 runs (no slab/objcache warnings) | 237 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0055 β PoC (REPRODUCED)
udev_uaf.c β deterministic trigger for the use-after-free of the shared
udev event dictionary via the multi-reader event-replication path.
Verdict
REPRODUCED. 3/3 fresh-VM runs panicked the DragonFlyBSD master DEV
kernel in the exact cited path
(udev_dev_read β udev_event_externalize β prop_object_release). Two
distinct panic signatures (malloc double-free; proplib refcount-underflow),
same root cause. See VERDICT.md and panic.txt.
The bug
The udev event queue replicates every event to all openers via per-softc
marker nodes spliced into the shared udev_evq TAILQ.
udev_event_externalize() (sys/kern/kern_udev.c:548) at :571 calls
prop_object_release(ev->ev.ev_dict) on the first reader to
externalize an event, freeing the shared proplib dict while the event
remains on udev_evq. The field is never NULLed, so:
udev_clean_events_locked()(:535, predicateev_dict != NULLat:540) leaves the event in the queue (it is stopped at the trailing reader's marker, which has a NULLev_dict).- The next reader's marker-walk (
:838-840) finds the same event (dangling non-NULLev_dictpasses the skip loop), callsudev_event_externalize()again, which at:566passes the freed pointer toprop_dictionary_set()βprop_object_retain(freed)β UAF write; the subsequent:571release then triggers a double-free / refcount underflow.
The sequence is deterministic (udev_lk serializes the two reads; a
reader cannot advance another reader's marker, so reader 2's marker is
guaranteed to still precede the event).
Privilege
/dev/udev is 0600 root:wheel (kern_udev.c:1039-1041). Trigger must
run as root (uid 0). maxx (uid 1001, not in wheel) cannot open it.
Realistic impact: reliable local kernel panic (DoS) from root β
matching the finding's Medium / CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H.
Build & run (root, disposable VM)
./build.sh # cc -O2 -o udev_uaf udev_uaf.c ./run.sh # ./udev_uaf (panics a vulnerable kernel in ~1-2s)
Expected output
Bug present β kernel panic (captured on the serial console /
dfbsd-qemu/boot.log):
panic: memory chunk 0xfffff80067b36860 is already free! chunk_mark_free() at chunk_mark_free+0xae _kfree() at _kfree+0x262 _prop_dictionary_free() at _prop_dictionary_free+0xe0 prop_object_release() at prop_object_release+0xfd udev_dev_read() at udev_dev_read+0x14f
or the equivalent refcount-underflow form:
panic: assertion "ocnt != 0" failed in prop_object_release at .../prop_object.c:1085
Bug fixed β runs ~12s, prints
no panic after 80 create/destroy cycles, exits 0.
Trigger mechanism
The PoC forks two readers, each opening /dev/udev (own softc/marker)
and blocking in read() (which auto-inserts both markers at
TAILQ_HEAD). The parent then runs ifconfig tap<N> create/destroy
in a loop β each make_dev/destroy_dev on tap_ops generates a
UDEV_EVENT_ATTACH/_DETACH via udev_event_insert
(sys/vfs/devfs/devfs_core.c:1428,1451; sys/net/tap/if_tap.c:289,491).
The first event the second reader reaches fires the UAF.
Fix
See fix.diff (matches the finding's proposal): move the
prop_object_release from udev_event_externalize:571 into
udev_clean_events_locked (release + NULL before TAILQ_REMOVE), so the
shared dict is released exactly once when the event is reaped (after all
readers have passed it), and each reader merely borrows it.
DF-0055 β VERDICT
Verdict: REPRODUCED (deterministic kernel panic / local DoS; root-only trigger).
3/3 fresh-VM runs panicked in the exact cited path (udev_dev_read β
udev_event_externalize β prop_object_release). Two distinct panic
signatures (double-free caught by the malloc layer; refcount-underflow
caught by the proplib _PROP_ASSERT) β both are direct consequences of
the same use-after-free of the shared udev event dictionary.
Mechanism (every hop cited path:line)
The udev event queue (udev_evq, a TAILQ) replicates every event to
all openers via a per-softc marker node spliced into the shared
queue. Each reader walks its own marker forward; an event is reaped only
once every reader's marker has advanced past it.
-
Event enqueue β
udev_event_insert()sys/kern/kern_udev.c:501prop_dictionary_copy()s the dict (refcount = 1) and stores it inev->ev.ev_dict(:512), thenTAILQ_INSERT_TAIL(&udev_evq, ev, link)(:516). -
Reader read path β
udev_dev_read():811finds the next event after the reader's marker, skippingNULL-dict nodes (:838-840), and callsudev_event_externalize(ev)(:842). -
The bug β
udev_event_externalize():548:
c
:566 prop_dictionary_set(dict, "evdict", ev->ev.ev_dict)
-> prop_object_retain(ev_dict) /* refcount 1 -> 2 */
:571 prop_object_release(ev->ev.ev_dict); /* refcount 2 -> 1 */
:575 prop_object_release(dict); /* temp dict: releases its "evdict"
child -> refcount 1 -> 0 -> FREED */
After reader 1 finishes, ev->ev.ev_dict is a dangling, non-NULL
pointer and the event is still on udev_evq. The field is never
NULLed.
-
Why the event is not reaped between readers β
udev_clean_events_locked():535reaps fromTAILQ_FIRSTwhileev->ev.ev_dict != NULL(:540). The loop stops at the firstNULL-dict node. The trailing reader's marker (astruct udev_event_kernelwhoseev_dictisNULL, inserted at:829) sits ahead of the just-read event in the other reader's view, so the clean loop halts at that marker and leaves the dangling event in place. Concretely: reader 1 cannot move reader 2's marker, so the event is provably still queued when reader 2 next reads. -
The UAF β reader 2's
udev_dev_read()finds the same event (dangling non-NULLev_dictpasses the:839skip loop and the:540predicate), callsudev_event_externalize()again, which at:566passes the freed pointer toprop_dictionary_set()->prop_object_retain(freed)(prop_object.c:992,atomic_inc_32_nv(&po->po_refcnt)β a write to freed memory). The subsequentprop_object_release()at:571then drives the stale refcount to 0 and calls_prop_dictionary_free()->_kfree()on memory the allocator already considers free.
This is deterministic, not a tight race: udev_lk serializes the two
reads, and reader 2's marker is guaranteed to still precede the event
because only reader 2 can advance its own marker.
Evidence
See panic.txt for all three serial-console panic dumps. The decisive
stack frames in every run are:
udev_dev_read() <- the reader's externalize call site (kern_udev.c:842) prop_object_release() <- :571 release of ev->ev.ev_dict _prop_dictionary_free() _kfree() -> chunk_mark_free() <- "memory chunk ... is already free!" (RUN 1) -- or -- prop_object_release(): _PROP_ASSERT(ocnt != 0) at prop_object.c:1085 (RUNs 2,3)
Both signatures name udev_dev_read as the entry point β i.e. the panic
is this bug, not an unrelated one.
Privilege / threat model (matches finding)
/dev/udevis0600 root:wheel(kern_udev.c:1039-1041);maxx(uid 1001, not in wheel) getsPermission deniedand cannot trigger this. Confirmed on the guest.- This is a root/wheel-local trigger. Realistic impact ceiling: reliable kernel panic (local DoS).
- CVSS 3.1:
AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H(Medium), matching the finding.
Exploit chain assessment (memory-corruption class)
The primitive is a UAF + double-free on a kernel prop_dictionary
object, with the freed pointer immediately handed to
prop_object_retain/prop_object_release, which dereference
po->po_refcnt and po->po_type from the freed memory. On a
non-INVARIANTS kernel the proplib object (struct _prop_dictionary,
allocated via prop_dictionary_create β kmalloc) lives in a general
kmalloc bucket and could in principle be reclaimed with a
victim object containing attacker-controlled bytes; the subsequent
pot_free/pot_lock indirect calls through po->po_type would then be
hijackable function-pointer targets.
However, two facts bound the realistic ceiling at DoS for this finding, and I did not develop a full LPE chain:
- The trigger already requires root. A root attacker can already
kldloadarbitrary code, write/dev/mem(when securelevel permits), or reboot the box β so "root β kernel code execution" is not a meaningful privilege-escalation boundary, and the finding correctly rates the impact as DoS. - The demonstrated panics (double-free / refcount-underflow) fire on
the very first event the second reader touches, before any
attacker has a chance to reclaim the freed object β so without first
defeating the allocator's double-free detection (or racing the
reclamation before
prop_object_releasere-derives the type), the bug expresses as a panic, not a controlled write.
A determined attacker who could arrange a reclaimed victim object in the
same slab between the two reads (the udev_lk serialization leaves a
window while reader 1 holds the lock releasing the dict and reader 2
blocks acquiring it) might convert this to a controlled kernel write,
but the root prerequisite makes the effort disproportionate to the gain.
The honest, defensible classification is reliable local kernel DoS
from root, exactly as filed.
PoC changes (vs. the initial seeded source)
The seeded udev_uaf.c was a sketch: it opened two fds and read in a
busy loop with usleep, but (a) never generated any device events, so
the readers would block forever on an empty queue, and (b) put both fds
in one process β which works (each open gets its own softc/marker) but
makes the deterministic nature non-obvious. I rewrote it to:
fork()two reader children, eachopen("/dev/udev")(own softc/marker) and block inread()β auto-initiating both markers atTAILQ_HEADbefore any event exists.- Parent waits for both to be ready, then generates a stream of udev
events via
ifconfig tap<N> create/destroy(eachmake_dev/destroy_devontap_opscallsudev_event_attach/_detachβudev_event_insert; confirmed atsys/net/tap/if_tap.c:289,491andsys/vfs/devfs/devfs_core.c:1428,1451). - The deterministic UAF fires on the first event the second reader reaches; 80 iterations guarantee it.
One compile fix: a stray /* temp */ inside the header block comment
prematurely closed the outer comment (fixed to (temp dict)).
Build: cc -O2 -o udev_uaf udev_uaf.c (clean, no deps).
Run: ./udev_uaf as root on a disposable VM.
Recommended fix
Authored in fix.diff (standalone, git apply-able, verified with
git apply --check). Matches the finding markdown's proposal:
- In
udev_clean_events_locked()(:535), addprop_object_release(ev->ev.ev_dict); ev->ev.ev_dict = NULL;before the existingTAILQ_REMOVE/objcache_putβ so the shared dict is released exactly once, when the event is reaped (after all readers have advanced past it). - Remove the
prop_object_release(ev->ev.ev_dict)atudev_event_externalize():571, so each reader merely borrows the dict (the tempdict's set/release is net-zero onev_dict).
Net effect on the correct path: dict refcount is 1 (held by the event) for the life of the event; each reader's externalize momentarily bumps it to 2 and back to 1; the final reader's clean reap drops it 1β0 and frees it. No dangling pointer, no double-free.
Fix validation (Phase 8 β built & booted the single-fix kernel)
Outcome: FIXED. Clean before/after on identical hardware, identical PoC.
Before (unpatched #0 baseline)
- Kernel:
DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026, sha256(/boot/kernel/kernel) =5dc83dac...22ad. - Re-ran the exact
./udev_uaftrigger as root: deterministic kernel panic on the first reader-2 event. Guest went DOWN. Serial console:panic: assertion "ocnt != 0" failed in prop_object_release at /usr/src/sys/libprop/prop_object.c:1085 cpuid = 1 prop_object_release() at prop_object_release+0x277 prop_object_release() at prop_object_release+0x277 udev_dev_read() at udev_dev_read+0x162Same signature as the prior session's 3/3 runs (double-free form on run 1, refcount-underflow form on runs 2-3). Seerun.baseline.logandpanic.txt.
Build the single-fix kernel
vm.sh reset with-srcβ clean source +#0.fix.diffapplied to/usr/srcwithpatch -p1: both hunks succeeded (Hunk #1 succeeded at 538. Hunk #2 succeeded at 575.). Verified the patched source:udev_clean_events_lockednow releases + NULLsev->ev.ev_dictbeforeTAILQ_REMOVE;udev_event_externalizeno longer releases it.make -j6 nativekernel KERNCONF=X86_64_GENERICβ rc=0, 0 errors (full output infix_build.log, 35573 lines). Artifacts:kernel.stripped(15705800 B),kernel.debug(119340832 B).- Installed bare
/boot/kernel/kernel(loader boots the bare name) +kernel.debug, sha βac173e08...ed6f. Rebooted.kern.versionnow reads#1: Thu Jul 2 15:06:40 UTC 2026(the build timestamp, NOT#0).
After (patched #1 single-fix kernel)
- Ran the same
./udev_uaftrigger 3Γ back-to-back as root: - 3/3 runs completed all 80 create/destroy cycles (160 events each,
480 events total), printed
no panic after 80 create/destroy cycles, exited 0. Guest stayed UP after every run. grep -ciE "panic:|fatal trap|already free|ocnt != 0|Memory modified"over the entireboot.logafter all 3 runs = 0.dmesg | grep -iE "slab|objcache|corrupt|modified|overflow"= empty (no silent heap corruption on this INVARIANTS-bearing kernel).- The only new
boot.log/dmesg lines are benigntap<N>: MAC addressmessages from the create/destroy device cycles.
Why this is conclusive
The bug is deterministic, not a tight race (udev_lk serializes the two
reads; reader 2's marker provably still precedes the event when reader 1
reads it). On #0 it fires on the first reader-2 event and panics
instantly. The patched kernel survives 480 such events with the proplib
_PROP_ASSERT(ocnt != 0) and malloc chunk_mark_free double-free detectors
both active (the same diagnostics that caught the baseline). There is no
masking β the fix closes the path.
fix_status = fixed. recommended_fix matches the finding markdown's
proposal; fix.diff is the authoritative git-apply-able form.
Fix verification
fixedVALIDATED. The exact ./udev_uaf trigger that panicked the unpatched #0 baseline on the first reader-2 event (ocnt != 0 in prop_object_release, guest DOWN) does NOT panic the single-fix #1 kernel: 3/3 runs completed 480 total udev events, exited 0, guest stayed UP, and boot.log + dmesg show zero panics/warnings (the proplib assertion and malloc double-free detectors that caught the baseline are still active). The fix correctly serializes the single release of the shared event dict into udev_clean_events_locked and removes the premature release from udev_event_externalize, closing the UAF/double-free.
baseline #0: panic: assertion "ocnt != 0" failed in prop_object_release ... udev_dev_read+0x162 (guest DOWN). patched #1: [!] no panic after 80 create/destroy cycles (160 udev events). RUN_EXIT=0 (3/3 runs, guest UP); boot.log panic grep = 0; dmesg warnings grep = empty. build: === NK_DONE rc=0 === (nativekernel, 0 errors).
Confirmed kernel references
Detail
Exploit chain
root-local kernel DoS via deterministic double-free/UAF of the shared udev event dictionary (the second reader's udev_event_externalize passes the freed dict to prop_object_retain/release). Root prerequisite (/dev/udev is 0600 root:wheel) bounds the realistic impact ceiling at DoS, not LPE; the finding's Medium / PR:H classification is correct. No privilege-escalation chain developed (root already bounds it).
Evidence (decisive lines)
BASELINE #0 (run.baseline.log/panic.txt): panic: assertion "ocnt != 0" failed in prop_object_release at /usr/src/sys/libprop/prop_object.c:1085 / prop_object_release+0x277 / prop_object_release+0x277 / udev_dev_read+0x162 / dev_dread / devfs_fo_read / kern_preadv -- guest DOWN. PATCHED #1 (fix_run.log): 3/3 runs of ./udev_uaf printed 'no panic after 80 create/destroy cycles (160 udev events)', RUN_EXIT=0, guest UP; grep panic|fatal trap|already free|ocnt!=0|Memory modified over boot.log = 0; dmesg slab|objcache|corrupt grep = empty.
PoC changes
fix.diff unchanged from the prior session (matches the finding markdown's proposal; re-verified git apply --check passes and both hunks apply cleanly to /usr/src). Added Phase-8 fix-validation evidence to findings/poc/DF-0055/: fix_build.log (full nativekernel output, rc=0), fix_run.log (3/3 patched runs no-panic + boot.log/dmesg checks), run.baseline.log (Phase-8 baseline re-reproduction on #0), dmesg.txt (clean dmesg excerpt). Updated VERDICT.md with the fix-validation section and manifest.json with the new artifacts + fix_status/fixed.
Verified recommended fix
In sys/kern/kern_udev.c, remove prop_object_release(ev->ev.ev_dict) from udev_event_externalize (:571) and instead add 'prop_object_release(ev->ev.ev_dict); ev->ev.ev_dict = NULL;' in udev_clean_events_locked before the existing TAILQ_REMOVE. This makes each reader's externalize net-zero on the shared dict (retain on prop_dictionary_set, release when the temp dict is dropped) and frees the dict exactly once when the last reader's marker advances past the event and the event is reaped. Matches the finding proposal; the standalone git-apply-able diff is at findings/poc/DF-0055/fix.diff.
Verdict
REPRODUCED + FIX VALIDATED. The use-after-free of the shared udev event dictionary is real and deterministic: udev_event_externalize (sys/kern/kern_udev.c:548) calls prop_object_release(ev->ev.ev_dict) at :571 on the FIRST reader to externalize an event, freeing the shared proplib dict while the event remains on udev_evq (the field is never NULLed, so udev_clean_events_locked :535/:540 cannot reap it). The next reader's udev_dev_read (:811/:842) finds the same dangling non-NULL ev_dict and re-externalizes it, hitting prop_object_retain(freed) then a double-free/refcount-underflow. Confirmed on the unpatched #0 kernel: the PoC panicked deterministically with 'panic: assertion "ocnt != 0" failed in prop_object_release at prop_object.c:1085' entered via udev_dev_read (same signature as the prior 3/3 baseline runs). The fix moves the single release into udev_clean_events_locked (release + NULL before TAILQ_REMOVE) and removes the premature release from externalize, so each reader's externalize is net-zero on ev_dict and the dict is freed exactly once when the last reader's marker advances past the event. I built the single-fix kernel (#1), installed it, and re-ran the SAME PoC 3x: all 3 completed 80 create/destroy cycles (480 udev events total), exited 0, guest stayed UP, with ZERO panics in boot.log and ZERO slab/objcache warnings in dmesg (the proplib _PROP_ASSERT and malloc double-free detectors that caught the baseline are still active).
No comments yet.