DF-3655 / harness.c
/* * DF-3655 harness โ NULL deref through the second WARN_ON in * amdgpu_dm_atomic_commit_tail() (sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4888-4890): * * 4888 status = dc_stream_get_status(dm_new_crtc_state->stream); * 4889 WARN_ON(!status); * 4890 WARN_ON(!status->plane_count); <-- dereferences `status` even * when the previous WARN_ON just * reported it NULL * * WARN_ON() evaluates and prints but does NOT stop execution, so line 4890 * faults. status==NULL is reachable when the stream is not present in the * current DC context (e.g. right after a failed dc_commit_state(), which is * only WARN_ON'd at amdgpu_dm.c:4837 and execution continues). * * Expected: WARN_ON(!status) = 1 printed, then SIGSEGV reading * offsetof(dc_stream_status, plane_count) โ small offset, unmapped page 0. */ #include <stdio.h> #include <stddef.h> #include <stdint.h> struct dc_stream_status { int primary_otg_inst; int stream_enc_inst; int plane_count; /* verbatim field order, dc/dc_stream.h */ struct dc_plane_state *plane_states[6]; }; #define WARN_ON(x) (printf("WARN_ON(%s) = %d at %s:%d\n", #x, \ (int)(x), __FILE__, __LINE__), fflush(stdout)) int main(void) { struct dc_stream_status *status = NULL; /* dc_stream_get_status() miss */ printf("offsetof(dc_stream_status, plane_count) ~ 0x%zx\n", offsetof(struct dc_stream_status, plane_count)); fflush(stdout); WARN_ON(!status); /* amdgpu_dm.c:4889 โ prints, continues */ WARN_ON(!status->plane_count); /* amdgpu_dm.c:4890 โ NULL DEREF */ printf("NOT REACHED\n"); return 0; } |