[<prev] [next>] [day] [month] [year] [list]
Message-ID:
<MEAPR01MB31582BAF75B78750BE6B2152AFFDA@MEAPR01MB3158.ausprd01.prod.outlook.com>
Date: Wed, 29 Oct 2025 00:25:24 +0800
From: moonafterrain@...look.com
To: David Airlie <airlied@...hat.com>
Cc: dri-devel@...ts.freedesktop.org,
linux-kernel@...r.kernel.org,
stable@...r.kernel.org,
Yuhao Jiang <danisjiang@...il.com>,
Junrui Luo <moonafterrain@...look.com>
Subject: [PATCH] agp/uninorth: fix out-of-bounds access with negative pg_start
From: Junrui Luo <moonafterrain@...look.com>
The uninorth_insert_memory and uninorth_remove_memory functions lack
proper validation of the pg_start parameter before using it as an array
index into the GATT (Graphics Address Translation Table).
The current bounds check fails to reject negative
pg_start values and potentially causes out-of-bounds writes.
Fix by explicitly checking that pg_start is non-negative before
performing bounds checking. This makes the security requirement clear
and does not rely on implicit type conversion behavior.
The uninorth_remove_memory function has no bounds checking at all, so
add the same validation there.
Reported-by: Yuhao Jiang <danisjiang@...il.com>
Reported-by: Junrui Luo <moonafterrain@...look.com>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@...r.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@...look.com>
---
drivers/char/agp/uninorth-agp.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index b8d7115b8c9e..4e0b949016f7 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -169,7 +169,9 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int ty
temp = agp_bridge->current_size;
num_entries = A_SIZE_32(temp)->num_entries;
- if ((pg_start + mem->page_count) > num_entries)
+ if (pg_start < 0 ||
+ (pg_start + mem->page_count) > num_entries ||
+ (pg_start + mem->page_count) < pg_start)
return -EINVAL;
gp = (u32 *) &agp_bridge->gatt_table[pg_start];
@@ -200,6 +202,9 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int ty
static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{
size_t i;
+ int num_entries;
+ void *temp;
+
u32 *gp;
int mask_type;
@@ -215,6 +220,14 @@ static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int ty
if (mem->page_count == 0)
return 0;
+ temp = agp_bridge->current_size;
+ num_entries = A_SIZE_32(temp)->num_entries;
+
+ if (pg_start < 0 ||
+ (pg_start + mem->page_count) > num_entries ||
+ (pg_start + mem->page_count) < pg_start)
+ return -EINVAL;
+
gp = (u32 *) &agp_bridge->gatt_table[pg_start];
for (i = 0; i < mem->page_count; ++i) {
gp[i] = scratch_value;
--
2.51.1.dirty
Powered by blists - more mailing lists