Skip to content

Commit

Permalink
floppy: disable FDRAWCMD by default
Browse files Browse the repository at this point in the history
commit 233087c 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>
  • Loading branch information
wtarreau authored and gregkh committed May 9, 2022
1 parent 22d6a3a commit d91ca05
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
16 changes: 16 additions & 0 deletions drivers/block/Kconfig
Expand Up @@ -33,6 +33,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
Expand Down
43 changes: 32 additions & 11 deletions drivers/block/floppy.c
Expand Up @@ -2984,6 +2984,8 @@ static const char *drive_name(int type, int drive)
return "(null)";
}

#ifdef CONFIG_BLK_DEV_FD_RAWCMD

/* raw commands */
static void raw_cmd_done(int flag)
{
Expand Down Expand Up @@ -3183,6 +3185,35 @@ static int raw_cmd_ioctl(int cmd, void __user *param)
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 */
Expand Down Expand Up @@ -3371,7 +3402,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
{
int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(drive_state[drive].fd_device);
int i;
int ret;
int size;
union inparam {
Expand Down Expand Up @@ -3522,16 +3552,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
outparam = &write_errors[drive];
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;
Expand Down

0 comments on commit d91ca05

Please sign in to comment.