Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e535976 authored by Willy Tarreau's avatar Willy Tarreau Committed by Greg Kroah-Hartman
Browse files

floppy: disable FDRAWCMD by default

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: default avatarMinh Yuan <yuanmingbuaa@gmail.com>
Reported-by: default avatar <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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c335e76a
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -39,6 +39,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
+32 −11
Original line number Diff line number Diff line
@@ -3023,6 +3023,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)
{
@@ -3234,6 +3236,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 */
@@ -3421,7 +3452,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(UDRS->fd_device);
	int i;
	int ret;
	int size;
	union inparam {
@@ -3572,16 +3602,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
		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;