lkml.org 
[lkml]   [2007]   [Feb]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 07/18] grow_buffers() infinite loop fix (CVE-2006-5757, CVE-2006-6060)
    -stable review patch.  If anyone has any objections, please let us know.

    ------------------
    From: Andrew Morton <akpm@osdl.org>

    If grow_buffers() is for some reason passed a block number which wants to lie
    outside the maximum-addressable pagecache range (PAGE_SIZE * 4G bytes) then it
    will accidentally truncate `index' and will then instnatiate a page at the
    wrong pagecache offset. This causes __getblk_slow() to go into an infinite
    loop.

    This can happen with corrupted disks, or with software errors elsewhere.

    Detect that, and handle it.

    Signed-off-by: Andrew Morton <akpm@osdl.org>
    Signed-off-by: Linus Torvalds <torvalds@osdl.org>
    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    fs/buffer.c | 21 +++++++++++++++++++--
    1 file changed, 19 insertions(+), 2 deletions(-)

    --- linux-2.6.18.7.orig/fs/buffer.c
    +++ linux-2.6.18.7/fs/buffer.c
    @@ -1179,8 +1179,21 @@ grow_buffers(struct block_device *bdev,
    } while ((size << sizebits) < PAGE_SIZE);

    index = block >> sizebits;
    - block = index << sizebits;

    + /*
    + * Check for a block which wants to lie outside our maximum possible
    + * pagecache index. (this comparison is done using sector_t types).
    + */
    + if (unlikely(index != block >> sizebits)) {
    + char b[BDEVNAME_SIZE];
    +
    + printk(KERN_ERR "%s: requested out-of-range block %llu for "
    + "device %s\n",
    + __FUNCTION__, (unsigned long long)block,
    + bdevname(bdev, b));
    + return -EIO;
    + }
    + block = index << sizebits;
    /* Create a page with the proper size buffers.. */
    page = grow_dev_page(bdev, block, index, size);
    if (!page)
    @@ -1207,12 +1220,16 @@ __getblk_slow(struct block_device *bdev,

    for (;;) {
    struct buffer_head * bh;
    + int ret;

    bh = __find_get_block(bdev, block, size);
    if (bh)
    return bh;

    - if (!grow_buffers(bdev, block, size))
    + ret = grow_buffers(bdev, block, size);
    + if (ret < 0)
    + return NULL;
    + if (ret == 0)
    free_more_memory();
    }
    }
    --
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-02-21 03:01    [W:0.021 / U:151.408 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site