Commit 233087ca authored by Willy Tarreau's avatar Willy Tarreau Committed by Linus Torvalds

floppy: disable FDRAWCMD by default

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.comReported-by: default avatarMinh Yuan <yuanmingbuaa@gmail.com>
Reported-by: syzbot+8e8958586909d62b6840@syzkaller.appspotmail.com
Reported-by: default avatarcruise k <cruise4k@gmail.com>
Reported-by: default avatarKyungtae Kim <kt0755@gmail.com>
Suggested-by: default avatarLinus Torvalds <torvalds@linuxfoundation.org>
Tested-by: default avatarDenis Efremov <efremov@linux.com>
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 46cf2c61
...@@ -33,6 +33,22 @@ config BLK_DEV_FD ...@@ -33,6 +33,22 @@ config BLK_DEV_FD
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called floppy. 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 config AMIGA_FLOPPY
tristate "Amiga floppy support" tristate "Amiga floppy support"
depends on AMIGA depends on AMIGA
......
...@@ -2982,6 +2982,8 @@ static const char *drive_name(int type, int drive) ...@@ -2982,6 +2982,8 @@ static const char *drive_name(int type, int drive)
return "(null)"; return "(null)";
} }
#ifdef CONFIG_BLK_DEV_FD_RAWCMD
/* raw commands */ /* raw commands */
static void raw_cmd_done(int flag) static void raw_cmd_done(int flag)
{ {
...@@ -3181,6 +3183,35 @@ static int raw_cmd_ioctl(int cmd, void __user *param) ...@@ -3181,6 +3183,35 @@ static int raw_cmd_ioctl(int cmd, void __user *param)
return ret; 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) static int invalidate_drive(struct block_device *bdev)
{ {
/* invalidate the buffer track to force a reread */ /* invalidate the buffer track to force a reread */
...@@ -3369,7 +3400,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int ...@@ -3369,7 +3400,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
{ {
int drive = (long)bdev->bd_disk->private_data; int drive = (long)bdev->bd_disk->private_data;
int type = ITYPE(drive_state[drive].fd_device); int type = ITYPE(drive_state[drive].fd_device);
int i;
int ret; int ret;
int size; int size;
union inparam { union inparam {
...@@ -3520,16 +3550,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int ...@@ -3520,16 +3550,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
outparam = &write_errors[drive]; outparam = &write_errors[drive];
break; break;
case FDRAWCMD: case FDRAWCMD:
if (type) return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param);
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;
case FDTWADDLE: case FDTWADDLE:
if (lock_fdc(drive)) if (lock_fdc(drive))
return -EINTR; return -EINTR;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment