| From 194b3da873fd334ef183806db751473512af29ce Mon Sep 17 00:00:00 2001 |
| From: Vasiliy Kulikov <segoon@openwall.com> |
| Date: Thu, 14 Apr 2011 20:55:16 +0400 |
| Subject: agp: fix arbitrary kernel memory writes |
| |
| From: Vasiliy Kulikov <segoon@openwall.com> |
| |
| commit 194b3da873fd334ef183806db751473512af29ce upstream. |
| |
| pg_start is copied from userspace on AGPIOC_BIND and AGPIOC_UNBIND ioctl |
| cmds of agp_ioctl() and passed to agpioc_bind_wrap(). As said in the |
| comment, (pg_start + mem->page_count) may wrap in case of AGPIOC_BIND, |
| and it is not checked at all in case of AGPIOC_UNBIND. As a result, user |
| with sufficient privileges (usually "video" group) may generate either |
| local DoS or privilege escalation. |
| |
| Signed-off-by: Vasiliy Kulikov <segoon@openwall.com> |
| Signed-off-by: Dave Airlie <airlied@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/char/agp/generic.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/char/agp/generic.c |
| +++ b/drivers/char/agp/generic.c |
| @@ -1123,8 +1123,8 @@ int agp_generic_insert_memory(struct agp |
| return -EINVAL; |
| } |
| |
| - /* AK: could wrap */ |
| - if ((pg_start + mem->page_count) > num_entries) |
| + if (((pg_start + mem->page_count) > num_entries) || |
| + ((pg_start + mem->page_count) < pg_start)) |
| return -EINVAL; |
| |
| j = pg_start; |
| @@ -1158,7 +1158,7 @@ int agp_generic_remove_memory(struct agp |
| { |
| size_t i; |
| struct agp_bridge_data *bridge; |
| - int mask_type; |
| + int mask_type, num_entries; |
| |
| bridge = mem->bridge; |
| if (!bridge) |
| @@ -1170,6 +1170,11 @@ int agp_generic_remove_memory(struct agp |
| if (type != mem->type) |
| return -EINVAL; |
| |
| + num_entries = agp_num_entries(); |
| + if (((pg_start + mem->page_count) > num_entries) || |
| + ((pg_start + mem->page_count) < pg_start)) |
| + return -EINVAL; |
| + |
| mask_type = bridge->driver->agp_type_to_mask_type(bridge, type); |
| if (mask_type != 0) { |
| /* The generic routines know nothing of memory types */ |