Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [Critical] Missing validation allows the CRTC to be enabled without a primary plane, causing a NULL pointer dereference in `arc_pgu_set_pxl_fmt()`. - [Critical] The CRTC atomic_enable hook accesses arcpgu->plane.state directly without holding the plane's lock, allowing a concurrent plane update to cause a Use-After-Free. - [High] Disabling the primary plane incorrectly clears the global CRTC enable bit, permanently desyncing hardware state from the DRM core. - [High] Missing `.cleanup_fb` callback causes GEM object pin count leak on every plane update. --
commit a8222dfe6a09a56b144901613fe5caafe6889898 Author: Davide Bonatto <[email protected]> drm/tiny: arcpgu: Replace simple display pipe with regular atomic helpers This commit migrates the arcpgu driver from the legacy drm_simple_display_pipe infrastructure to explicitly managing plane, CRTC, and encoder objects using standard atomic helpers. > diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c > index c93d61ac0bb75..e500e6e52b669 100644 > --- a/drivers/gpu/drm/tiny/arcpgu.c > +++ b/drivers/gpu/drm/tiny/arcpgu.c [ ... ] > @@ -117,8 +125,8 @@ static const u32 arc_pgu_supported_formats[] = { > > static void arc_pgu_set_pxl_fmt(struct arcpgu_drm_private *arcpgu) > { > - const struct drm_framebuffer *fb = arcpgu->pipe.plane.state->fb; > - uint32_t pixel_format = fb->format->format; > + const struct drm_framebuffer *fb = arcpgu->plane.state->fb; > + u32 pixel_format = fb->format->format; [Severity: Critical] What happens if userspace enables the CRTC but disables the primary plane? In that scenario, fb would be NULL, and the subsequent fb->format->format dereference would crash the kernel. The driver does not appear to have a CRTC atomic_check hook to prevent enabling the CRTC without a valid plane, and arc_pgu_plane_atomic_check() gracefully returns 0 when the framebuffer is missing. [Severity: Critical] Can a concurrent plane update cause a use-after-free here? This function is called from the CRTC enable path: arc_pgu_crtc_atomic_enable() -> arc_pgu_mode_set() -> arc_pgu_set_pxl_fmt() Since there is no CRTC atomic_check hook calling drm_atomic_add_affected_planes(), a modeset only locks the CRTC and not the plane. A concurrent plane update (page flip) could acquire the plane lock, swap the state, and free the old framebuffer, causing the modesetting thread to read freed memory when locklessly accessing fb->format->format. [ ... ] > +static void arc_pgu_plane_atomic_disable(struct drm_plane *plane, > + struct drm_atomic_commit *state) > +{ > + struct arcpgu_drm_private *arcpgu = plane_to_arcpgu(plane); > + > + arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, 0); > + arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, > + arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) & > + ~ARCPGU_CTRL_ENABLE_MASK); > +} [Severity: High] Does clearing ARCPGU_CTRL_ENABLE_MASK permanently desync the hardware state? This appears to be the global CRTC enable bit. If userspace disables just the primary plane, this clears the global enable bit for the entire CRTC. When the plane is later re-enabled, arc_pgu_plane_atomic_update() sets the buffer address but does not restore the CRTC enable bit, leaving the display controller completely disabled and causing VBLANK timeouts. [ ... ] > +static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = { > + .atomic_update = arc_pgu_plane_atomic_update, > + .prepare_fb = drm_gem_plane_helper_prepare_fb, > + .atomic_check = arc_pgu_plane_atomic_check, > + .atomic_disable = arc_pgu_plane_atomic_disable, > +}; [Severity: High] Does this leak the GEM object pin count on every plane update? The prepare_fb hook is set to drm_gem_plane_helper_prepare_fb, which pins the backing BO for the framebuffer. However, there is no corresponding cleanup_fb callback (drm_gem_plane_helper_cleanup_fb) to unpin it. Whenever a framebuffer is replaced during a page flip or disabled, its pin count will never be decremented. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1
