lkml.org 
[lkml]   [2013]   [Mar]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 101/153] tmpfs: fix use-after-free of mempolicy object
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Greg Thelen <gthelen@google.com>

    commit 5f00110f7273f9ff04ac69a5f85bb535a4fd0987 upstream.

    The tmpfs remount logic preserves filesystem mempolicy if the mpol=M
    option is not specified in the remount request. A new policy can be
    specified if mpol=M is given.

    Before this patch remounting an mpol bound tmpfs without specifying
    mpol= mount option in the remount request would set the filesystem's
    mempolicy object to a freed mempolicy object.

    To reproduce the problem boot a DEBUG_PAGEALLOC kernel and run:
    # mkdir /tmp/x

    # mount -t tmpfs -o size=100M,mpol=interleave nodev /tmp/x

    # grep /tmp/x /proc/mounts
    nodev /tmp/x tmpfs rw,relatime,size=102400k,mpol=interleave:0-3 0 0

    # mount -o remount,size=200M nodev /tmp/x

    # grep /tmp/x /proc/mounts
    nodev /tmp/x tmpfs rw,relatime,size=204800k,mpol=??? 0 0
    # note ? garbage in mpol=... output above

    # dd if=/dev/zero of=/tmp/x/f count=1
    # panic here

    Panic:
    BUG: unable to handle kernel NULL pointer dereference at (null)
    IP: [< (null)>] (null)
    [...]
    Oops: 0010 [#1] SMP DEBUG_PAGEALLOC
    Call Trace:
    mpol_shared_policy_init+0xa5/0x160
    shmem_get_inode+0x209/0x270
    shmem_mknod+0x3e/0xf0
    shmem_create+0x18/0x20
    vfs_create+0xb5/0x130
    do_last+0x9a1/0xea0
    path_openat+0xb3/0x4d0
    do_filp_open+0x42/0xa0
    do_sys_open+0xfe/0x1e0
    compat_sys_open+0x1b/0x20
    cstar_dispatch+0x7/0x1f

    Non-debug kernels will not crash immediately because referencing the
    dangling mpol will not cause a fault. Instead the filesystem will
    reference a freed mempolicy object, which will cause unpredictable
    behavior.

    The problem boils down to a dropped mpol reference below if
    shmem_parse_options() does not allocate a new mpol:

    config = *sbinfo
    shmem_parse_options(data, &config, true)
    mpol_put(sbinfo->mpol)
    sbinfo->mpol = config.mpol /* BUG: saves unreferenced mpol */

    This patch avoids the crash by not releasing the mempolicy if
    shmem_parse_options() doesn't create a new mpol.

    How far back does this issue go? I see it in both 2.6.36 and 3.3. I did
    not look back further.

    Signed-off-by: Greg Thelen <gthelen@google.com>
    Acked-by: Hugh Dickins <hughd@google.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    mm/shmem.c | 10 ++++++++--
    1 file changed, 8 insertions(+), 2 deletions(-)

    --- a/mm/shmem.c
    +++ b/mm/shmem.c
    @@ -2121,6 +2121,7 @@ static int shmem_remount_fs(struct super
    unsigned long inodes;
    int error = -EINVAL;

    + config.mpol = NULL;
    if (shmem_parse_options(data, &config, true))
    return error;

    @@ -2145,8 +2146,13 @@ static int shmem_remount_fs(struct super
    sbinfo->max_inodes = config.max_inodes;
    sbinfo->free_inodes = config.max_inodes - inodes;

    - mpol_put(sbinfo->mpol);
    - sbinfo->mpol = config.mpol; /* transfers initial ref */
    + /*
    + * Preserve previous mempolicy unless mpol remount option was specified.
    + */
    + if (config.mpol) {
    + mpol_put(sbinfo->mpol);
    + sbinfo->mpol = config.mpol; /* transfers initial ref */
    + }
    out:
    spin_unlock(&sbinfo->stat_lock);
    return error;



    \
     
     \ /
      Last update: 2013-03-04 05:41    [W:4.087 / U:0.112 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site