Skip to content

Commit 5c32017

Browse files
zhovnerTingPing
authored andcommitted
kms: Skip mode copy for connectors without any modes
kms_screen_probe() unconditionally memcpy()s drmModeModeInfo from con->modes[0] regardless of con->count_modes. drmModeGetConnector(3) documents that drmModeConnector::modes is NULL whenever count_modes is zero, which is normal for any disconnected connector (no EDID, no mode list). Currently this only matters in practice when the caller asks for universal planes via DRM_CLIENT_CAP_UNIVERSAL_PLANES, because that is when init_cursor()'s kms_device_open() path runs and probes every connector returned by drmModeGetResources(), including the disconnected ones. Concrete reproducer on a Rockchip RK3576 board (driver: rockchip-drm) with the integrated DisplayPort connector unplugged and HDMI plugged in. card2 reports two connectors: DP-1 (disconnected, count_modes=0, modes=NULL) and HDMI-A-1 (connected). With COG_PLATFORM_DRM_CURSOR=1 set, cog crashes with SIGSEGV inside kms_screen_probe() at the first iteration of kms_device_probe_screens on the disconnected DP-1 connector. Trace from the suspect line, captured by an instrumented build: [cursor-debug] kms.c kms_screen_probe: connector id=74 type=10 connection=2 count_modes=0 modes_ptr=(nil) [cursor-debug] kms.c kms_screen_probe: about to memcpy con->modes[0] (count_modes=0, modes=(nil)) *** SIGSEGV *** Guard the memcpy on count_modes > 0. screen is calloc()'d in kms_screen_create(), so on the no-modes path screen->mode and screen->{width,height} stay zeroed -- which is correct: a connector with no modes has no screen geometry to report. This is reproducible on any system with a multi-output DRM driver and at least one connector unplugged at startup; the FlipperOne hardware just makes it easy to demonstrate.
1 parent 8a7051b commit 5c32017

1 file changed

Lines changed: 5 additions & 3 deletions

File tree

platform/drm/kms.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,11 @@ static void kms_screen_probe(struct kms_screen *screen)
361361
else
362362
screen->connected = false;
363363

364-
memcpy(&screen->mode, &con->modes[0], sizeof(drmModeModeInfo));
365-
screen->width = screen->mode.hdisplay;
366-
screen->height = screen->mode.vdisplay;
364+
if (con->count_modes > 0) {
365+
memcpy(&screen->mode, &con->modes[0], sizeof(drmModeModeInfo));
366+
screen->width = screen->mode.hdisplay;
367+
screen->height = screen->mode.vdisplay;
368+
}
367369

368370
drmModeFreeConnector(con);
369371
}

0 commit comments

Comments
 (0)