lkml.org 
[lkml]   [2017]   [Nov]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 16/96] dm bufio: fix integer overflow when limiting maximum cache size
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Eric Biggers <ebiggers@google.com>

    commit 74d4108d9e681dbbe4a2940ed8fdff1f6868184c upstream.

    The default max_cache_size_bytes for dm-bufio is meant to be the lesser
    of 25% of the size of the vmalloc area and 2% of the size of lowmem.
    However, on 32-bit systems the intermediate result in the expression

    (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100

    overflows, causing the wrong result to be computed. For example, on a
    32-bit system where the vmalloc area is 520093696 bytes, the result is
    1174405 rather than the expected 130023424, which makes the maximum
    cache size much too small (far less than 2% of lowmem). This causes
    severe performance problems for dm-verity users on affected systems.

    Fix this by using mult_frac() to correctly multiply by a percentage. Do
    this for all places in dm-bufio that multiply by a percentage. Also
    replace (VMALLOC_END - VMALLOC_START) with VMALLOC_TOTAL, which contrary
    to the comment is now defined in include/linux/vmalloc.h.

    Depends-on: 9993bc635 ("sched/x86: Fix overflow in cyc2ns_offset")
    Fixes: 95d402f057f2 ("dm: add bufio")
    Signed-off-by: Eric Biggers <ebiggers@google.com>
    Signed-off-by: Mike Snitzer <snitzer@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/md/dm-bufio.c | 15 ++++++---------
    1 file changed, 6 insertions(+), 9 deletions(-)

    --- a/drivers/md/dm-bufio.c
    +++ b/drivers/md/dm-bufio.c
    @@ -928,7 +928,8 @@ static void __get_memory_limit(struct dm
    buffers = c->minimum_buffers;

    *limit_buffers = buffers;
    - *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
    + *threshold_buffers = mult_frac(buffers,
    + DM_BUFIO_WRITEBACK_PERCENT, 100);
    }

    /*
    @@ -1829,19 +1830,15 @@ static int __init dm_bufio_init(void)
    memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
    memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);

    - mem = (__u64)((totalram_pages - totalhigh_pages) *
    - DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
    + mem = (__u64)mult_frac(totalram_pages - totalhigh_pages,
    + DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT;

    if (mem > ULONG_MAX)
    mem = ULONG_MAX;

    #ifdef CONFIG_MMU
    - /*
    - * Get the size of vmalloc space the same way as VMALLOC_TOTAL
    - * in fs/proc/internal.h
    - */
    - if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
    - mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
    + if (mem > mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100))
    + mem = mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100);
    #endif

    dm_bufio_default_cache_size = mem;

    \
     
     \ /
      Last update: 2017-11-28 13:30    [W:4.200 / U:0.304 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site