lkml.org 
[lkml]   [2011]   [Apr]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[60/74] Squashfs: handle corruption of directory structure
    2.6.32-longterm review patch.  If anyone has any objections, please let us 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>

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

    --- a/fs/squashfs/dir.c
    +++ b/fs/squashfs/dir.c
    @@ -173,6 +173,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.
    @@ -184,6 +189,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)
    --- a/fs/squashfs/namei.c
    +++ b/fs/squashfs/namei.c
    @@ -175,6 +175,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.
    @@ -186,6 +191,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)
    @@ -227,6 +236,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-13 18:01    [W:4.656 / U:0.384 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site