lkml.org 
[lkml]   [2022]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 01/78] floppy: disable FDRAWCMD by default
    Date
    From: Willy Tarreau <w@1wt.eu>

    commit 233087ca063686964a53c829d547c7571e3f67bf upstream.

    Minh Yuan reported a concurrency use-after-free issue in the floppy code
    between raw_cmd_ioctl and seek_interrupt.

    [ It turns out this has been around, and that others have reported the
    KASAN splats over the years, but Minh Yuan had a reproducer for it and
    so gets primary credit for reporting it for this fix - Linus ]

    The problem is, this driver tends to break very easily and nowadays,
    nobody is expected to use FDRAWCMD anyway since it was used to
    manipulate non-standard formats. The risk of breaking the driver is
    higher than the risk presented by this race, and accessing the device
    requires privileges anyway.

    Let's just add a config option to completely disable this ioctl and
    leave it disabled by default. Distros shouldn't use it, and only those
    running on antique hardware might need to enable it.

    Link: https://lore.kernel.org/all/000000000000b71cdd05d703f6bf@google.com/
    Link: https://lore.kernel.org/lkml/CAKcFiNC=MfYVW-Jt9A3=FPJpTwCD2PL_ULNCpsCVE5s8ZeBQgQ@mail.gmail.com
    Link: https://lore.kernel.org/all/CAEAjamu1FRhz6StCe_55XY5s389ZP_xmCF69k987En+1z53=eg@mail.gmail.com
    Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
    Reported-by: syzbot+8e8958586909d62b6840@syzkaller.appspotmail.com
    Reported-by: cruise k <cruise4k@gmail.com>
    Reported-by: Kyungtae Kim <kt0755@gmail.com>
    Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
    Tested-by: Denis Efremov <efremov@linux.com>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/block/Kconfig | 16 ++++++++++++++++
    drivers/block/floppy.c | 43 ++++++++++++++++++++++++++++++++-----------
    2 files changed, 48 insertions(+), 11 deletions(-)

    --- a/drivers/block/Kconfig
    +++ b/drivers/block/Kconfig
    @@ -35,6 +35,22 @@ config BLK_DEV_FD
    To compile this driver as a module, choose M here: the
    module will be called floppy.

    +config BLK_DEV_FD_RAWCMD
    + bool "Support for raw floppy disk commands (DEPRECATED)"
    + depends on BLK_DEV_FD
    + help
    + If you want to use actual physical floppies and expect to do
    + special low-level hardware accesses to them (access and use
    + non-standard formats, for example), then enable this.
    +
    + Note that the code enabled by this option is rarely used and
    + might be unstable or insecure, and distros should not enable it.
    +
    + Note: FDRAWCMD is deprecated and will be removed from the kernel
    + in the near future.
    +
    + If unsure, say N.
    +
    config AMIGA_FLOPPY
    tristate "Amiga floppy support"
    depends on AMIGA
    --- a/drivers/block/floppy.c
    +++ b/drivers/block/floppy.c
    @@ -3018,6 +3018,8 @@ static const char *drive_name(int type,
    return "(null)";
    }

    +#ifdef CONFIG_BLK_DEV_FD_RAWCMD
    +
    /* raw commands */
    static void raw_cmd_done(int flag)
    {
    @@ -3229,6 +3231,35 @@ static int raw_cmd_ioctl(int cmd, void _
    return ret;
    }

    +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
    + void __user *param)
    +{
    + int ret;
    +
    + pr_warn_once("Note: FDRAWCMD is deprecated and will be removed from the kernel in the near future.\n");
    +
    + if (type)
    + return -EINVAL;
    + if (lock_fdc(drive))
    + return -EINTR;
    + set_floppy(drive);
    + ret = raw_cmd_ioctl(cmd, param);
    + if (ret == -EINTR)
    + return -EINTR;
    + process_fd_request();
    + return ret;
    +}
    +
    +#else /* CONFIG_BLK_DEV_FD_RAWCMD */
    +
    +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
    + void __user *param)
    +{
    + return -EOPNOTSUPP;
    +}
    +
    +#endif
    +
    static int invalidate_drive(struct block_device *bdev)
    {
    /* invalidate the buffer track to force a reread */
    @@ -3416,7 +3447,6 @@ static int fd_locked_ioctl(struct block_
    {
    int drive = (long)bdev->bd_disk->private_data;
    int type = ITYPE(UDRS->fd_device);
    - int i;
    int ret;
    int size;
    union inparam {
    @@ -3567,16 +3597,7 @@ static int fd_locked_ioctl(struct block_
    outparam = UDRWE;
    break;
    case FDRAWCMD:
    - if (type)
    - return -EINVAL;
    - if (lock_fdc(drive))
    - return -EINTR;
    - set_floppy(drive);
    - i = raw_cmd_ioctl(cmd, (void __user *)param);
    - if (i == -EINTR)
    - return -EINTR;
    - process_fd_request();
    - return i;
    + return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param);
    case FDTWADDLE:
    if (lock_fdc(drive))
    return -EINTR;

    \
     
     \ /
      Last update: 2022-05-10 15:20    [W:4.137 / U:0.228 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site