]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fix up floppy backports for 4.9 and 4.4
authorSasha Levin <sashal@kernel.org>
Wed, 24 Jul 2019 03:09:11 +0000 (23:09 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 24 Jul 2019 04:09:07 +0000 (00:09 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
12 files changed:
queue-4.4/floppy-fix-div-by-zero-in-setup_format_params.patch
queue-4.4/floppy-fix-invalid-pointer-dereference-in-drive_name.patch
queue-4.4/floppy-fix-out-of-bounds-read-in-copy_buffer.patch
queue-4.4/floppy-fix-out-of-bounds-read-in-next_valid_format.patch
queue-4.4/series
queue-4.4/take-floppy-compat-ioctls-to-sodding-floppy.c.patch [new file with mode: 0644]
queue-4.9/floppy-fix-div-by-zero-in-setup_format_params.patch
queue-4.9/floppy-fix-invalid-pointer-dereference-in-drive_name.patch
queue-4.9/floppy-fix-out-of-bounds-read-in-copy_buffer.patch
queue-4.9/floppy-fix-out-of-bounds-read-in-next_valid_format.patch
queue-4.9/series
queue-4.9/take-floppy-compat-ioctls-to-sodding-floppy.c.patch [new file with mode: 0644]

index 9c2efe5eb100c2614f17ceed6f1e7474bc6c8705..ead84fa29a1403017af67f7945e2382f7de04441 100644 (file)
@@ -1,4 +1,4 @@
-From 33b5b1783bcff0ca134b4d7b2b1e3da3d83b5f43 Mon Sep 17 00:00:00 2001
+From 26cf267767b46f0ea5c6312838085fa01c7a1b9c Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:20 +0300
 Subject: floppy: fix div-by-zero in setup_format_params
@@ -29,14 +29,15 @@ 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>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
- drivers/block/floppy.c |    5 +++++
+ drivers/block/floppy.c | 5 +++++
  1 file changed, 5 insertions(+)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 5fe9e899d2a6..3fca5246bbaf 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -2113,6 +2113,9 @@ static void setup_format_params(int trac
+@@ -2114,6 +2114,9 @@ static void setup_format_params(int track)
        raw_cmd->kernel_data = floppy_track_buffer;
        raw_cmd->length = 4 * F_SECT_PER_TRACK;
  
@@ -46,7 +47,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        /* allow for about 30ms for data transport per track */
        head_shift = (F_SECT_PER_TRACK + 5) / 6;
  
-@@ -3235,6 +3238,8 @@ static int set_geometry(unsigned int cmd
+@@ -3236,6 +3239,8 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
        /* sanity checking for parameters. */
        if (g->sect <= 0 ||
            g->head <= 0 ||
@@ -55,3 +56,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
            g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
            /* check if reserved bits are set */
            (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
+-- 
+2.20.1
+
index ae36d7e6a40d5bbe8f821e3ac4a85cf83c441535..0e24af40baf98550925a706e401fc2a9defe150d 100644 (file)
@@ -1,11 +1,9 @@
-From 9b04609b784027968348796a18f601aed9db3789 Mon Sep 17 00:00:00 2001
+From 2e8dfc077179a0a9886c94e2467a392024d16f3a Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:22 +0300
 Subject: floppy: fix invalid pointer dereference in drive_name
 
-From: Denis Efremov <efremov@ispras.ru>
-
-commit 9b04609b784027968348796a18f601aed9db3789 upstream.
+[ Upstream commit 9b04609b784027968348796a18f601aed9db3789 ]
 
 This fixes the invalid pointer dereference in the drive_name function of
 the floppy driver.
@@ -30,15 +28,16 @@ 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
+Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- drivers/block/floppy.c |    9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
+ drivers/block/floppy.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index e319fb6c96a7..013c25bad540 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3383,7 +3383,8 @@ static int fd_getgeo(struct block_device
+@@ -3384,7 +3384,8 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
  }
  
@@ -48,7 +47,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  {
        size_t floppy_type_size = ARRAY_SIZE(floppy_type);
        size_t i = 0;
-@@ -3394,6 +3395,9 @@ static bool valid_floppy_drive_params(co
+@@ -3395,6 +3396,9 @@ static bool valid_floppy_drive_params(const short autodetect[8])
                        return false;
        }
  
@@ -58,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        return true;
  }
  
-@@ -3523,7 +3527,8 @@ static int fd_locked_ioctl(struct block_
+@@ -3524,7 +3528,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:
@@ -68,3 +67,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
                        return -EINVAL;
                *UDP = inparam.dp;
                break;
+@@ -3723,7 +3728,7 @@ 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))
++      if (!valid_floppy_drive_params(v.autodetect, v.native_format))
+               return -EINVAL;
+       mutex_lock(&floppy_mutex);
+       UDP->cmos = v.cmos;
+-- 
+2.20.1
+
index 5bf0eaa9a214846e07183f5eb86c22236d4a62ff..45a81f32716c8538f4eb0fc2113b1956824f2a57 100644 (file)
@@ -1,4 +1,4 @@
-From ab1e593f24d8a821cb8b37e8c3562e72c4fb1cd0 Mon Sep 17 00:00:00 2001
+From 7f25f4a37e8351cf70762583aa024bd229466db5 Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:23 +0300
 Subject: floppy: fix out-of-bounds read in copy_buffer
@@ -26,14 +26,15 @@ 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>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
- drivers/block/floppy.c |    6 ++++--
+ drivers/block/floppy.c | 6 ++++--
  1 file changed, 4 insertions(+), 2 deletions(-)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 013c25bad540..35b2d2c86a1f 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3236,8 +3236,10 @@ static int set_geometry(unsigned int cmd
+@@ -3237,8 +3237,10 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
        int cnt;
  
        /* sanity checking for parameters. */
@@ -46,3 +47,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
            /* check for zero in F_SECT_PER_TRACK */
            (unsigned char)((g->sect << 2) >> FD_SIZECODE(g)) == 0 ||
            g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
+-- 
+2.20.1
+
index 860a525b1f01d8fc9cb28bd76669d1f3657709e9..a85de5de3d440e6bf669f81a8e97fee24e828038 100644 (file)
@@ -1,11 +1,9 @@
-From 5635f897ed83fd539df78e98ba69ee91592f9bb8 Mon Sep 17 00:00:00 2001
+From 57927747a6b775b792d184a51a53c6bf101e92c1 Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:21 +0300
 Subject: floppy: fix out-of-bounds read in next_valid_format
 
-From: Denis Efremov <efremov@ispras.ru>
-
-commit 5635f897ed83fd539df78e98ba69ee91592f9bb8 upstream.
+[ Upstream commit 5635f897ed83fd539df78e98ba69ee91592f9bb8 ]
 
 This fixes a global out-of-bounds read access in the next_valid_format
 function of the floppy driver.
@@ -28,15 +26,16 @@ 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
+Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- drivers/block/floppy.c |   16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
+ drivers/block/floppy.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 3fca5246bbaf..e319fb6c96a7 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3383,6 +3383,20 @@ static int fd_getgeo(struct block_device
+@@ -3384,6 +3384,20 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
  }
  
@@ -57,7 +56,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                    unsigned long param)
  {
-@@ -3509,6 +3523,8 @@ static int fd_locked_ioctl(struct block_
+@@ -3510,6 +3524,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:
@@ -66,3 +65,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
                *UDP = inparam.dp;
                break;
        case FDGETDRVPRM:
+@@ -3707,6 +3723,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
+
index 842c43ad7a1b3478b9e9f008166cd12d790d17d1..72363cf909a0b8b3527fb95ab4df14dfd29810a4 100644 (file)
@@ -53,10 +53,6 @@ bluetooth-hci_bcsp-fix-memory-leak-in-rx_skb.patch
 bluetooth-6lowpan-search-for-destination-address-in-.patch
 bluetooth-check-state-in-l2cap_disconnect_rsp.patch
 bluetooth-validate-ble-connection-interval-updates.patch
-floppy-fix-div-by-zero-in-setup_format_params.patch
-floppy-fix-out-of-bounds-read-in-next_valid_format.patch
-floppy-fix-invalid-pointer-dereference-in-drive_name.patch
-floppy-fix-out-of-bounds-read-in-copy_buffer.patch
 crypto-ghash-fix-unaligned-memory-access-in-ghash_setkey.patch
 crypto-arm64-sha1-ce-correct-digest-for-empty-data-in-finup.patch
 crypto-arm64-sha2-ce-correct-digest-for-empty-data-in-finup.patch
@@ -73,3 +69,8 @@ drm-nouveau-i2c-enable-i2c-pads-busses-during-preinit.patch
 padata-use-smp_mb-in-padata_reorder-to-avoid-orphaned-padata-jobs.patch
 9p-virtio-add-cleanup-path-in-p9_virtio_init.patch
 pci-do-not-poll-for-pme-if-the-device-is-in-d3cold.patch
+take-floppy-compat-ioctls-to-sodding-floppy.c.patch
+floppy-fix-div-by-zero-in-setup_format_params.patch
+floppy-fix-out-of-bounds-read-in-next_valid_format.patch
+floppy-fix-invalid-pointer-dereference-in-drive_name.patch
+floppy-fix-out-of-bounds-read-in-copy_buffer.patch
diff --git a/queue-4.4/take-floppy-compat-ioctls-to-sodding-floppy.c.patch b/queue-4.4/take-floppy-compat-ioctls-to-sodding-floppy.c.patch
new file mode 100644 (file)
index 0000000..39cce75
--- /dev/null
@@ -0,0 +1,745 @@
+From b56b2384505e0d7032b45a5f4edbc3e451271c84 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 27 Jun 2017 15:47:56 -0400
+Subject: take floppy compat ioctls to sodding floppy.c
+
+[ Upstream commit 229b53c9bf4e1132a4aa6feb9632a7a1f1d08c5c ]
+
+all other drivers recognizing those ioctls are very much *not*
+biarch.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/compat_ioctl.c   | 340 -----------------------------------------
+ drivers/block/floppy.c | 328 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 328 insertions(+), 340 deletions(-)
+
+diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
+index f678c733df40..d2c46454ffa8 100644
+--- a/block/compat_ioctl.c
++++ b/block/compat_ioctl.c
+@@ -4,7 +4,6 @@
+ #include <linux/cdrom.h>
+ #include <linux/compat.h>
+ #include <linux/elevator.h>
+-#include <linux/fd.h>
+ #include <linux/hdreg.h>
+ #include <linux/slab.h>
+ #include <linux/syscalls.h>
+@@ -209,318 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
+ #define BLKBSZSET_32          _IOW(0x12, 113, int)
+ #define BLKGETSIZE64_32               _IOR(0x12, 114, int)
+-struct compat_floppy_drive_params {
+-      char            cmos;
+-      compat_ulong_t  max_dtr;
+-      compat_ulong_t  hlt;
+-      compat_ulong_t  hut;
+-      compat_ulong_t  srt;
+-      compat_ulong_t  spinup;
+-      compat_ulong_t  spindown;
+-      unsigned char   spindown_offset;
+-      unsigned char   select_delay;
+-      unsigned char   rps;
+-      unsigned char   tracks;
+-      compat_ulong_t  timeout;
+-      unsigned char   interleave_sect;
+-      struct floppy_max_errors max_errors;
+-      char            flags;
+-      char            read_track;
+-      short           autodetect[8];
+-      compat_int_t    checkfreq;
+-      compat_int_t    native_format;
+-};
+-
+-struct compat_floppy_drive_struct {
+-      signed char     flags;
+-      compat_ulong_t  spinup_date;
+-      compat_ulong_t  select_date;
+-      compat_ulong_t  first_read_date;
+-      short           probed_format;
+-      short           track;
+-      short           maxblock;
+-      short           maxtrack;
+-      compat_int_t    generation;
+-      compat_int_t    keep_data;
+-      compat_int_t    fd_ref;
+-      compat_int_t    fd_device;
+-      compat_int_t    last_checked;
+-      compat_caddr_t dmabuf;
+-      compat_int_t    bufblocks;
+-};
+-
+-struct compat_floppy_fdc_state {
+-      compat_int_t    spec1;
+-      compat_int_t    spec2;
+-      compat_int_t    dtr;
+-      unsigned char   version;
+-      unsigned char   dor;
+-      compat_ulong_t  address;
+-      unsigned int    rawcmd:2;
+-      unsigned int    reset:1;
+-      unsigned int    need_configure:1;
+-      unsigned int    perp_mode:2;
+-      unsigned int    has_fifo:1;
+-      unsigned int    driver_version;
+-      unsigned char   track[4];
+-};
+-
+-struct compat_floppy_write_errors {
+-      unsigned int    write_errors;
+-      compat_ulong_t  first_error_sector;
+-      compat_int_t    first_error_generation;
+-      compat_ulong_t  last_error_sector;
+-      compat_int_t    last_error_generation;
+-      compat_uint_t   badness;
+-};
+-
+-#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
+-#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
+-#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
+-#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
+-#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
+-#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
+-#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
+-#define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
+-
+-static struct {
+-      unsigned int    cmd32;
+-      unsigned int    cmd;
+-} fd_ioctl_trans_table[] = {
+-      { FDSETPRM32, FDSETPRM },
+-      { FDDEFPRM32, FDDEFPRM },
+-      { FDGETPRM32, FDGETPRM },
+-      { FDSETDRVPRM32, FDSETDRVPRM },
+-      { FDGETDRVPRM32, FDGETDRVPRM },
+-      { FDGETDRVSTAT32, FDGETDRVSTAT },
+-      { FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+-      { FDGETFDCSTAT32, FDGETFDCSTAT },
+-      { FDWERRORGET32, FDWERRORGET }
+-};
+-
+-#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
+-
+-static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
+-              unsigned int cmd, unsigned long arg)
+-{
+-      mm_segment_t old_fs = get_fs();
+-      void *karg = NULL;
+-      unsigned int kcmd = 0;
+-      int i, err;
+-
+-      for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+-              if (cmd == fd_ioctl_trans_table[i].cmd32) {
+-                      kcmd = fd_ioctl_trans_table[i].cmd;
+-                      break;
+-              }
+-      if (!kcmd)
+-              return -EINVAL;
+-
+-      switch (cmd) {
+-      case FDSETPRM32:
+-      case FDDEFPRM32:
+-      case FDGETPRM32:
+-      {
+-              compat_uptr_t name;
+-              struct compat_floppy_struct __user *uf;
+-              struct floppy_struct *f;
+-
+-              uf = compat_ptr(arg);
+-              f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              if (cmd == FDGETPRM32)
+-                      break;
+-              err = __get_user(f->size, &uf->size);
+-              err |= __get_user(f->sect, &uf->sect);
+-              err |= __get_user(f->head, &uf->head);
+-              err |= __get_user(f->track, &uf->track);
+-              err |= __get_user(f->stretch, &uf->stretch);
+-              err |= __get_user(f->gap, &uf->gap);
+-              err |= __get_user(f->rate, &uf->rate);
+-              err |= __get_user(f->spec1, &uf->spec1);
+-              err |= __get_user(f->fmt_gap, &uf->fmt_gap);
+-              err |= __get_user(name, &uf->name);
+-              f->name = compat_ptr(name);
+-              if (err) {
+-                      err = -EFAULT;
+-                      goto out;
+-              }
+-              break;
+-      }
+-      case FDSETDRVPRM32:
+-      case FDGETDRVPRM32:
+-      {
+-              struct compat_floppy_drive_params __user *uf;
+-              struct floppy_drive_params *f;
+-
+-              uf = compat_ptr(arg);
+-              f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              if (cmd == FDGETDRVPRM32)
+-                      break;
+-              err = __get_user(f->cmos, &uf->cmos);
+-              err |= __get_user(f->max_dtr, &uf->max_dtr);
+-              err |= __get_user(f->hlt, &uf->hlt);
+-              err |= __get_user(f->hut, &uf->hut);
+-              err |= __get_user(f->srt, &uf->srt);
+-              err |= __get_user(f->spinup, &uf->spinup);
+-              err |= __get_user(f->spindown, &uf->spindown);
+-              err |= __get_user(f->spindown_offset, &uf->spindown_offset);
+-              err |= __get_user(f->select_delay, &uf->select_delay);
+-              err |= __get_user(f->rps, &uf->rps);
+-              err |= __get_user(f->tracks, &uf->tracks);
+-              err |= __get_user(f->timeout, &uf->timeout);
+-              err |= __get_user(f->interleave_sect, &uf->interleave_sect);
+-              err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
+-              err |= __get_user(f->flags, &uf->flags);
+-              err |= __get_user(f->read_track, &uf->read_track);
+-              err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
+-              err |= __get_user(f->checkfreq, &uf->checkfreq);
+-              err |= __get_user(f->native_format, &uf->native_format);
+-              if (err) {
+-                      err = -EFAULT;
+-                      goto out;
+-              }
+-              break;
+-      }
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-              karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      case FDGETFDCSTAT32:
+-              karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      case FDWERRORGET32:
+-              karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-      set_fs(KERNEL_DS);
+-      err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
+-      set_fs(old_fs);
+-      if (err)
+-              goto out;
+-      switch (cmd) {
+-      case FDGETPRM32:
+-      {
+-              struct floppy_struct *f = karg;
+-              struct compat_floppy_struct __user *uf = compat_ptr(arg);
+-
+-              err = __put_user(f->size, &uf->size);
+-              err |= __put_user(f->sect, &uf->sect);
+-              err |= __put_user(f->head, &uf->head);
+-              err |= __put_user(f->track, &uf->track);
+-              err |= __put_user(f->stretch, &uf->stretch);
+-              err |= __put_user(f->gap, &uf->gap);
+-              err |= __put_user(f->rate, &uf->rate);
+-              err |= __put_user(f->spec1, &uf->spec1);
+-              err |= __put_user(f->fmt_gap, &uf->fmt_gap);
+-              err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
+-              break;
+-      }
+-      case FDGETDRVPRM32:
+-      {
+-              struct compat_floppy_drive_params __user *uf;
+-              struct floppy_drive_params *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->cmos, &uf->cmos);
+-              err |= __put_user(f->max_dtr, &uf->max_dtr);
+-              err |= __put_user(f->hlt, &uf->hlt);
+-              err |= __put_user(f->hut, &uf->hut);
+-              err |= __put_user(f->srt, &uf->srt);
+-              err |= __put_user(f->spinup, &uf->spinup);
+-              err |= __put_user(f->spindown, &uf->spindown);
+-              err |= __put_user(f->spindown_offset, &uf->spindown_offset);
+-              err |= __put_user(f->select_delay, &uf->select_delay);
+-              err |= __put_user(f->rps, &uf->rps);
+-              err |= __put_user(f->tracks, &uf->tracks);
+-              err |= __put_user(f->timeout, &uf->timeout);
+-              err |= __put_user(f->interleave_sect, &uf->interleave_sect);
+-              err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
+-              err |= __put_user(f->flags, &uf->flags);
+-              err |= __put_user(f->read_track, &uf->read_track);
+-              err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
+-              err |= __put_user(f->checkfreq, &uf->checkfreq);
+-              err |= __put_user(f->native_format, &uf->native_format);
+-              break;
+-      }
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-      {
+-              struct compat_floppy_drive_struct __user *uf;
+-              struct floppy_drive_struct *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->flags, &uf->flags);
+-              err |= __put_user(f->spinup_date, &uf->spinup_date);
+-              err |= __put_user(f->select_date, &uf->select_date);
+-              err |= __put_user(f->first_read_date, &uf->first_read_date);
+-              err |= __put_user(f->probed_format, &uf->probed_format);
+-              err |= __put_user(f->track, &uf->track);
+-              err |= __put_user(f->maxblock, &uf->maxblock);
+-              err |= __put_user(f->maxtrack, &uf->maxtrack);
+-              err |= __put_user(f->generation, &uf->generation);
+-              err |= __put_user(f->keep_data, &uf->keep_data);
+-              err |= __put_user(f->fd_ref, &uf->fd_ref);
+-              err |= __put_user(f->fd_device, &uf->fd_device);
+-              err |= __put_user(f->last_checked, &uf->last_checked);
+-              err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
+-              err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
+-              break;
+-      }
+-      case FDGETFDCSTAT32:
+-      {
+-              struct compat_floppy_fdc_state __user *uf;
+-              struct floppy_fdc_state *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->spec1, &uf->spec1);
+-              err |= __put_user(f->spec2, &uf->spec2);
+-              err |= __put_user(f->dtr, &uf->dtr);
+-              err |= __put_user(f->version, &uf->version);
+-              err |= __put_user(f->dor, &uf->dor);
+-              err |= __put_user(f->address, &uf->address);
+-              err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
+-                                 (char *)&f->address + sizeof(f->address), sizeof(int));
+-              err |= __put_user(f->driver_version, &uf->driver_version);
+-              err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
+-              break;
+-      }
+-      case FDWERRORGET32:
+-      {
+-              struct compat_floppy_write_errors __user *uf;
+-              struct floppy_write_errors *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->write_errors, &uf->write_errors);
+-              err |= __put_user(f->first_error_sector, &uf->first_error_sector);
+-              err |= __put_user(f->first_error_generation, &uf->first_error_generation);
+-              err |= __put_user(f->last_error_sector, &uf->last_error_sector);
+-              err |= __put_user(f->last_error_generation, &uf->last_error_generation);
+-              err |= __put_user(f->badness, &uf->badness);
+-              break;
+-      }
+-      default:
+-              break;
+-      }
+-      if (err)
+-              err = -EFAULT;
+-
+-out:
+-      kfree(karg);
+-      return err;
+-}
+-
+ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+                       unsigned cmd, unsigned long arg)
+ {
+@@ -537,16 +224,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+       case HDIO_GET_ADDRESS:
+       case HDIO_GET_BUSSTATE:
+               return compat_hdio_ioctl(bdev, mode, cmd, arg);
+-      case FDSETPRM32:
+-      case FDDEFPRM32:
+-      case FDGETPRM32:
+-      case FDSETDRVPRM32:
+-      case FDGETDRVPRM32:
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-      case FDGETFDCSTAT32:
+-      case FDWERRORGET32:
+-              return compat_fd_ioctl(bdev, mode, cmd, arg);
+       case CDROMREADAUDIO:
+               return compat_cdrom_read_audio(bdev, mode, cmd, arg);
+       case CDROM_SEND_PACKET:
+@@ -566,23 +243,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+       case HDIO_DRIVE_CMD:
+       /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+       case 0x330:
+-      /* 0x02 -- Floppy ioctls */
+-      case FDMSGON:
+-      case FDMSGOFF:
+-      case FDSETEMSGTRESH:
+-      case FDFLUSH:
+-      case FDWERRORCLR:
+-      case FDSETMAXERRS:
+-      case FDGETMAXERRS:
+-      case FDGETDRVTYP:
+-      case FDEJECT:
+-      case FDCLRPRM:
+-      case FDFMTBEG:
+-      case FDFMTEND:
+-      case FDRESET:
+-      case FDTWADDLE:
+-      case FDFMTTRK:
+-      case FDRAWCMD:
+       /* CDROM stuff */
+       case CDROMPAUSE:
+       case CDROMRESUME:
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 2daa5b84abbc..5fe9e899d2a6 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -192,6 +192,7 @@ static int print_unex = 1;
+ #include <linux/io.h>
+ #include <linux/uaccess.h>
+ #include <linux/async.h>
++#include <linux/compat.h>
+ /*
+  * PS/2 floppies have much slower step rates than regular floppies.
+@@ -3569,6 +3570,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+       return ret;
+ }
++#ifdef CONFIG_COMPAT
++
++struct compat_floppy_drive_params {
++      char            cmos;
++      compat_ulong_t  max_dtr;
++      compat_ulong_t  hlt;
++      compat_ulong_t  hut;
++      compat_ulong_t  srt;
++      compat_ulong_t  spinup;
++      compat_ulong_t  spindown;
++      unsigned char   spindown_offset;
++      unsigned char   select_delay;
++      unsigned char   rps;
++      unsigned char   tracks;
++      compat_ulong_t  timeout;
++      unsigned char   interleave_sect;
++      struct floppy_max_errors max_errors;
++      char            flags;
++      char            read_track;
++      short           autodetect[8];
++      compat_int_t    checkfreq;
++      compat_int_t    native_format;
++};
++
++struct compat_floppy_drive_struct {
++      signed char     flags;
++      compat_ulong_t  spinup_date;
++      compat_ulong_t  select_date;
++      compat_ulong_t  first_read_date;
++      short           probed_format;
++      short           track;
++      short           maxblock;
++      short           maxtrack;
++      compat_int_t    generation;
++      compat_int_t    keep_data;
++      compat_int_t    fd_ref;
++      compat_int_t    fd_device;
++      compat_int_t    last_checked;
++      compat_caddr_t dmabuf;
++      compat_int_t    bufblocks;
++};
++
++struct compat_floppy_fdc_state {
++      compat_int_t    spec1;
++      compat_int_t    spec2;
++      compat_int_t    dtr;
++      unsigned char   version;
++      unsigned char   dor;
++      compat_ulong_t  address;
++      unsigned int    rawcmd:2;
++      unsigned int    reset:1;
++      unsigned int    need_configure:1;
++      unsigned int    perp_mode:2;
++      unsigned int    has_fifo:1;
++      unsigned int    driver_version;
++      unsigned char   track[4];
++};
++
++struct compat_floppy_write_errors {
++      unsigned int    write_errors;
++      compat_ulong_t  first_error_sector;
++      compat_int_t    first_error_generation;
++      compat_ulong_t  last_error_sector;
++      compat_int_t    last_error_generation;
++      compat_uint_t   badness;
++};
++
++#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
++#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
++#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
++#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
++#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
++#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
++#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
++#define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
++
++static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd,
++                  struct compat_floppy_struct __user *arg)
++{
++      struct floppy_struct v;
++      int drive, type;
++      int err;
++
++      BUILD_BUG_ON(offsetof(struct floppy_struct, name) !=
++                   offsetof(struct compat_floppy_struct, name));
++
++      if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL)))
++              return -EPERM;
++
++      memset(&v, 0, sizeof(struct floppy_struct));
++      if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name)))
++              return -EFAULT;
++
++      mutex_lock(&floppy_mutex);
++      drive = (long)bdev->bd_disk->private_data;
++      type = ITYPE(UDRS->fd_device);
++      err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM,
++                      &v, drive, type, bdev);
++      mutex_unlock(&floppy_mutex);
++      return err;
++}
++
++static int compat_get_prm(int drive,
++                        struct compat_floppy_struct __user *arg)
++{
++      struct compat_floppy_struct v;
++      struct floppy_struct *p;
++      int err;
++
++      memset(&v, 0, sizeof(v));
++      mutex_lock(&floppy_mutex);
++      err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p);
++      if (err) {
++              mutex_unlock(&floppy_mutex);
++              return err;
++      }
++      memcpy(&v, p, offsetof(struct floppy_struct, name));
++      mutex_unlock(&floppy_mutex);
++      if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_setdrvprm(int drive,
++                          struct compat_floppy_drive_params __user *arg)
++{
++      struct compat_floppy_drive_params v;
++
++      if (!capable(CAP_SYS_ADMIN))
++              return -EPERM;
++      if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params)))
++              return -EFAULT;
++      mutex_lock(&floppy_mutex);
++      UDP->cmos = v.cmos;
++      UDP->max_dtr = v.max_dtr;
++      UDP->hlt = v.hlt;
++      UDP->hut = v.hut;
++      UDP->srt = v.srt;
++      UDP->spinup = v.spinup;
++      UDP->spindown = v.spindown;
++      UDP->spindown_offset = v.spindown_offset;
++      UDP->select_delay = v.select_delay;
++      UDP->rps = v.rps;
++      UDP->tracks = v.tracks;
++      UDP->timeout = v.timeout;
++      UDP->interleave_sect = v.interleave_sect;
++      UDP->max_errors = v.max_errors;
++      UDP->flags = v.flags;
++      UDP->read_track = v.read_track;
++      memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect));
++      UDP->checkfreq = v.checkfreq;
++      UDP->native_format = v.native_format;
++      mutex_unlock(&floppy_mutex);
++      return 0;
++}
++
++static int compat_getdrvprm(int drive,
++                          struct compat_floppy_drive_params __user *arg)
++{
++      struct compat_floppy_drive_params v;
++
++      memset(&v, 0, sizeof(struct compat_floppy_drive_params));
++      mutex_lock(&floppy_mutex);
++      v.cmos = UDP->cmos;
++      v.max_dtr = UDP->max_dtr;
++      v.hlt = UDP->hlt;
++      v.hut = UDP->hut;
++      v.srt = UDP->srt;
++      v.spinup = UDP->spinup;
++      v.spindown = UDP->spindown;
++      v.spindown_offset = UDP->spindown_offset;
++      v.select_delay = UDP->select_delay;
++      v.rps = UDP->rps;
++      v.tracks = UDP->tracks;
++      v.timeout = UDP->timeout;
++      v.interleave_sect = UDP->interleave_sect;
++      v.max_errors = UDP->max_errors;
++      v.flags = UDP->flags;
++      v.read_track = UDP->read_track;
++      memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect));
++      v.checkfreq = UDP->checkfreq;
++      v.native_format = UDP->native_format;
++      mutex_unlock(&floppy_mutex);
++
++      if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_getdrvstat(int drive, bool poll,
++                          struct compat_floppy_drive_struct __user *arg)
++{
++      struct compat_floppy_drive_struct v;
++
++      memset(&v, 0, sizeof(struct compat_floppy_drive_struct));
++      mutex_lock(&floppy_mutex);
++
++      if (poll) {
++              if (lock_fdc(drive))
++                      goto Eintr;
++              if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
++                      goto Eintr;
++              process_fd_request();
++      }
++      v.spinup_date = UDRS->spinup_date;
++      v.select_date = UDRS->select_date;
++      v.first_read_date = UDRS->first_read_date;
++      v.probed_format = UDRS->probed_format;
++      v.track = UDRS->track;
++      v.maxblock = UDRS->maxblock;
++      v.maxtrack = UDRS->maxtrack;
++      v.generation = UDRS->generation;
++      v.keep_data = UDRS->keep_data;
++      v.fd_ref = UDRS->fd_ref;
++      v.fd_device = UDRS->fd_device;
++      v.last_checked = UDRS->last_checked;
++      v.dmabuf = (uintptr_t)UDRS->dmabuf;
++      v.bufblocks = UDRS->bufblocks;
++      mutex_unlock(&floppy_mutex);
++
++      if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct)))
++              return -EFAULT;
++      return 0;
++Eintr:
++      mutex_unlock(&floppy_mutex);
++      return -EINTR;
++}
++
++static int compat_getfdcstat(int drive,
++                          struct compat_floppy_fdc_state __user *arg)
++{
++      struct compat_floppy_fdc_state v32;
++      struct floppy_fdc_state v;
++
++      mutex_lock(&floppy_mutex);
++      v = *UFDCS;
++      mutex_unlock(&floppy_mutex);
++
++      memset(&v32, 0, sizeof(struct compat_floppy_fdc_state));
++      v32.spec1 = v.spec1;
++      v32.spec2 = v.spec2;
++      v32.dtr = v.dtr;
++      v32.version = v.version;
++      v32.dor = v.dor;
++      v32.address = v.address;
++      v32.rawcmd = v.rawcmd;
++      v32.reset = v.reset;
++      v32.need_configure = v.need_configure;
++      v32.perp_mode = v.perp_mode;
++      v32.has_fifo = v.has_fifo;
++      v32.driver_version = v.driver_version;
++      memcpy(v32.track, v.track, 4);
++      if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_werrorget(int drive,
++                          struct compat_floppy_write_errors __user *arg)
++{
++      struct compat_floppy_write_errors v32;
++      struct floppy_write_errors v;
++
++      memset(&v32, 0, sizeof(struct compat_floppy_write_errors));
++      mutex_lock(&floppy_mutex);
++      v = *UDRWE;
++      mutex_unlock(&floppy_mutex);
++      v32.write_errors = v.write_errors;
++      v32.first_error_sector = v.first_error_sector;
++      v32.first_error_generation = v.first_error_generation;
++      v32.last_error_sector = v.last_error_sector;
++      v32.last_error_generation = v.last_error_generation;
++      v32.badness = v.badness;
++      if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors)))
++              return -EFAULT;
++      return 0;
++}
++
++static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
++                  unsigned long param)
++{
++      int drive = (long)bdev->bd_disk->private_data;
++      switch (cmd) {
++      case FDMSGON:
++      case FDMSGOFF:
++      case FDSETEMSGTRESH:
++      case FDFLUSH:
++      case FDWERRORCLR:
++      case FDEJECT:
++      case FDCLRPRM:
++      case FDFMTBEG:
++      case FDRESET:
++      case FDTWADDLE:
++              return fd_ioctl(bdev, mode, cmd, param);
++      case FDSETMAXERRS:
++      case FDGETMAXERRS:
++      case FDGETDRVTYP:
++      case FDFMTEND:
++      case FDFMTTRK:
++      case FDRAWCMD:
++              return fd_ioctl(bdev, mode, cmd,
++                              (unsigned long)compat_ptr(param));
++      case FDSETPRM32:
++      case FDDEFPRM32:
++              return compat_set_geometry(bdev, mode, cmd, compat_ptr(param));
++      case FDGETPRM32:
++              return compat_get_prm(drive, compat_ptr(param));
++      case FDSETDRVPRM32:
++              return compat_setdrvprm(drive, compat_ptr(param));
++      case FDGETDRVPRM32:
++              return compat_getdrvprm(drive, compat_ptr(param));
++      case FDPOLLDRVSTAT32:
++              return compat_getdrvstat(drive, true, compat_ptr(param));
++      case FDGETDRVSTAT32:
++              return compat_getdrvstat(drive, false, compat_ptr(param));
++      case FDGETFDCSTAT32:
++              return compat_getfdcstat(drive, compat_ptr(param));
++      case FDWERRORGET32:
++              return compat_werrorget(drive, compat_ptr(param));
++      }
++      return -EINVAL;
++}
++#endif
++
+ static void __init config_types(void)
+ {
+       bool has_drive = false;
+@@ -3885,6 +4210,9 @@ static const struct block_device_operations floppy_fops = {
+       .getgeo                 = fd_getgeo,
+       .check_events           = floppy_check_events,
+       .revalidate_disk        = floppy_revalidate,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl           = fd_compat_ioctl,
++#endif
+ };
+ /*
+-- 
+2.20.1
+
index 9f2b148649739b6b0f26241631d342e0dd71741c..c30faadfd51f44662165b2fd3ffc63147d8a8701 100644 (file)
@@ -1,4 +1,4 @@
-From 77163150bdc22c8ec7a3564d95b02bbbe0392bda Mon Sep 17 00:00:00 2001
+From 5544bb65ad6f4a74df98c5d428f96539a1f939bd Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:20 +0300
 Subject: floppy: fix div-by-zero in setup_format_params
@@ -29,14 +29,15 @@ 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>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
- drivers/block/floppy.c |    5 +++++
+ drivers/block/floppy.c | 5 +++++
  1 file changed, 5 insertions(+)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 896dea296076..d39dc8807d3f 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -2113,6 +2113,9 @@ static void setup_format_params(int trac
+@@ -2114,6 +2114,9 @@ static void setup_format_params(int track)
        raw_cmd->kernel_data = floppy_track_buffer;
        raw_cmd->length = 4 * F_SECT_PER_TRACK;
  
@@ -46,7 +47,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        /* allow for about 30ms for data transport per track */
        head_shift = (F_SECT_PER_TRACK + 5) / 6;
  
-@@ -3235,6 +3238,8 @@ static int set_geometry(unsigned int cmd
+@@ -3236,6 +3239,8 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
        /* sanity checking for parameters. */
        if (g->sect <= 0 ||
            g->head <= 0 ||
@@ -55,3 +56,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
            g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
            /* check if reserved bits are set */
            (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
+-- 
+2.20.1
+
index ae36d7e6a40d5bbe8f821e3ac4a85cf83c441535..b9e7e981ceb2a430ce8c60b8dc3f715f9ab123e3 100644 (file)
@@ -1,11 +1,9 @@
-From 9b04609b784027968348796a18f601aed9db3789 Mon Sep 17 00:00:00 2001
+From fcd20f29d0471fddfb010a536fa25ceeb9744615 Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:22 +0300
 Subject: floppy: fix invalid pointer dereference in drive_name
 
-From: Denis Efremov <efremov@ispras.ru>
-
-commit 9b04609b784027968348796a18f601aed9db3789 upstream.
+[ Upstream commit 9b04609b784027968348796a18f601aed9db3789 ]
 
 This fixes the invalid pointer dereference in the drive_name function of
 the floppy driver.
@@ -30,15 +28,16 @@ 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
+Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- drivers/block/floppy.c |    9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
+ drivers/block/floppy.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 945f93d1ffe7..d651e4309371 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3383,7 +3383,8 @@ static int fd_getgeo(struct block_device
+@@ -3384,7 +3384,8 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
  }
  
@@ -48,7 +47,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  {
        size_t floppy_type_size = ARRAY_SIZE(floppy_type);
        size_t i = 0;
-@@ -3394,6 +3395,9 @@ static bool valid_floppy_drive_params(co
+@@ -3395,6 +3396,9 @@ static bool valid_floppy_drive_params(const short autodetect[8])
                        return false;
        }
  
@@ -58,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        return true;
  }
  
-@@ -3523,7 +3527,8 @@ static int fd_locked_ioctl(struct block_
+@@ -3524,7 +3528,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:
@@ -68,3 +67,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
                        return -EINVAL;
                *UDP = inparam.dp;
                break;
+@@ -3723,7 +3728,7 @@ 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))
++      if (!valid_floppy_drive_params(v.autodetect, v.native_format))
+               return -EINVAL;
+       mutex_lock(&floppy_mutex);
+       UDP->cmos = v.cmos;
+-- 
+2.20.1
+
index 390abb6d15c373280aa762ca669f3029b916ffb6..aac07d7df1df1ea4ee74e18bb0559f0e0db95715 100644 (file)
@@ -1,4 +1,4 @@
-From f08ab6458e0c83d14ac4e9856018fbb79b583feb Mon Sep 17 00:00:00 2001
+From 7022683a256b641c683d236b65beb59e2630f9e8 Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:23 +0300
 Subject: floppy: fix out-of-bounds read in copy_buffer
@@ -26,14 +26,15 @@ 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>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
- drivers/block/floppy.c |    6 ++++--
+ drivers/block/floppy.c | 6 ++++--
  1 file changed, 4 insertions(+), 2 deletions(-)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index d651e4309371..6930abef42b3 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3236,8 +3236,10 @@ static int set_geometry(unsigned int cmd
+@@ -3237,8 +3237,10 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
        int cnt;
  
        /* sanity checking for parameters. */
@@ -46,3 +47,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
            /* check for zero in F_SECT_PER_TRACK */
            (unsigned char)((g->sect << 2) >> FD_SIZECODE(g)) == 0 ||
            g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
+-- 
+2.20.1
+
index 860a525b1f01d8fc9cb28bd76669d1f3657709e9..d9680a431adce2567820404c311c6a726486b19e 100644 (file)
@@ -1,11 +1,9 @@
-From 5635f897ed83fd539df78e98ba69ee91592f9bb8 Mon Sep 17 00:00:00 2001
+From 5d927beed36f215ae2443e260480880a5e1452a5 Mon Sep 17 00:00:00 2001
 From: Denis Efremov <efremov@ispras.ru>
 Date: Fri, 12 Jul 2019 21:55:21 +0300
 Subject: floppy: fix out-of-bounds read in next_valid_format
 
-From: Denis Efremov <efremov@ispras.ru>
-
-commit 5635f897ed83fd539df78e98ba69ee91592f9bb8 upstream.
+[ Upstream commit 5635f897ed83fd539df78e98ba69ee91592f9bb8 ]
 
 This fixes a global out-of-bounds read access in the next_valid_format
 function of the floppy driver.
@@ -28,15 +26,16 @@ 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
+Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- drivers/block/floppy.c |   16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
+ drivers/block/floppy.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
 
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index d39dc8807d3f..945f93d1ffe7 100644
 --- a/drivers/block/floppy.c
 +++ b/drivers/block/floppy.c
-@@ -3383,6 +3383,20 @@ static int fd_getgeo(struct block_device
+@@ -3384,6 +3384,20 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
  }
  
@@ -57,7 +56,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                    unsigned long param)
  {
-@@ -3509,6 +3523,8 @@ static int fd_locked_ioctl(struct block_
+@@ -3510,6 +3524,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:
@@ -66,3 +65,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
                *UDP = inparam.dp;
                break;
        case FDGETDRVPRM:
+@@ -3707,6 +3723,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
+
index bbdcf87d2eca8123b2c7ef42a15ebaea92c2dc25..678d17082257e17af09d8cd523cae7ccfb05d577 100644 (file)
@@ -72,10 +72,6 @@ bluetooth-check-state-in-l2cap_disconnect_rsp.patch
 bluetooth-validate-ble-connection-interval-updates.patch
 gtp-fix-illegal-context-switch-in-rcu-read-side-crit.patch
 gtp-fix-use-after-free-in-gtp_newlink.patch
-floppy-fix-div-by-zero-in-setup_format_params.patch
-floppy-fix-out-of-bounds-read-in-next_valid_format.patch
-floppy-fix-invalid-pointer-dereference-in-drive_name.patch
-floppy-fix-out-of-bounds-read-in-copy_buffer.patch
 xen-let-alloc_xenballooned_pages-fail-if-not-enough-memory-free.patch
 scsi-ncr5380-reduce-goto-statements-in-ncr5380_select.patch
 scsi-ncr5380-always-re-enable-reselection-interrupt.patch
@@ -105,3 +101,8 @@ padata-use-smp_mb-in-padata_reorder-to-avoid-orphaned-padata-jobs.patch
 pci-do-not-poll-for-pme-if-the-device-is-in-d3cold.patch
 btrfs-add-missing-inode-version-ctime-and-mtime-updates-when-punching-hole.patch
 libnvdimm-pfn-fix-fsdax-mode-namespace-info-block-zero-fields.patch
+take-floppy-compat-ioctls-to-sodding-floppy.c.patch
+floppy-fix-div-by-zero-in-setup_format_params.patch
+floppy-fix-out-of-bounds-read-in-next_valid_format.patch
+floppy-fix-invalid-pointer-dereference-in-drive_name.patch
+floppy-fix-out-of-bounds-read-in-copy_buffer.patch
diff --git a/queue-4.9/take-floppy-compat-ioctls-to-sodding-floppy.c.patch b/queue-4.9/take-floppy-compat-ioctls-to-sodding-floppy.c.patch
new file mode 100644 (file)
index 0000000..19d6471
--- /dev/null
@@ -0,0 +1,745 @@
+From 3850e02efae9bd24e29eae9e6c289e4d8a0b637c Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 27 Jun 2017 15:47:56 -0400
+Subject: take floppy compat ioctls to sodding floppy.c
+
+[ Upstream commit 229b53c9bf4e1132a4aa6feb9632a7a1f1d08c5c ]
+
+all other drivers recognizing those ioctls are very much *not*
+biarch.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/compat_ioctl.c   | 340 -----------------------------------------
+ drivers/block/floppy.c | 328 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 328 insertions(+), 340 deletions(-)
+
+diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
+index 556826ac7cb4..3c9fdd6983aa 100644
+--- a/block/compat_ioctl.c
++++ b/block/compat_ioctl.c
+@@ -4,7 +4,6 @@
+ #include <linux/cdrom.h>
+ #include <linux/compat.h>
+ #include <linux/elevator.h>
+-#include <linux/fd.h>
+ #include <linux/hdreg.h>
+ #include <linux/slab.h>
+ #include <linux/syscalls.h>
+@@ -209,318 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
+ #define BLKBSZSET_32          _IOW(0x12, 113, int)
+ #define BLKGETSIZE64_32               _IOR(0x12, 114, int)
+-struct compat_floppy_drive_params {
+-      char            cmos;
+-      compat_ulong_t  max_dtr;
+-      compat_ulong_t  hlt;
+-      compat_ulong_t  hut;
+-      compat_ulong_t  srt;
+-      compat_ulong_t  spinup;
+-      compat_ulong_t  spindown;
+-      unsigned char   spindown_offset;
+-      unsigned char   select_delay;
+-      unsigned char   rps;
+-      unsigned char   tracks;
+-      compat_ulong_t  timeout;
+-      unsigned char   interleave_sect;
+-      struct floppy_max_errors max_errors;
+-      char            flags;
+-      char            read_track;
+-      short           autodetect[8];
+-      compat_int_t    checkfreq;
+-      compat_int_t    native_format;
+-};
+-
+-struct compat_floppy_drive_struct {
+-      signed char     flags;
+-      compat_ulong_t  spinup_date;
+-      compat_ulong_t  select_date;
+-      compat_ulong_t  first_read_date;
+-      short           probed_format;
+-      short           track;
+-      short           maxblock;
+-      short           maxtrack;
+-      compat_int_t    generation;
+-      compat_int_t    keep_data;
+-      compat_int_t    fd_ref;
+-      compat_int_t    fd_device;
+-      compat_int_t    last_checked;
+-      compat_caddr_t dmabuf;
+-      compat_int_t    bufblocks;
+-};
+-
+-struct compat_floppy_fdc_state {
+-      compat_int_t    spec1;
+-      compat_int_t    spec2;
+-      compat_int_t    dtr;
+-      unsigned char   version;
+-      unsigned char   dor;
+-      compat_ulong_t  address;
+-      unsigned int    rawcmd:2;
+-      unsigned int    reset:1;
+-      unsigned int    need_configure:1;
+-      unsigned int    perp_mode:2;
+-      unsigned int    has_fifo:1;
+-      unsigned int    driver_version;
+-      unsigned char   track[4];
+-};
+-
+-struct compat_floppy_write_errors {
+-      unsigned int    write_errors;
+-      compat_ulong_t  first_error_sector;
+-      compat_int_t    first_error_generation;
+-      compat_ulong_t  last_error_sector;
+-      compat_int_t    last_error_generation;
+-      compat_uint_t   badness;
+-};
+-
+-#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
+-#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
+-#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
+-#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
+-#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
+-#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
+-#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
+-#define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
+-
+-static struct {
+-      unsigned int    cmd32;
+-      unsigned int    cmd;
+-} fd_ioctl_trans_table[] = {
+-      { FDSETPRM32, FDSETPRM },
+-      { FDDEFPRM32, FDDEFPRM },
+-      { FDGETPRM32, FDGETPRM },
+-      { FDSETDRVPRM32, FDSETDRVPRM },
+-      { FDGETDRVPRM32, FDGETDRVPRM },
+-      { FDGETDRVSTAT32, FDGETDRVSTAT },
+-      { FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+-      { FDGETFDCSTAT32, FDGETFDCSTAT },
+-      { FDWERRORGET32, FDWERRORGET }
+-};
+-
+-#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
+-
+-static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
+-              unsigned int cmd, unsigned long arg)
+-{
+-      mm_segment_t old_fs = get_fs();
+-      void *karg = NULL;
+-      unsigned int kcmd = 0;
+-      int i, err;
+-
+-      for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+-              if (cmd == fd_ioctl_trans_table[i].cmd32) {
+-                      kcmd = fd_ioctl_trans_table[i].cmd;
+-                      break;
+-              }
+-      if (!kcmd)
+-              return -EINVAL;
+-
+-      switch (cmd) {
+-      case FDSETPRM32:
+-      case FDDEFPRM32:
+-      case FDGETPRM32:
+-      {
+-              compat_uptr_t name;
+-              struct compat_floppy_struct __user *uf;
+-              struct floppy_struct *f;
+-
+-              uf = compat_ptr(arg);
+-              f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              if (cmd == FDGETPRM32)
+-                      break;
+-              err = __get_user(f->size, &uf->size);
+-              err |= __get_user(f->sect, &uf->sect);
+-              err |= __get_user(f->head, &uf->head);
+-              err |= __get_user(f->track, &uf->track);
+-              err |= __get_user(f->stretch, &uf->stretch);
+-              err |= __get_user(f->gap, &uf->gap);
+-              err |= __get_user(f->rate, &uf->rate);
+-              err |= __get_user(f->spec1, &uf->spec1);
+-              err |= __get_user(f->fmt_gap, &uf->fmt_gap);
+-              err |= __get_user(name, &uf->name);
+-              f->name = compat_ptr(name);
+-              if (err) {
+-                      err = -EFAULT;
+-                      goto out;
+-              }
+-              break;
+-      }
+-      case FDSETDRVPRM32:
+-      case FDGETDRVPRM32:
+-      {
+-              struct compat_floppy_drive_params __user *uf;
+-              struct floppy_drive_params *f;
+-
+-              uf = compat_ptr(arg);
+-              f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              if (cmd == FDGETDRVPRM32)
+-                      break;
+-              err = __get_user(f->cmos, &uf->cmos);
+-              err |= __get_user(f->max_dtr, &uf->max_dtr);
+-              err |= __get_user(f->hlt, &uf->hlt);
+-              err |= __get_user(f->hut, &uf->hut);
+-              err |= __get_user(f->srt, &uf->srt);
+-              err |= __get_user(f->spinup, &uf->spinup);
+-              err |= __get_user(f->spindown, &uf->spindown);
+-              err |= __get_user(f->spindown_offset, &uf->spindown_offset);
+-              err |= __get_user(f->select_delay, &uf->select_delay);
+-              err |= __get_user(f->rps, &uf->rps);
+-              err |= __get_user(f->tracks, &uf->tracks);
+-              err |= __get_user(f->timeout, &uf->timeout);
+-              err |= __get_user(f->interleave_sect, &uf->interleave_sect);
+-              err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
+-              err |= __get_user(f->flags, &uf->flags);
+-              err |= __get_user(f->read_track, &uf->read_track);
+-              err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
+-              err |= __get_user(f->checkfreq, &uf->checkfreq);
+-              err |= __get_user(f->native_format, &uf->native_format);
+-              if (err) {
+-                      err = -EFAULT;
+-                      goto out;
+-              }
+-              break;
+-      }
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-              karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      case FDGETFDCSTAT32:
+-              karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      case FDWERRORGET32:
+-              karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
+-              if (!karg)
+-                      return -ENOMEM;
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-      set_fs(KERNEL_DS);
+-      err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
+-      set_fs(old_fs);
+-      if (err)
+-              goto out;
+-      switch (cmd) {
+-      case FDGETPRM32:
+-      {
+-              struct floppy_struct *f = karg;
+-              struct compat_floppy_struct __user *uf = compat_ptr(arg);
+-
+-              err = __put_user(f->size, &uf->size);
+-              err |= __put_user(f->sect, &uf->sect);
+-              err |= __put_user(f->head, &uf->head);
+-              err |= __put_user(f->track, &uf->track);
+-              err |= __put_user(f->stretch, &uf->stretch);
+-              err |= __put_user(f->gap, &uf->gap);
+-              err |= __put_user(f->rate, &uf->rate);
+-              err |= __put_user(f->spec1, &uf->spec1);
+-              err |= __put_user(f->fmt_gap, &uf->fmt_gap);
+-              err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
+-              break;
+-      }
+-      case FDGETDRVPRM32:
+-      {
+-              struct compat_floppy_drive_params __user *uf;
+-              struct floppy_drive_params *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->cmos, &uf->cmos);
+-              err |= __put_user(f->max_dtr, &uf->max_dtr);
+-              err |= __put_user(f->hlt, &uf->hlt);
+-              err |= __put_user(f->hut, &uf->hut);
+-              err |= __put_user(f->srt, &uf->srt);
+-              err |= __put_user(f->spinup, &uf->spinup);
+-              err |= __put_user(f->spindown, &uf->spindown);
+-              err |= __put_user(f->spindown_offset, &uf->spindown_offset);
+-              err |= __put_user(f->select_delay, &uf->select_delay);
+-              err |= __put_user(f->rps, &uf->rps);
+-              err |= __put_user(f->tracks, &uf->tracks);
+-              err |= __put_user(f->timeout, &uf->timeout);
+-              err |= __put_user(f->interleave_sect, &uf->interleave_sect);
+-              err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
+-              err |= __put_user(f->flags, &uf->flags);
+-              err |= __put_user(f->read_track, &uf->read_track);
+-              err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
+-              err |= __put_user(f->checkfreq, &uf->checkfreq);
+-              err |= __put_user(f->native_format, &uf->native_format);
+-              break;
+-      }
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-      {
+-              struct compat_floppy_drive_struct __user *uf;
+-              struct floppy_drive_struct *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->flags, &uf->flags);
+-              err |= __put_user(f->spinup_date, &uf->spinup_date);
+-              err |= __put_user(f->select_date, &uf->select_date);
+-              err |= __put_user(f->first_read_date, &uf->first_read_date);
+-              err |= __put_user(f->probed_format, &uf->probed_format);
+-              err |= __put_user(f->track, &uf->track);
+-              err |= __put_user(f->maxblock, &uf->maxblock);
+-              err |= __put_user(f->maxtrack, &uf->maxtrack);
+-              err |= __put_user(f->generation, &uf->generation);
+-              err |= __put_user(f->keep_data, &uf->keep_data);
+-              err |= __put_user(f->fd_ref, &uf->fd_ref);
+-              err |= __put_user(f->fd_device, &uf->fd_device);
+-              err |= __put_user(f->last_checked, &uf->last_checked);
+-              err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
+-              err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
+-              break;
+-      }
+-      case FDGETFDCSTAT32:
+-      {
+-              struct compat_floppy_fdc_state __user *uf;
+-              struct floppy_fdc_state *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->spec1, &uf->spec1);
+-              err |= __put_user(f->spec2, &uf->spec2);
+-              err |= __put_user(f->dtr, &uf->dtr);
+-              err |= __put_user(f->version, &uf->version);
+-              err |= __put_user(f->dor, &uf->dor);
+-              err |= __put_user(f->address, &uf->address);
+-              err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
+-                                 (char *)&f->address + sizeof(f->address), sizeof(int));
+-              err |= __put_user(f->driver_version, &uf->driver_version);
+-              err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
+-              break;
+-      }
+-      case FDWERRORGET32:
+-      {
+-              struct compat_floppy_write_errors __user *uf;
+-              struct floppy_write_errors *f = karg;
+-
+-              uf = compat_ptr(arg);
+-              err = __put_user(f->write_errors, &uf->write_errors);
+-              err |= __put_user(f->first_error_sector, &uf->first_error_sector);
+-              err |= __put_user(f->first_error_generation, &uf->first_error_generation);
+-              err |= __put_user(f->last_error_sector, &uf->last_error_sector);
+-              err |= __put_user(f->last_error_generation, &uf->last_error_generation);
+-              err |= __put_user(f->badness, &uf->badness);
+-              break;
+-      }
+-      default:
+-              break;
+-      }
+-      if (err)
+-              err = -EFAULT;
+-
+-out:
+-      kfree(karg);
+-      return err;
+-}
+-
+ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+                       unsigned cmd, unsigned long arg)
+ {
+@@ -537,16 +224,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+       case HDIO_GET_ADDRESS:
+       case HDIO_GET_BUSSTATE:
+               return compat_hdio_ioctl(bdev, mode, cmd, arg);
+-      case FDSETPRM32:
+-      case FDDEFPRM32:
+-      case FDGETPRM32:
+-      case FDSETDRVPRM32:
+-      case FDGETDRVPRM32:
+-      case FDGETDRVSTAT32:
+-      case FDPOLLDRVSTAT32:
+-      case FDGETFDCSTAT32:
+-      case FDWERRORGET32:
+-              return compat_fd_ioctl(bdev, mode, cmd, arg);
+       case CDROMREADAUDIO:
+               return compat_cdrom_read_audio(bdev, mode, cmd, arg);
+       case CDROM_SEND_PACKET:
+@@ -566,23 +243,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+       case HDIO_DRIVE_CMD:
+       /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+       case 0x330:
+-      /* 0x02 -- Floppy ioctls */
+-      case FDMSGON:
+-      case FDMSGOFF:
+-      case FDSETEMSGTRESH:
+-      case FDFLUSH:
+-      case FDWERRORCLR:
+-      case FDSETMAXERRS:
+-      case FDGETMAXERRS:
+-      case FDGETDRVTYP:
+-      case FDEJECT:
+-      case FDCLRPRM:
+-      case FDFMTBEG:
+-      case FDFMTEND:
+-      case FDRESET:
+-      case FDTWADDLE:
+-      case FDFMTTRK:
+-      case FDRAWCMD:
+       /* CDROM stuff */
+       case CDROMPAUSE:
+       case CDROMRESUME:
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 6914c6e1e1a8..896dea296076 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -192,6 +192,7 @@ static int print_unex = 1;
+ #include <linux/io.h>
+ #include <linux/uaccess.h>
+ #include <linux/async.h>
++#include <linux/compat.h>
+ /*
+  * PS/2 floppies have much slower step rates than regular floppies.
+@@ -3569,6 +3570,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
+       return ret;
+ }
++#ifdef CONFIG_COMPAT
++
++struct compat_floppy_drive_params {
++      char            cmos;
++      compat_ulong_t  max_dtr;
++      compat_ulong_t  hlt;
++      compat_ulong_t  hut;
++      compat_ulong_t  srt;
++      compat_ulong_t  spinup;
++      compat_ulong_t  spindown;
++      unsigned char   spindown_offset;
++      unsigned char   select_delay;
++      unsigned char   rps;
++      unsigned char   tracks;
++      compat_ulong_t  timeout;
++      unsigned char   interleave_sect;
++      struct floppy_max_errors max_errors;
++      char            flags;
++      char            read_track;
++      short           autodetect[8];
++      compat_int_t    checkfreq;
++      compat_int_t    native_format;
++};
++
++struct compat_floppy_drive_struct {
++      signed char     flags;
++      compat_ulong_t  spinup_date;
++      compat_ulong_t  select_date;
++      compat_ulong_t  first_read_date;
++      short           probed_format;
++      short           track;
++      short           maxblock;
++      short           maxtrack;
++      compat_int_t    generation;
++      compat_int_t    keep_data;
++      compat_int_t    fd_ref;
++      compat_int_t    fd_device;
++      compat_int_t    last_checked;
++      compat_caddr_t dmabuf;
++      compat_int_t    bufblocks;
++};
++
++struct compat_floppy_fdc_state {
++      compat_int_t    spec1;
++      compat_int_t    spec2;
++      compat_int_t    dtr;
++      unsigned char   version;
++      unsigned char   dor;
++      compat_ulong_t  address;
++      unsigned int    rawcmd:2;
++      unsigned int    reset:1;
++      unsigned int    need_configure:1;
++      unsigned int    perp_mode:2;
++      unsigned int    has_fifo:1;
++      unsigned int    driver_version;
++      unsigned char   track[4];
++};
++
++struct compat_floppy_write_errors {
++      unsigned int    write_errors;
++      compat_ulong_t  first_error_sector;
++      compat_int_t    first_error_generation;
++      compat_ulong_t  last_error_sector;
++      compat_int_t    last_error_generation;
++      compat_uint_t   badness;
++};
++
++#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
++#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
++#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
++#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
++#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
++#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
++#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
++#define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
++
++static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd,
++                  struct compat_floppy_struct __user *arg)
++{
++      struct floppy_struct v;
++      int drive, type;
++      int err;
++
++      BUILD_BUG_ON(offsetof(struct floppy_struct, name) !=
++                   offsetof(struct compat_floppy_struct, name));
++
++      if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL)))
++              return -EPERM;
++
++      memset(&v, 0, sizeof(struct floppy_struct));
++      if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name)))
++              return -EFAULT;
++
++      mutex_lock(&floppy_mutex);
++      drive = (long)bdev->bd_disk->private_data;
++      type = ITYPE(UDRS->fd_device);
++      err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM,
++                      &v, drive, type, bdev);
++      mutex_unlock(&floppy_mutex);
++      return err;
++}
++
++static int compat_get_prm(int drive,
++                        struct compat_floppy_struct __user *arg)
++{
++      struct compat_floppy_struct v;
++      struct floppy_struct *p;
++      int err;
++
++      memset(&v, 0, sizeof(v));
++      mutex_lock(&floppy_mutex);
++      err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p);
++      if (err) {
++              mutex_unlock(&floppy_mutex);
++              return err;
++      }
++      memcpy(&v, p, offsetof(struct floppy_struct, name));
++      mutex_unlock(&floppy_mutex);
++      if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_setdrvprm(int drive,
++                          struct compat_floppy_drive_params __user *arg)
++{
++      struct compat_floppy_drive_params v;
++
++      if (!capable(CAP_SYS_ADMIN))
++              return -EPERM;
++      if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params)))
++              return -EFAULT;
++      mutex_lock(&floppy_mutex);
++      UDP->cmos = v.cmos;
++      UDP->max_dtr = v.max_dtr;
++      UDP->hlt = v.hlt;
++      UDP->hut = v.hut;
++      UDP->srt = v.srt;
++      UDP->spinup = v.spinup;
++      UDP->spindown = v.spindown;
++      UDP->spindown_offset = v.spindown_offset;
++      UDP->select_delay = v.select_delay;
++      UDP->rps = v.rps;
++      UDP->tracks = v.tracks;
++      UDP->timeout = v.timeout;
++      UDP->interleave_sect = v.interleave_sect;
++      UDP->max_errors = v.max_errors;
++      UDP->flags = v.flags;
++      UDP->read_track = v.read_track;
++      memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect));
++      UDP->checkfreq = v.checkfreq;
++      UDP->native_format = v.native_format;
++      mutex_unlock(&floppy_mutex);
++      return 0;
++}
++
++static int compat_getdrvprm(int drive,
++                          struct compat_floppy_drive_params __user *arg)
++{
++      struct compat_floppy_drive_params v;
++
++      memset(&v, 0, sizeof(struct compat_floppy_drive_params));
++      mutex_lock(&floppy_mutex);
++      v.cmos = UDP->cmos;
++      v.max_dtr = UDP->max_dtr;
++      v.hlt = UDP->hlt;
++      v.hut = UDP->hut;
++      v.srt = UDP->srt;
++      v.spinup = UDP->spinup;
++      v.spindown = UDP->spindown;
++      v.spindown_offset = UDP->spindown_offset;
++      v.select_delay = UDP->select_delay;
++      v.rps = UDP->rps;
++      v.tracks = UDP->tracks;
++      v.timeout = UDP->timeout;
++      v.interleave_sect = UDP->interleave_sect;
++      v.max_errors = UDP->max_errors;
++      v.flags = UDP->flags;
++      v.read_track = UDP->read_track;
++      memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect));
++      v.checkfreq = UDP->checkfreq;
++      v.native_format = UDP->native_format;
++      mutex_unlock(&floppy_mutex);
++
++      if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_getdrvstat(int drive, bool poll,
++                          struct compat_floppy_drive_struct __user *arg)
++{
++      struct compat_floppy_drive_struct v;
++
++      memset(&v, 0, sizeof(struct compat_floppy_drive_struct));
++      mutex_lock(&floppy_mutex);
++
++      if (poll) {
++              if (lock_fdc(drive))
++                      goto Eintr;
++              if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
++                      goto Eintr;
++              process_fd_request();
++      }
++      v.spinup_date = UDRS->spinup_date;
++      v.select_date = UDRS->select_date;
++      v.first_read_date = UDRS->first_read_date;
++      v.probed_format = UDRS->probed_format;
++      v.track = UDRS->track;
++      v.maxblock = UDRS->maxblock;
++      v.maxtrack = UDRS->maxtrack;
++      v.generation = UDRS->generation;
++      v.keep_data = UDRS->keep_data;
++      v.fd_ref = UDRS->fd_ref;
++      v.fd_device = UDRS->fd_device;
++      v.last_checked = UDRS->last_checked;
++      v.dmabuf = (uintptr_t)UDRS->dmabuf;
++      v.bufblocks = UDRS->bufblocks;
++      mutex_unlock(&floppy_mutex);
++
++      if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct)))
++              return -EFAULT;
++      return 0;
++Eintr:
++      mutex_unlock(&floppy_mutex);
++      return -EINTR;
++}
++
++static int compat_getfdcstat(int drive,
++                          struct compat_floppy_fdc_state __user *arg)
++{
++      struct compat_floppy_fdc_state v32;
++      struct floppy_fdc_state v;
++
++      mutex_lock(&floppy_mutex);
++      v = *UFDCS;
++      mutex_unlock(&floppy_mutex);
++
++      memset(&v32, 0, sizeof(struct compat_floppy_fdc_state));
++      v32.spec1 = v.spec1;
++      v32.spec2 = v.spec2;
++      v32.dtr = v.dtr;
++      v32.version = v.version;
++      v32.dor = v.dor;
++      v32.address = v.address;
++      v32.rawcmd = v.rawcmd;
++      v32.reset = v.reset;
++      v32.need_configure = v.need_configure;
++      v32.perp_mode = v.perp_mode;
++      v32.has_fifo = v.has_fifo;
++      v32.driver_version = v.driver_version;
++      memcpy(v32.track, v.track, 4);
++      if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state)))
++              return -EFAULT;
++      return 0;
++}
++
++static int compat_werrorget(int drive,
++                          struct compat_floppy_write_errors __user *arg)
++{
++      struct compat_floppy_write_errors v32;
++      struct floppy_write_errors v;
++
++      memset(&v32, 0, sizeof(struct compat_floppy_write_errors));
++      mutex_lock(&floppy_mutex);
++      v = *UDRWE;
++      mutex_unlock(&floppy_mutex);
++      v32.write_errors = v.write_errors;
++      v32.first_error_sector = v.first_error_sector;
++      v32.first_error_generation = v.first_error_generation;
++      v32.last_error_sector = v.last_error_sector;
++      v32.last_error_generation = v.last_error_generation;
++      v32.badness = v.badness;
++      if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors)))
++              return -EFAULT;
++      return 0;
++}
++
++static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
++                  unsigned long param)
++{
++      int drive = (long)bdev->bd_disk->private_data;
++      switch (cmd) {
++      case FDMSGON:
++      case FDMSGOFF:
++      case FDSETEMSGTRESH:
++      case FDFLUSH:
++      case FDWERRORCLR:
++      case FDEJECT:
++      case FDCLRPRM:
++      case FDFMTBEG:
++      case FDRESET:
++      case FDTWADDLE:
++              return fd_ioctl(bdev, mode, cmd, param);
++      case FDSETMAXERRS:
++      case FDGETMAXERRS:
++      case FDGETDRVTYP:
++      case FDFMTEND:
++      case FDFMTTRK:
++      case FDRAWCMD:
++              return fd_ioctl(bdev, mode, cmd,
++                              (unsigned long)compat_ptr(param));
++      case FDSETPRM32:
++      case FDDEFPRM32:
++              return compat_set_geometry(bdev, mode, cmd, compat_ptr(param));
++      case FDGETPRM32:
++              return compat_get_prm(drive, compat_ptr(param));
++      case FDSETDRVPRM32:
++              return compat_setdrvprm(drive, compat_ptr(param));
++      case FDGETDRVPRM32:
++              return compat_getdrvprm(drive, compat_ptr(param));
++      case FDPOLLDRVSTAT32:
++              return compat_getdrvstat(drive, true, compat_ptr(param));
++      case FDGETDRVSTAT32:
++              return compat_getdrvstat(drive, false, compat_ptr(param));
++      case FDGETFDCSTAT32:
++              return compat_getfdcstat(drive, compat_ptr(param));
++      case FDWERRORGET32:
++              return compat_werrorget(drive, compat_ptr(param));
++      }
++      return -EINVAL;
++}
++#endif
++
+ static void __init config_types(void)
+ {
+       bool has_drive = false;
+@@ -3891,6 +4216,9 @@ static const struct block_device_operations floppy_fops = {
+       .getgeo                 = fd_getgeo,
+       .check_events           = floppy_check_events,
+       .revalidate_disk        = floppy_revalidate,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl           = fd_compat_ioctl,
++#endif
+ };
+ /*
+-- 
+2.20.1
+