hwss1_plane_atomic_disconnect: `opp` NULL check placed after its own dereferences (dead guard, latent NULL-deref)
Summary
The function captures opp at :887, dereferences it at :889, and only afterwards tests opp!=NULL at :897 β dead guard. Currently unreachable (init_hw assigns stream_res.opp before its call; apply_ctx reaches the hook only for old pipes with OPP mapped). Linux v5.4 carries the byte-identical misplaced check β carried-in latent defect. Hoist the guard like dcn10_wait_for_mpcc_disconnect already does.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3980 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.4 KB | β raw | |
| VERDICT.md | β | 1.7 KB | β raw | |
| df3980_opp_order.c | β | 1.4 KB | view raw | |
| manifest.json | β | 622 B | view raw | |
| verdict.json | β | 1.8 KB | view raw |
DF-3980 β dcn10: opp NULL check placed after its dereference in hwss1_plane_atomic_disconnect (latent)
File: sys/dev/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c:889,897
Severity: Info (latent β currently unreachable; upstream-identical)
Hardware: DCN10 β absent from the audit guest; source-level certainty.
hwss1_plane_atomic_disconnect() reads pipe_ctx->stream_res.opp into a
local at :887, dereferences it at :889 (&(opp->mpc_tree_params), then
get_mpcc_for_dpp/remove_mpcc on that pointer), and only afterwards
tests if (opp != NULL) at :897 before touching it again. The check is dead
code: it can never protect the earlier dereferences.
Unreachable today: the two callers both guarantee a non-NULL OPP β
dcn10_init_hw sets pipe_ctx->stream_res.opp = dc->res_pool->opps[i]
(:1076) immediately before invoking the hook (:1078), and
dcn10_apply_ctx_for_surface calls it only for old pipes that had a plane
attached (:2387-2391), which by resource mapping have stream_res.opp
assigned. Upstream Linux v5.4 carries byte-identical code, so a future caller
that relaxes the invariant trips the NULL deref.
Fix: hoist the check to the top of the function
(if (opp == NULL) return;) β matching the style of dcn10_wait_for_mpcc_disconnect's
if (!pipe_ctx->stream_res.opp) return; (:2579-2580).
Files
df3980_opp_order.cβ documentation stubVERDICT.md,manifest.json,verdict.json
DF-3980 β VERDICT
Status: inconclusive (hardware-gated β no DCN10 GPU on the audit guest;
additionally the defect is unreachable by construction today), source certainty
only.
Root cause: hwss1_plane_atomic_disconnect() at
sys/dev/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c:889 dereferences
opp (&(opp->mpc_tree_params) and subsequent get_mpcc_for_dpp /
remove_mpcc through that pointer) before the NULL guard at :897
(if (opp != NULL)), which is therefore dead. If any future caller invokes the
hook with pipe_ctx->stream_res.opp == NULL, the kernel NULL-derefs at :889.
Current callers (both safe):
1. dcn10_init_hw :1078 β assigns pipe_ctx->stream_res.opp at :1076 first.
2. dcn10_apply_ctx_for_surface :2391 β only for old pipes with
old_pipe_ctx->plane_state set (:2387), which have OPP resources mapped.
Upstream parity: Linux v5.4 hwss1_plane_atomic_disconnect is
byte-identical in this respect (deref at its :986, dead check at :994) β a
carried-in latent defect, not a port regression.
Fix: hoist if (opp == NULL) return; to the top of the function (same
pattern as dcn10_wait_for_mpcc_disconnect :2579-2580 in this file).
Classification rationale: Info β latent NULL-deref, no reachable trigger today, no memory corruption; filed as hardening with the exact one-line fix.
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.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testableInfo hardening finding; no fix validation applicable (no hardware, unreachable path).
n/a
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md: caller-by-caller safety proof + upstream v5.4 byte-identical comparison.
PoC changes
n/a (documentation stub only)
Verified recommended fix
Hoist if (opp == NULL) return; to the top of hwss1_plane_atomic_disconnect (pattern already used by dcn10_wait_for_mpcc_disconnect :2579).
Verdict
hwss1_plane_atomic_disconnect dereferences stream_res.opp at dcn10_hw_sequencer.c:889 and only tests it for NULL afterwards at :897, so the guard is dead. Both current callers guarantee non-NULL (dcn10_init_hw assigns opp at :1076 before the :1078 call; dcn10_apply_ctx_for_surface only reaches the hook for old planes with mapped OPP resources at :2387-2391), and Linux v5.4 carries the identical misplaced check, so this is a latent carried-in defect rather than a port regression. No DCN10 GPU on the audit guest and no reachable trigger by construction: no runtime demonstration possible; Info hardening with a one-line fix (hoist the NULL check).
No comments yet.