lkml.org 
[lkml]   [2011]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[34-longterm 225/247] agp: fix arbitrary kernel memory writes
    Date
    From: Vasiliy Kulikov <segoon@openwall.com>

    -------------------
    This is a commit scheduled for the next v2.6.34 longterm release.
    If you see a problem with using this for longterm, please comment.
    -------------------

    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: Paul Gortmaker <paul.gortmaker@windriver.com>
    ---
    drivers/char/agp/generic.c | 11 ++++++++---
    1 files changed, 8 insertions(+), 3 deletions(-)

    diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
    index fb86708..13a3446 100644
    --- a/drivers/char/agp/generic.c
    +++ b/drivers/char/agp/generic.c
    @@ -1124,8 +1124,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
    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;
    @@ -1159,7 +1159,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
    {
    size_t i;
    struct agp_bridge_data *bridge;
    - int mask_type;
    + int mask_type, num_entries;

    bridge = mem->bridge;
    if (!bridge)
    @@ -1171,6 +1171,11 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
    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 */
    --
    1.7.4.4


    \
     
     \ /
      Last update: 2011-06-23 19:45    [W:0.021 / U:60.596 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site