mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] drm/vboxvideo: validate VBVA ring buffer offsets and cursor dimensions
@ 2026-09-19 22:35 Hui Peng
  0 siblings, 0 replies; only message in thread
From: Hui Peng @ 2026-09-19 22:35 UTC (permalink / raw)
  To: hansg, tzimmermann, simona, airlied; +Cc: dri-devel, linux-kernel

In drivers/gpu/drm/vboxvideo/ (vbox_main.c, vbox_mode.c, vbva_base.c),
validate VBVA ring buffer offsets against buffer_length and check cursor
dimensions before copying cursor data into HGSMI buffers.

Fixes: 131abc56e1ba ("drm/vboxvideo: Move the vboxvideo driver out of staging")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c
index aa6664542b20..8cf326661b57 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_main.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_main.c
@@ -115,6 +115,10 @@ int vbox_hw_init(struct vbox_private *vbox)
 
 	DRM_INFO("VRAM %08x\n", vbox->full_vram_size);
 
+	if (vbox->full_vram_size < VBVA_ADAPTER_INFORMATION_SIZE +
+				   vbox->num_crtcs * VBVA_MIN_BUFFER_SIZE)
+		return -EINVAL;
+
 	ret = pcim_request_region(pdev, 0, "vboxvideo");
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c
index 3c41238a8268..9a1d9e1aa92b 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_mode.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c
@@ -141,7 +141,8 @@ static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
 
 		if (!fb1) {
 			fb1 = fb;
-			if (fb1 == vbox->ddev.fb_helper->fb)
+			if (vbox->ddev.fb_helper &&
+			    fb1 == vbox->ddev.fb_helper->fb)
 				break;
 		} else if (fb != fb1) {
 			single_framebuffer = false;
@@ -363,7 +364,8 @@ static int vbox_cursor_atomic_check(struct drm_plane *plane,
 		return 0;
 
 	if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT ||
-	    width == 0 || height == 0)
+	    width == 0 || height == 0 ||
+	    width != new_state->fb->width || height != new_state->fb->height)
 		return -EINVAL;
 
 	return 0;
@@ -380,6 +382,7 @@ static void copy_cursor_image(u8 *src, u8 *dst, u32 width, u32 height,
 	size_t line_size = (width + 7) / 8;
 	u32 i, j;
 
+	memset(dst, 0, mask_size);
 	memcpy(dst + mask_size, src, width * height * 4);
 	for (i = 0; i < height; ++i)
 		for (j = 0; j < width; ++j)
diff --git a/drivers/gpu/drm/vboxvideo/vbva_base.c b/drivers/gpu/drm/vboxvideo/vbva_base.c
index 36bc9824ec3f..3a752be06f4e 100644
--- a/drivers/gpu/drm/vboxvideo/vbva_base.c
+++ b/drivers/gpu/drm/vboxvideo/vbva_base.c
@@ -21,18 +21,35 @@
 
 static u32 vbva_buffer_available(const struct vbva_buffer *vbva)
 {
-	s32 diff = vbva->data_offset - vbva->free_offset;
+	u32 data_len = READ_ONCE(vbva->data_len);
+	u32 data_offset = READ_ONCE(vbva->data_offset);
+	u32 free_offset = READ_ONCE(vbva->free_offset);
+	s32 diff;
 
-	return diff > 0 ? diff : vbva->data_len + diff;
+	if (!data_len || data_offset >= data_len || free_offset >= data_len)
+		return 0;
+
+	diff = data_offset - free_offset;
+
+	return diff > 0 ? diff : data_len + diff;
 }
 
 static void vbva_buffer_place_data_at(struct vbva_buf_ctx *vbva_ctx,
 				      const void *p, u32 len, u32 offset)
 {
 	struct vbva_buffer *vbva = vbva_ctx->vbva;
-	u32 bytes_till_boundary = vbva->data_len - offset;
-	u8 *dst = &vbva->data[offset];
-	s32 diff = len - bytes_till_boundary;
+	u32 data_len = READ_ONCE(vbva->data_len);
+	u32 bytes_till_boundary;
+	u8 *dst;
+	s32 diff;
+
+	if (data_len > vbva_ctx->buffer_length - sizeof(*vbva) ||
+	    offset >= data_len || len > data_len)
+		return;
+
+	bytes_till_boundary = data_len - offset;
+	dst = &vbva->data[offset];
+	diff = len - bytes_till_boundary;
 
 	if (diff <= 0) {
 		/* Chunk will not cross buffer boundary. */
@@ -93,6 +110,9 @@ bool vbva_write(struct vbva_buf_ctx *vbva_ctx, struct gen_pool *ctx,
 		vbva_buffer_place_data_at(vbva_ctx, p, chunk,
 					  vbva->free_offset);
 
+		if (!vbva->data_len)
+			return false;
+
 		vbva->free_offset = (vbva->free_offset + chunk) %
 				    vbva->data_len;
 		record->len_and_flags += chunk;
@@ -165,7 +185,7 @@ bool vbva_buffer_begin_update(struct vbva_buf_ctx *vbva_ctx,
 			      struct gen_pool *ctx)
 {
 	struct vbva_record *record;
-	u32 next;
+	u32 free_idx, next;
 
 	if (!vbva_ctx->vbva ||
 	    !(vbva_ctx->vbva->host_flags.host_events & VBVA_F_MODE_ENABLED))
@@ -173,7 +193,11 @@ bool vbva_buffer_begin_update(struct vbva_buf_ctx *vbva_ctx,
 
 	WARN_ON(vbva_ctx->buffer_overflow || vbva_ctx->record);
 
-	next = (vbva_ctx->vbva->record_free_index + 1) % VBVA_MAX_RECORDS;
+	free_idx = READ_ONCE(vbva_ctx->vbva->record_free_index);
+	if (free_idx >= VBVA_MAX_RECORDS)
+		return false;
+
+	next = (free_idx + 1) % VBVA_MAX_RECORDS;
 
 	/* Flush if all slots in the records queue are used */
 	if (next == vbva_ctx->vbva->record_first_index)
@@ -183,7 +207,7 @@ bool vbva_buffer_begin_update(struct vbva_buf_ctx *vbva_ctx,
 	if (next == vbva_ctx->vbva->record_first_index)
 		return false;
 
-	record = &vbva_ctx->vbva->records[vbva_ctx->vbva->record_free_index];
+	record = &vbva_ctx->vbva->records[free_idx];
 	record->len_and_flags = VBVA_F_RECORD_PARTIAL;
 	vbva_ctx->vbva->record_free_index = next;
 	/* Remember which record we are using. */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-19 22:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-19 22:35 [PATCH] drm/vboxvideo: validate VBVA ring buffer offsets and cursor dimensions Hui Peng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®