lkml.org 
[lkml]   [2011]   [Apr]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] [43/106] Squashfs: handle corruption of directory structure
    Date
    2.6.35-longterm review patch.  If anyone has any objections, please let me know.

    ------------------
    From: Phillip Lougher <phillip@lougher.demon.co.uk>

    commit 44cff8a9ee8a974f9e931df910688e7fc1f0b0f9 upstream.

    Handle the rare case where a directory metadata block is uncompressed and
    corrupted, leading to a kernel oops in directory scanning (memcpy).
    Normally corruption is detected at the decompression stage and dealt with
    then, however, this will not happen if:

    - metadata isn't compressed (users can optionally request no metadata
    compression), or
    - the compressed metadata block was larger than the original, in which
    case the uncompressed version was used, or
    - the data was corrupt after decompression

    This patch fixes this by adding some sanity checks against known maximum
    values.

    Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
    Signed-off-by: Andi Kleen <ak@linux.intel.com>

    ---
    fs/squashfs/dir.c | 9 +++++++++
    fs/squashfs/namei.c | 12 ++++++++++++
    2 files changed, 21 insertions(+)

    Index: linux-2.6.35.y/fs/squashfs/dir.c
    ===================================================================
    --- linux-2.6.35.y.orig/fs/squashfs/dir.c
    +++ linux-2.6.35.y/fs/squashfs/dir.c
    @@ -172,6 +172,11 @@ static int squashfs_readdir(struct file
    length += sizeof(dirh);

    dir_count = le32_to_cpu(dirh.count) + 1;
    +
    + /* dir_count should never be larger than 256 */
    + if (dir_count > 256)
    + goto failed_read;
    +
    while (dir_count--) {
    /*
    * Read directory entry.
    @@ -183,6 +188,10 @@ static int squashfs_readdir(struct file

    size = le16_to_cpu(dire->size) + 1;

    + /* size should never be larger than SQUASHFS_NAME_LEN */
    + if (size > SQUASHFS_NAME_LEN)
    + goto failed_read;
    +
    err = squashfs_read_metadata(inode->i_sb, dire->name,
    &block, &offset, size);
    if (err < 0)
    Index: linux-2.6.35.y/fs/squashfs/namei.c
    ===================================================================
    --- linux-2.6.35.y.orig/fs/squashfs/namei.c
    +++ linux-2.6.35.y/fs/squashfs/namei.c
    @@ -176,6 +176,11 @@ static struct dentry *squashfs_lookup(st
    length += sizeof(dirh);

    dir_count = le32_to_cpu(dirh.count) + 1;
    +
    + /* dir_count should never be larger than 256 */
    + if (dir_count > 256)
    + goto data_error;
    +
    while (dir_count--) {
    /*
    * Read directory entry.
    @@ -187,6 +192,10 @@ static struct dentry *squashfs_lookup(st

    size = le16_to_cpu(dire->size) + 1;

    + /* size should never be larger than SQUASHFS_NAME_LEN */
    + if (size > SQUASHFS_NAME_LEN)
    + goto data_error;
    +
    err = squashfs_read_metadata(dir->i_sb, dire->name,
    &block, &offset, size);
    if (err < 0)
    @@ -228,6 +237,9 @@ exit_lookup:
    d_add(dentry, inode);
    return ERR_PTR(0);

    +data_error:
    + err = -EIO;
    +
    read_failure:
    ERROR("Unable to read directory block [%llx:%x]\n",
    squashfs_i(dir)->start + msblk->directory_table,

    \
     
     \ /
      Last update: 2011-04-26 23:35    [W:4.682 / U:1.332 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site