lkml.org 
[lkml]   [2019]   [Jul]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 108/293] floppy: fix out-of-bounds read in next_valid_format
    Date
    [ Upstream commit 5635f897ed83fd539df78e98ba69ee91592f9bb8 ]

    This fixes a global out-of-bounds read access in the next_valid_format
    function of the floppy driver.

    The values from autodetect field of the struct floppy_drive_params are
    used as indices for the floppy_type array in the next_valid_format
    function 'floppy_type[DP->autodetect[probed_format]].sect'.

    To trigger the bug, one could use a value out of range and set the drive
    parameters with the FDSETDRVPRM ioctl. A floppy disk is not required to
    be inserted.

    CAP_SYS_ADMIN is required to call FDSETDRVPRM.

    The patch adds the check for values of the autodetect field to be in the
    '0 <= x < ARRAY_SIZE(floppy_type)' range of the floppy_type array indices.

    The bug was found by syzkaller.

    Signed-off-by: Denis Efremov <efremov@ispras.ru>
    Tested-by: Willy Tarreau <w@1wt.eu>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/block/floppy.c | 18 ++++++++++++++++++
    1 file changed, 18 insertions(+)

    diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
    index 4c6c20376a83..a4f630ef2b75 100644
    --- a/drivers/block/floppy.c
    +++ b/drivers/block/floppy.c
    @@ -3386,6 +3386,20 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
    return 0;
    }

    +static bool valid_floppy_drive_params(const short autodetect[8])
    +{
    + size_t floppy_type_size = ARRAY_SIZE(floppy_type);
    + size_t i = 0;
    +
    + for (i = 0; i < 8; ++i) {
    + if (autodetect[i] < 0 ||
    + autodetect[i] >= floppy_type_size)
    + return false;
    + }
    +
    + return true;
    +}
    +
    static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
    unsigned long param)
    {
    @@ -3512,6 +3526,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
    SUPBOUND(size, strlen((const char *)outparam) + 1);
    break;
    case FDSETDRVPRM:
    + if (!valid_floppy_drive_params(inparam.dp.autodetect))
    + return -EINVAL;
    *UDP = inparam.dp;
    break;
    case FDGETDRVPRM:
    @@ -3709,6 +3725,8 @@ static int compat_setdrvprm(int drive,
    return -EPERM;
    if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params)))
    return -EFAULT;
    + if (!valid_floppy_drive_params(v.autodetect))
    + return -EINVAL;
    mutex_lock(&floppy_mutex);
    UDP->cmos = v.cmos;
    UDP->max_dtr = v.max_dtr;
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-07-29 21:39    [W:2.841 / U:0.356 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site