⬢ DragonFlyBSD Kernel Audit
DF-4145 / run.log
← back to finding ↓ download raw
################ BASELINE (verbatim production code) ################
===== [BASELINE] MODE layout =====
sizeof(struct radeon_ps)          = 48 (kernel x86_64: 48)
offsetof(radeon_ps, ps_priv)      = 40 (kernel: 40; last member of the struct)
sizeof(struct radeon_power_state) = 48
sizeof(struct trinity_pl)         = 12; offsetof(allow_gnb_slow) = 7
sizeof(struct trinity_ps)         = 92; offsetof(levels) = 4; offsetof(num_levels) = 0
sizeof(struct sumo_ps)            = 128 (per-state kzalloc size at :1779)
sizeof(struct trinity_power_info) = 528
requested_rps..requested_ps gap   = 48 (== sizeof(radeon_ps)? YES)
&pi->requested_ps - 1 == MSB(&pi->requested_rps.ps_priv)? YES
levels[num_levels-1].allow_gnb_slow with num_levels==0 -> ps-1 (levels[-1] spans ps-8..ps+3)
in-kernel consequence: ps_priv = 0xffff.... heap pointer; MSB 0xff -> 0x00 = 0x00ffff.... non-canonical -> page fault on next trinity_get_ps
RESULT: OK layout
----- rc=0 -----
===== [BASELINE] MODE good =====
RIG: trinity_dpm_init rc=0 num_ps=2 boot_ps=0x80047e000
RIG: trinity_dpm_enable rc=0
RIG: trinity_dpm_disable done
RIG: pre_set_power_state rc=0
RIG: get_sclk(low)=30000 (expect 30000)
RESULT: OK good-table regression (init/enable/disable/fini clean)
----- rc=0 -----
===== [BASELINE] MODE 4143-enable =====
RIG: init rc=0 num_ps=2 boot_ps=0x0 (no BOOT-classified state -> stays NULL)
RIG: simulating radeon_pm.c:1448 'radeon_dpm_init(rdev);' -- return value DISCARDED -- then :1449 current_ps=requested_ps=boot_ps and :1453 radeon_dpm_enable(rdev)
RESULT: FAULT addr=0x28  guard/unmapped address
NOTE: fault address 40 < page size -> NULL-pointer dereference at member offset 40
----- rc=88 -----
===== [BASELINE] MODE 4143-presel =====
RIG: requested_ps=0x0; verbatim trinity_dpm_pre_set_power_state (:1240 derefs it)
RESULT: FAULT addr=0x0  guard/unmapped address
NOTE: fault address 0 < page size -> NULL-pointer dereference at member offset 0
----- rc=88 -----
===== [BASELINE] MODE 4143-initfail =====
RIG: init rc=-22 (parse aborted on NULL power_state[1].clock_info at :1777) boot_ps=0x0
RIG: simulating radeon_pm.c:1448 'radeon_dpm_init(rdev);' -- return value DISCARDED -- then :1449 current_ps=requested_ps=boot_ps and :1453 radeon_dpm_enable(rdev)
RESULT: FAULT addr=0x28  guard/unmapped address
NOTE: fault address 40 < page size -> NULL-pointer dereference at member offset 40
----- rc=88 -----
===== [BASELINE] MODE 4144-doublefree =====
RIG: injecting kzalloc(128) failure (#2)
RIG: init rc=-12; dpm.ps=0x80047e000 (kfreed at :1781, pointer NOT NULLed), num_ps=0, boot_ps=0x80047e000 (points INTO the freed array)
RIG: allocator confirms dpm.ps 0x80047e000 is FREED while rdev still holds it
RIG: simulating unload: radeon_pm.c:1705 radeon_dpm_fini(rdev) (unconditional)
RESULT: DOUBLEFREE ptr=0x80047e000 (allocation of 96 bytes freed a 2nd time)
----- rc=89 -----
===== [BASELINE] MODE 4144-uaf =====
RIG: injecting kzalloc(128) failure (#2)
RIG: init rc=-12; boot_ps=0x80047e000 -> &freed_dpm.ps[0]; :1129 reads boot_ps->ps_priv
RIG: simulating radeon_pm.c:1448 'radeon_dpm_init(rdev);' -- return value DISCARDED -- then :1449 current_ps=requested_ps=boot_ps and :1453 radeon_dpm_enable(rdev)
RESULT: FAULT addr=0x80047e028  USE-AFTER-FREE in freed allocation 0x80047e000..0x80047e060 (+40 bytes in, alloc size 96)
----- rc=88 -----
===== [BASELINE] MODE 4145-guard =====
drm: ERROR drm: ERROR UVD clock index not found!
RIG: init rc=0 nb_dpm_enable=1
RIG: ps=0x8004c6000 (page start, PROT_NONE page before) num_levels=0 class=SDSTATE; verbatim trinity_apply_state_adjust_rules -> :1619 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0
RIG: num_levels is u32: num_levels-1 = 0xFFFFFFFF, sizeof(trinity_pl)=12 -> the store address is ps + 0xbffffffff (a WILD write ~48GB past the object, NOT ps-1: the unsigned index wraps before scaling)
RESULT: FAULT addr=0x14004c5fff  guard/unmapped address
----- rc=88 -----
===== [BASELINE] MODE 4145-fullflow =====
drm: ERROR drm: ERROR UVD clock index not found!
RIG: init rc=0
RIG: state1 num_levels=0 (ucNumDPMLevels==0 -> num_levels never set by :1726)
RIG: &pi->requested_ps=0x80047c1b0 ; :1619 store target = 0x140047c1af (ps + 0xBFFFFFFFF, u32 wrap) ; canary page mapped at 0x140047b000, pre-filled 0xAA
RIG: pre_set_power_state rc=0
RIG: canary byte at target: 0xaa -> 0x00 (WRITTEN 0x00 BY THE VERBATIM STORE)
RIG: canary region bytes changed: 1 (of 12288)
RIG: requested_ps.Dpm0PgNbPsLo=2 DpmXNbPsLo=2 (:1603-:1618 EXECUTED: the 1/2 defaults from :1604/:1606 were overwritten at :1615/:1617 immediately before the :1619 OOB store)
RIG: verbatim trinity_dpm_get_sclk(low=false) = 0xaaaaaaaa -- reads levels[0xFFFFFFFF].sclk at ps + 0xBFFFFFFF8 (the SAME wild region; value = 0xAA-repeated canary bytes unless the store overlapped: 0xaaaaaaaa)
RESULT: OK 4145-fullflow (wild OOB write + OOB read at ps+0xBFFFFFFFF demonstrated)
----- rc=0 -----
===== [BASELINE] MODE 4146-offset =====
RIG: usStateArrayOffset=0x1000, PowerPlayInfo at bios+0x500, image 0x1000 -> state_array=bios+0x1500 (past the image); :1767 reads ucNumEntries
RESULT: FAULT addr=0x800479500  guard/unmapped address
----- rc=88 -----
===== [BASELINE] MODE 4146-stride =====
RIG: state at 0x1FFD with ucNumDPMLevels=255; :1788 idx[j] walk crosses the image end at j=1 (addr bios+0x2000)
RESULT: FAULT addr=0x80047a000  guard/unmapped address
----- rc=88 -----
===== [BASELINE] MODE 4146-canary =====
RIG: state array at img+0x40: ucNumEntries=1 state0 @ img+0x541 bytes: ff 01 00 05 06 07 08 ff ff ff  (idx[0..7] =) 0 5 6 7 8 255 255 255
RIG: 1-entry state array, ucNumDPMLevels=255; bytes past the state entry: 5,6,7,8 at idx[1..4] then 0xff; at idx[253] (state+254 = 0x640) sits the NON-CLOCK ARRAY header (ucNumEntries=3) -- the unbounded walk crosses into the adjacent table and parses its metadata as clock indices. clock entries carry sclk=1000*i+777
RIG: init rc=0
RIG: state0 num_levels=5
RIG:   level 0 sclk=777
RIG:   level 1 sclk=5777
RIG:   level 2 sclk=6777
RIG:   level 3 sclk=7777
RIG:   level 4 sclk=3777
RESULT: OK 4146-canary (data-flow proof printed above)
----- rc=0 -----
===== [BASELINE] MODE 4146-powerguard =====
RIG: legacy pre-parse sized power_state[] for ucNumStates=1 (radeon_atombios.c:2592, 48-byte entry); trinity loop bound is state_array->ucNumEntries=255; array at page end -> i=1 read faults
RESULT: FAULT addr=0x80047c008  guard/unmapped address
----- rc=88 -----
===== [BASELINE] MODE 4146-nullabort =====
RIG: ucNumEntries=4 > filled legacy power_state entries (1); state0 non-BOOT
RIG: init rc=-22 (parse hit NULL power_state[1].clock_info at :1777-1778)
RIG: simulating radeon_pm.c:1448 'radeon_dpm_init(rdev);' -- return value DISCARDED -- then :1449 current_ps=requested_ps=boot_ps and :1453 radeon_dpm_enable(rdev)
RESULT: FAULT addr=0x28  guard/unmapped address
NOTE: fault address 40 < page size -> NULL-pointer dereference at member offset 40
----- rc=88 -----

################ FIXED (same slice + the four fix.diffs) ################
===== [FIXED] MODE layout =====
sizeof(struct radeon_ps)          = 48 (kernel x86_64: 48)
offsetof(radeon_ps, ps_priv)      = 40 (kernel: 40; last member of the struct)
sizeof(struct radeon_power_state) = 48
sizeof(struct trinity_pl)         = 12; offsetof(allow_gnb_slow) = 7
sizeof(struct trinity_ps)         = 92; offsetof(levels) = 4; offsetof(num_levels) = 0
sizeof(struct sumo_ps)            = 128 (per-state kzalloc size at :1779)
sizeof(struct trinity_power_info) = 528
requested_rps..requested_ps gap   = 48 (== sizeof(radeon_ps)? YES)
&pi->requested_ps - 1 == MSB(&pi->requested_rps.ps_priv)? YES
levels[num_levels-1].allow_gnb_slow with num_levels==0 -> ps-1 (levels[-1] spans ps-8..ps+3)
in-kernel consequence: ps_priv = 0xffff.... heap pointer; MSB 0xff -> 0x00 = 0x00ffff.... non-canonical -> page fault on next trinity_get_ps
RESULT: OK layout
----- rc=0 -----
===== [FIXED] MODE good =====
RIG: trinity_dpm_init rc=0 num_ps=2 boot_ps=0x80047e000
RIG: trinity_dpm_enable rc=0
RIG: trinity_dpm_disable done
RIG: pre_set_power_state rc=0
RIG: get_sclk(low)=30000 (expect 30000)
RESULT: OK good-table regression (init/enable/disable/fini clean)
----- rc=0 -----
===== [FIXED] MODE 4143-enable =====
drm: ERROR drm: ERROR no boot state; dpm init did not succeed
RIG: init rc=0 num_ps=2 boot_ps=0x0 (no BOOT-classified state -> stays NULL)
RIG: simulating radeon_pm.c:1448 'radeon_dpm_init(rdev);' -- return value DISCARDED -- then :1449 current_ps=requested_ps=boot_ps and :1453 radeon_dpm_enable(rdev)
RIG: enable rc=-22
RESULT: OK (fixed) 4143-enable rejected cleanly, no fault (rc=-22)
----- rc=0 -----
===== [FIXED] MODE 4143-presel =====
RESULT: OK (fixed) parse rejected the crafted table (init rc=0) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4143-initfail =====
drm: ERROR drm: ERROR state count exceeds power_state table
RIG: init rc=-22 (parse aborted on NULL power_state[1].clock_info at :1777) boot_ps=0x0
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4144-doublefree =====
RIG: injecting kzalloc(128) failure (#2)
RIG: init rc=-12; dpm.ps=0x0 (kfreed at :1781, pointer NOT NULLed), num_ps=0, boot_ps=0x0 (points INTO the freed array)
RIG: simulating unload: radeon_pm.c:1705 radeon_dpm_fini(rdev) (unconditional)
RESULT: OK (fixed) parse rejected the crafted table (init rc=-12) before the vulnerable site
RIG: allocator report: (0 live)
RESULT: OK (fixed) unwind + idempotent fini, no double free, no leak
----- rc=0 -----
===== [FIXED] MODE 4144-uaf =====
RIG: injecting kzalloc(128) failure (#2)
drm: ERROR drm: ERROR no boot state; dpm init did not succeed
RIG: init rc=-12; boot_ps=0x0 -> &freed_dpm.ps[0]; :1129 reads boot_ps->ps_priv
RESULT: OK (fixed) parse rejected the crafted table (init rc=-12) before the vulnerable site
RIG: fixed enable rc=-22 (guard; boot_ps NULLed by unwind)
RESULT: OK (fixed) no UAF: dangling boot_ps cleared
----- rc=0 -----
===== [FIXED] MODE 4145-guard =====
drm: ERROR drm: ERROR power state 1 has no dpm levels
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4145-fullflow =====
drm: ERROR drm: ERROR power state 1 has no dpm levels
RIG: init rc=-22
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4146-offset =====
drm: ERROR drm: ERROR invalid powerplay array offsets
RIG: usStateArrayOffset=0x1000, PowerPlayInfo at bios+0x500, image 0x1000 -> state_array=bios+0x1500 (past the image); :1767 reads ucNumEntries
RIG: init rc=-22
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4146-stride =====
drm: ERROR drm: ERROR invalid powerplay array offsets
RIG: state at 0x1FFD with ucNumDPMLevels=255; :1788 idx[j] walk crosses the image end at j=1 (addr bios+0x2000)
RIG: init rc=-22
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4146-canary =====
RIG: state array at img+0x40: ucNumEntries=1 state0 @ img+0x541 bytes: ff 01 00 05 06 07 08 ff ff ff  (idx[0..7] =) 0 5 6 7 8 255 255 255
RIG: 1-entry state array, ucNumDPMLevels=255; bytes past the state entry: 5,6,7,8 at idx[1..4] then 0xff; at idx[253] (state+254 = 0x640) sits the NON-CLOCK ARRAY header (ucNumEntries=3) -- the unbounded walk crosses into the adjacent table and parses its metadata as clock indices. clock entries carry sclk=1000*i+777
RIG: init rc=0
RIG: state0 num_levels=5
RIG:   level 0 sclk=777
RIG:   level 1 sclk=5777
RIG:   level 2 sclk=6777
RIG:   level 3 sclk=7777
RIG:   level 4 sclk=3777
RESULT: OK 4146-canary (data-flow proof printed above)
----- rc=0 -----
===== [FIXED] MODE 4146-powerguard =====
drm: ERROR drm: ERROR state count exceeds power_state table
RIG: legacy pre-parse sized power_state[] for ucNumStates=1 (radeon_atombios.c:2592, 48-byte entry); trinity loop bound is state_array->ucNumEntries=255; array at page end -> i=1 read faults
RIG: init rc=-22
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
----- rc=0 -----
===== [FIXED] MODE 4146-nullabort =====
drm: ERROR drm: ERROR state count exceeds power_state table
drm: ERROR drm: ERROR no boot state; dpm init did not succeed
RIG: ucNumEntries=4 > filled legacy power_state entries (1); state0 non-BOOT
RIG: init rc=-22 (parse hit NULL power_state[1].clock_info at :1777-1778)
RESULT: OK (fixed) parse rejected the crafted table (init rc=-22) before the vulnerable site
RIG: fixed enable rc=-22
RESULT: OK (fixed) count-bound reject + enable guard, no fault
----- rc=0 -----