β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4272

dcn_bw_notify_pplib_of_wm_ranges dereferences unchecked res_pool->pp_smu (kzalloc-failure NULL) β€” probe-time panic on DCN1

Summary

The function loads pp = dc->res_pool->pp_smu and dereferences pp->set_wm_ranges without ever checking pp itself. The sole assignment returns NULL on kzalloc failure and no check follows; the probe-time call is unconditional. Raven-APU systems: kernel memory pressure at the instant of construct's kzalloc turns driver probe into a NULL-pointer panic at boot. Upstream carries the same latent pattern. NULL-guard fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4272 Β· 5 files
FileTypeDescriptionSize
README.md β€” 1.8 KB ↓ raw
VERDICT.md β€” 1.8 KB ↓ raw
fix.diff β€” 855 B view raw
verdict.json β€” 2.6 KB view raw
env.txt β€” 700 B view raw

DF-4272 β€” dcn_bw_notify_pplib_of_wm_ranges() dereferences res_pool->pp_smu without a NULL check

File: sys/dev/drm/amd/display/dc/calcs/dcn_calcs.c:1399-1407 (DCN1 bandwidth calc engine).

What

void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
{
        struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu;
        ...
        if (!pp->set_wm_ranges)          /* :1406 - pp itself unchecked */
                return;

dc->res_pool->pp_smu is assigned exactly once, in dcn10_resource_construct():

pool->base.pp_smu = dcn10_pp_smu_create(ctx);   /* dcn10_resource.c:1352 */
...
if (!dc->debug.disable_pplib_wm_range) {
        dc->res_pool = &pool->base;
        dcn_bw_notify_pplib_of_wm_ranges(dc);   /* dcn10_resource.c:1357 */
}

and dcn10_pp_smu_create() is a plain kzalloc() that returns NULL on allocation failure (dcn10_resource.c:858-865):

struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx)
{
        struct pp_smu_funcs_rv *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL);
        if (!pp_smu)
                return pp_smu;           /* NULL */

There is no NULL check anywhere between the create and the dereference, so an allocation failure during amdgpu DCN1 (Raven APU) driver probe takes a NULL-pointer read at pp->set_wm_ranges β†’ kernel panic at probe time. The second call site, dcn10_hw_sequencer.c:2303 (optimize_shared_resources), would fault the same way whenever it is reached with a NULL pp_smu.

Impact

Boot/probe-time panic under kernel memory pressure on Raven-APU systems (amdgpu with DCN1). No privilege needed by an attacker beyond the ability to influence allocation timing (or simply an unlucky boot); OOM-gated, hardware-gated. Severity Low. CWE-476.

Fix

if (!pp || !pp->set_wm_ranges) return; (fix.diff).

VERDICT.md
↓ download raw

VERDICT - DF-4272 (dcn_bw_notify_pplib_of_wm_ranges NULL pp_smu deref)

Status: untested - the audit guest has no AMD DCN1 (Raven) GPU (env.txt); the code path is source-certain.

Trace

  1. dcn_bw_notify_pplib_of_wm_ranges() (dcn_calcs.c:1401): struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu;
  2. First dereference of pp: if (!pp->set_wm_ranges) (dcn_calcs.c:1406) - pp itself is never NULL-checked.
  3. Sole assignment: pool->base.pp_smu = dcn10_pp_smu_create(ctx); (dcn10_resource.c:1352), whose implementation returns NULL on kzalloc failure (dcn10_resource.c:858-865). No NULL check follows the create.
  4. Unconditional call site (unless the debug flag disable_pplib_wm_range is set): dcn10_resource.c:1353-1357, inside dcn10_resource_construct() during driver probe. Second site: dcn10_hw_sequencer.c:2303 (optimize_shared_resources), reached later in DC bring-up.

Impact

NULL pointer read β†’ panic during amdgpu probe under memory pressure on DCN1-bearing APUs (Raven). Trigger is environmental (kzalloc OOM at the wrong instant), not attacker-directed in the usual sense; the guest has no such hardware so no reproduction is possible. Low severity, certain code path, speculative trigger. Note: the same latent pattern exists in the upstream Linux DC code of this vintage.

Fix

One-line guard (fix.diff). A NULL-check-only change: no behavioral difference on the success path.

Fix validation

Not possible on this guest (no Raven GPU). fix_status = not_testable.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Fix validation requires DCN1 hardware; the guest has none.

fix.diff; VERDICT.md
↓ fix.diffper-fix-DF-4272

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md trace (create->store->deref chain with path:line); dcn10_resource.c:858-865 (NULL return), :1352-1357 (unchecked store + probe-time call); dcn_calcs.c:1401-1406

PoC changes

No PoC (no DCN1 hardware in guest); analysis pack.

Verified recommended fix

if (!pp || !pp->set_wm_ranges) return; in dcn_bw_notify_pplib_of_wm_ranges().

Verdict

Source-certain NULL-deref path, OOM-gated trigger. dcn_bw_notify_pplib_of_wm_ranges() (dcn_calcs.c:1401) loads pp = dc->res_pool->pp_smu and dereferences pp->set_wm_ranges at :1406 without checking pp. The sole assignment is pool->base.pp_smu = dcn10_pp_smu_create(ctx) (dcn10_resource.c:1352), which returns NULL on kzalloc failure (dcn10_resource.c:858-865); no NULL check anywhere between create and use. Call sites: dcn10_resource.c:1353-1357 (probe, unconditional unless disable_pplib_wm_range) and dcn10_hw_sequencer.c:2303 (optimize_shared_resources). Allocation failure during amdgpu DCN1 probe -> NULL read -> panic at boot/probe on Raven APU systems. Guest has no DCN1 GPU (env.txt), so not kernel-reproduced; trigger requires kernel memory pressure at the wrong instant (speculative trigger, certain code path). Upstream Linux DC of this vintage carries the same latent pattern.