lkml.org 
[lkml]   [2018]   [Jun]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 48/61] iio:kfifo_buf: check for uint overflow
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Martin Kelly <mkelly@xevo.com>

    commit 3d13de4b027d5f6276c0f9d3a264f518747d83f2 upstream.

    Currently, the following causes a kernel OOPS in memcpy:

    echo 1073741825 > buffer/length
    echo 1 > buffer/enable

    Note that using 1073741824 instead of 1073741825 causes "write error:
    Cannot allocate memory" but no OOPS.

    This is because 1073741824 == 2^30 and 1073741825 == 2^30+1. Since kfifo
    rounds up to the nearest power of 2, it will actually call kmalloc with
    roundup_pow_of_two(length) * bytes_per_datum.

    Using length == 1073741825 and bytes_per_datum == 2, we get:

    kmalloc(roundup_pow_of_two(1073741825) * 2
    or kmalloc(2147483648 * 2)
    or kmalloc(4294967296)
    or kmalloc(UINT_MAX + 1)

    so this overflows to 0, causing kmalloc to return ZERO_SIZE_PTR and
    subsequent memcpy to fail once the device is enabled.

    Fix this by checking for overflow prior to allocating a kfifo. With this
    check added, the above code returns -EINVAL when enabling the buffer,
    rather than causing an OOPS.

    Signed-off-by: Martin Kelly <mkelly@xevo.com>
    cc: <Stable@vger.kernel.org>
    Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/iio/buffer/kfifo_buf.c | 7 +++++++
    1 file changed, 7 insertions(+)

    --- a/drivers/iio/buffer/kfifo_buf.c
    +++ b/drivers/iio/buffer/kfifo_buf.c
    @@ -24,6 +24,13 @@ static inline int __iio_allocate_kfifo(s
    if ((length == 0) || (bytes_per_datum == 0))
    return -EINVAL;

    + /*
    + * Make sure we don't overflow an unsigned int after kfifo rounds up to
    + * the next power of 2.
    + */
    + if (roundup_pow_of_two(length) > UINT_MAX / bytes_per_datum)
    + return -EINVAL;
    +
    return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
    bytes_per_datum, GFP_KERNEL);
    }

    \
     
     \ /
      Last update: 2018-06-05 19:09    [W:3.962 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site