From: Junrui Luo moonafterrain@outlook.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@gmail.com Reported-by: Junrui Luo moonafterrain@outlook.com Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Junrui Luo moonafterrain@outlook.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;
linux-stable-mirror@lists.linaro.org