All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hui Peng <benquike@gmail.com>
To: rubenru09@aol.com, tzimmermann@suse.de, simona@ffwll.ch,
	airlied@redhat.com
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: [PATCH] drm/gud: fix bulk_len divide-by-zero, connector bitmap OOB, and short USB reads
Date: Sat, 19 Sep 2026 22:35:10 +0000	[thread overview]
Message-ID: <20260919223510.3888975-1-benquike@gmail.com> (raw)

In drivers/gpu/drm/gud/ (gud_drv.c, gud_pipe.c, gud_connector.c), ensure
gdrm->bulk_len >= max_pitch so lines = bulk_len / pitch cannot be 0 in
gud_flush_damage(), cap num_connectors to GUD_CONNECTORS_MAX, and reject
short USB control transfers in gud_usb_get().

Fixes: 40e1a70b4aed ("drm: Add GUD USB Display driver")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index 8141c3a1e30a..1bf0495bf43f 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -569,7 +569,7 @@ static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_conn
 			continue; /* not a DRM property */
 
 		property = gud_connector_property_lookup(connector, prop);
-		if (drm_WARN_ON(drm, IS_ERR(property)))
+		if (drm_WARN_ON(drm, IS_ERR_OR_NULL(property)))
 			continue;
 
 		state_val = gud_connector_tv_state_val(prop, &gconn->initial_tv_state);
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 3a1b9e2a2eaa..f69b0e6e2ee0 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -328,7 +328,7 @@ static int gud_stats_debugfs(struct seq_file *m, void *data)
 		seq_puts(m, " none");
 	seq_puts(m, "\n");
 
-	if (gdrm->compression) {
+	if (gdrm->compression && gdrm->stats_actual_length) {
 		u64 remainder;
 		u64 ratio = div64_u64_rem(gdrm->stats_length, gdrm->stats_actual_length,
 					  &remainder);
@@ -427,6 +427,8 @@ static void gud_free_buffers_and_mutex(void *data)
 {
 	struct gud_device *gdrm = data;
 
+	vfree(gdrm->shadow_buf);
+	gdrm->shadow_buf = NULL;
 	vfree(gdrm->compress_buf);
 	gdrm->compress_buf = NULL;
 	sg_free_table(&gdrm->bulk_sgt);
@@ -443,7 +445,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	struct usb_endpoint_descriptor *bulk_out;
 	struct gud_display_descriptor_req desc;
 	struct device *dev = &intf->dev;
-	size_t max_buffer_size = 0;
+	size_t max_buffer_size = 0, max_pitch = 0;
 	struct gud_device *gdrm;
 	struct drm_device *drm;
 	struct device *dma_dev;
@@ -495,6 +497,10 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 		put_device(dma_dev);
 	} else {
 		dev_warn(dev, "buffer sharing not supported"); /* not an error */
+	if (!drm->mode_config.min_width || !drm->mode_config.min_height ||
+	    drm->mode_config.max_width < drm->mode_config.min_width ||
+	    drm->mode_config.max_height < drm->mode_config.min_height)
+		return -EINVAL;
 	}
 
 	/* Mode config init */
@@ -523,7 +529,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	num_formats_dev = ret;
 	for (i = 0; i < num_formats_dev; i++) {
 		const struct drm_format_info *info;
-		size_t fmt_buf_size;
+		size_t fmt_buf_size, fmt_pitch;
 		u32 format;
 
 		format = gud_to_fourcc(formats_dev[i]);
@@ -562,8 +568,9 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 			break;
 		}
 
-		fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
-			       drm->mode_config.max_height;
+		fmt_pitch = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width);
+		fmt_buf_size = fmt_pitch * drm->mode_config.max_height;
+		max_pitch = max(max_pitch, fmt_pitch);
 		max_buffer_size = max(max_buffer_size, fmt_buf_size);
 
 		if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
@@ -588,9 +595,13 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	if (desc.max_buffer_size)
 		max_buffer_size = le32_to_cpu(desc.max_buffer_size);
+	if (max_buffer_size < max_pitch)
+		max_buffer_size = max_pitch;
 	/* Prevent a misbehaving device from allocating loads of RAM. 4096x4096@XRGB8888 = 64 MB */
 	if (max_buffer_size > SZ_64M)
 		max_buffer_size = SZ_64M;
+	if (max_buffer_size < max_pitch)
+		return -EINVAL;
 
 	gdrm->bulk_pipe = usb_sndbulkpipe(interface_to_usbdev(intf), usb_endpoint_num(bulk_out));
 	gdrm->bulk_len = max_buffer_size;
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 5ef887d8485a..1f08226b23b2 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -156,10 +156,14 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
 			  struct drm_format_conv_state *fmtcnv_state)
 {
 	u8 compression = gdrm->compression;
+	unsigned int block_width = drm_format_info_block_width(format, 0);
 	struct iosys_map dst;
 	void *vaddr, *buf;
 	size_t pitch, len;
 
+	if (block_width > 1)
+		rect->x1 = ALIGN_DOWN(rect->x1, block_width);
+
 	pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(rect));
 	len = pitch * drm_rect_height(rect);
 	if (len > gdrm->bulk_len)
@@ -327,7 +331,7 @@ static void gud_flush_damage(struct gud_device *gdrm, struct drm_framebuffer *fb
 {
 	struct drm_format_conv_state fmtcnv_state = DRM_FORMAT_CONV_STATE_INIT;
 	const struct drm_format_info *format;
-	unsigned int i, lines;
+	unsigned int i, lines, block_width;
 	size_t pitch;
 	int ret;
 
@@ -335,12 +339,21 @@ static void gud_flush_damage(struct gud_device *gdrm, struct drm_framebuffer *fb
 	if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
 		format = gdrm->xrgb8888_emulation_format;
 
+	block_width = drm_format_info_block_width(format, 0);
+	if (block_width > 1)
+		damage->x1 = ALIGN_DOWN(damage->x1, block_width);
+
 	/* Split update if it's too big */
 	pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(damage));
 	lines = drm_rect_height(damage);
 
+	if (!pitch || !lines)
+		return;
+
 	if (gdrm->bulk_len < lines * pitch)
 		lines = gdrm->bulk_len / pitch;
+	if (!lines)
+		return;
 
 	for (i = 0; i < DIV_ROUND_UP(drm_rect_height(damage), lines); i++) {
 		struct drm_rect rect = *damage;
@@ -399,6 +412,13 @@ static int gud_fb_queue_damage(struct gud_device *gdrm, struct drm_framebuffer *
 
 	mutex_lock(&gdrm->damage_lock);
 
+	if (gdrm->shadow_buf && gdrm->fb &&
+	    (fb->pitches[0] != gdrm->fb->pitches[0] || fb->height != gdrm->fb->height)) {
+		vfree(gdrm->shadow_buf);
+		gdrm->shadow_buf = NULL;
+		gud_clear_damage(gdrm);
+	}
+
 	if (!gdrm->shadow_buf) {
 		gdrm->shadow_buf = vcalloc(fb->pitches[0], fb->height);
 		if (!gdrm->shadow_buf) {
@@ -562,8 +582,8 @@ int gud_plane_atomic_check(struct drm_plane *plane,
 			goto out;
 		}
 
-		req->properties[num_properties + i].prop = cpu_to_le16(prop);
-		req->properties[num_properties + i].val = cpu_to_le64(val);
+		req->properties[num_properties].prop = cpu_to_le16(prop);
+		req->properties[num_properties].val = cpu_to_le64(val);
 		num_properties++;
 	}
 

             reply	other threads:[~2026-09-21  7:01 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19 22:35 Hui Peng [this message]
2026-09-19 22:57 ` [PATCH] drm/gud: fix bulk_len divide-by-zero, connector bitmap OOB, and short USB reads sashiko-bot
2026-10-06 13:02 ` Ruben Wauters

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260919223510.3888975-1-benquike@gmail.com \
    --to=benquike@gmail.com \
    --cc=airlied@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rubenru09@aol.com \
    --cc=simona@ffwll.ch \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.