[Y2038] [PATCH v2 11/27] compat_ioctl: move CDROM_SEND_PACKET handling into scsi

2019-12-17 Thread Arnd Bergmann
There is only one implementation of this ioctl, so move the handling out
of the common block layer code into the place where it's actually needed.

It also gets called indirectly through pktcdvd, which needs to be aware
of this change.

As I noticed, the old implementation of the compat handler failed to
convert the structure on the way out, so the updated fields never got
written back to user space. This is either not important, or it has
never worked and should be fixed now.

Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c|  47 +-
 block/scsi_ioctl.c  | 185 
 drivers/block/pktcdvd.c |   6 +-
 3 files changed, 135 insertions(+), 103 deletions(-)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index f16ae92065d7..578e04f94619 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -102,18 +102,6 @@ struct compat_cdrom_read_audio {
compat_caddr_t  buf;
 };
 
-struct compat_cdrom_generic_command {
-   unsigned char   cmd[CDROM_PACKET_SIZE];
-   compat_caddr_t  buffer;
-   compat_uint_t   buflen;
-   compat_int_tstat;
-   compat_caddr_t  sense;
-   unsigned char   data_direction;
-   compat_int_tquiet;
-   compat_int_ttimeout;
-   compat_caddr_t  reserved[1];
-};
-
 static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
 {
@@ -141,38 +129,6 @@ static int compat_cdrom_read_audio(struct block_device 
*bdev, fmode_t mode,
(unsigned long)cdread_audio);
 }
 
-static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t 
mode,
-   unsigned int cmd, unsigned long arg)
-{
-   struct cdrom_generic_command __user *cgc;
-   struct compat_cdrom_generic_command __user *cgc32;
-   u32 data;
-   unsigned char dir;
-   int itmp;
-
-   cgc = compat_alloc_user_space(sizeof(*cgc));
-   cgc32 = compat_ptr(arg);
-
-   if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
-   get_user(data, &cgc32->buffer) ||
-   put_user(compat_ptr(data), &cgc->buffer) ||
-   copy_in_user(&cgc->buflen, &cgc32->buflen,
-(sizeof(unsigned int) + sizeof(int))) ||
-   get_user(data, &cgc32->sense) ||
-   put_user(compat_ptr(data), &cgc->sense) ||
-   get_user(dir, &cgc32->data_direction) ||
-   put_user(dir, &cgc->data_direction) ||
-   get_user(itmp, &cgc32->quiet) ||
-   put_user(itmp, &cgc->quiet) ||
-   get_user(itmp, &cgc32->timeout) ||
-   put_user(itmp, &cgc->timeout) ||
-   get_user(data, &cgc32->reserved[0]) ||
-   put_user(compat_ptr(data), &cgc->reserved[0]))
-   return -EFAULT;
-
-   return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
-}
-
 struct compat_blkpg_ioctl_arg {
compat_int_t op;
compat_int_t flags;
@@ -224,8 +180,6 @@ static int compat_blkdev_driver_ioctl(struct block_device 
*bdev, fmode_t mode,
return compat_hdio_ioctl(bdev, mode, cmd, arg);
case CDROMREADAUDIO:
return compat_cdrom_read_audio(bdev, mode, cmd, arg);
-   case CDROM_SEND_PACKET:
-   return compat_cdrom_generic_command(bdev, mode, cmd, arg);
 
/*
 * No handler required for the ones below, we just need to
@@ -263,6 +217,7 @@ static int compat_blkdev_driver_ioctl(struct block_device 
*bdev, fmode_t mode,
case CDROM_DISC_STATUS:
case CDROM_CHANGER_NSLOTS:
case CDROM_GET_CAPABILITY:
+   case CDROM_SEND_PACKET:
/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
 * not take a struct cdrom_read, instead they take a struct cdrom_msf
 * which is compatible.
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index b61dbf4d8443..b4e73d5dd5c2 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -639,6 +639,136 @@ int get_sg_io_hdr(struct sg_io_hdr *hdr, const void 
__user *argp)
 }
 EXPORT_SYMBOL(get_sg_io_hdr);
 
+#ifdef CONFIG_COMPAT
+struct compat_cdrom_generic_command {
+   unsigned char   cmd[CDROM_PACKET_SIZE];
+   compat_caddr_t  buffer;
+   compat_uint_t   buflen;
+   compat_int_tstat;
+   compat_caddr_t  sense;
+   unsigned char   data_direction;
+   compat_int_tquiet;
+   compat_int_ttimeout;
+   compat_caddr_t  reserved[1];
+};
+#endif
+
+static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
+ const void __user *arg)
+{
+#ifdef CONFIG_COMPAT
+   if (in_compat_syscall()) {
+   struct compat_cdrom_generic_command cgc32;
+
+   if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
+   return -EFAULT;
+
+   *cgc = (struct cdrom_generic_command) {
+   .buffer = compat_ptr

[Y2038] [PATCH v2 04/27] compat_ioctl: block: handle add zone open, close and finish ioctl

2019-12-17 Thread Arnd Bergmann
These were added to blkdev_ioctl() in linux-5.5 but not
blkdev_compat_ioctl, so add them now.

Fixes: e876df1fe0ad ("block: add zone open, close and finish ioctl support")
Reviewed-by: Damien Le Moal 
Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index f5c1140b8624..5b13e344229c 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -356,6 +356,9 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
case BLKRRPART:
case BLKREPORTZONE:
case BLKRESETZONE:
+   case BLKOPENZONE:
+   case BLKCLOSEZONE:
+   case BLKFINISHZONE:
case BLKGETZONESZ:
case BLKGETNRZONES:
return blkdev_ioctl(bdev, mode, cmd,
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


Re: [Y2038] [PATCH v7 0/8] Fix year 2038 issue for sound subsystem

2019-12-17 Thread Takashi Iwai
On Tue, 17 Dec 2019 22:15:32 +0100,
Arnd Bergmann wrote:
> 
> On Tue, Dec 17, 2019 at 11:42 AM Takashi Iwai  wrote:
> > On Wed, 11 Dec 2019 22:20:16 +0100,
> > Arnd Bergmann wrote:
> 
> > >
> > > I hope I addressed all review comments by now, so please pull this
> > > for linux-5.6.
> > >
> > > A git branch with the same contents is available for testing at [1].
> > >
> > >  Arnd
> >
> > I see no issue other than the timer API patch Ben pointed.
> >
> > Could you resubmit that patch?  Or just submit the whole as v8, I
> > don't mind either way.  Then we'll get this done for 5.6.
> 
> Can you take this as a pull request? That would be ideal for me,
> as I can then use it as a parent for a shared branch with additional
> cleanups on top (removing time_t etc) in linux-next. It also provides
> a nice place to preserve the series cover letter.
> 
> I'm sending you the pull request now, and the last modified patch,
> in case you prefer the patch over a git tag.

That's fine for me.  Now I pulled it to a branch for 5.6 kernel.

Thanks for your patient works!


Takashi
___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 24/27] compat_ioctl: block: move blkdev_compat_ioctl() into ioctl.c

2019-12-17 Thread Arnd Bergmann
Having both in the same file allows a number of simplifications
to the compat path, and makes it more likely that changes to
the native path get applied to the compat version as well.

Signed-off-by: Arnd Bergmann 
---
 block/Makefile   |   1 -
 block/compat_ioctl.c | 225 ---
 block/ioctl.c| 219 +
 3 files changed, 219 insertions(+), 226 deletions(-)
 delete mode 100644 block/compat_ioctl.c

diff --git a/block/Makefile b/block/Makefile
index 205a5f2fef17..1f70c73ea83d 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER)+= kyber-iosched.o
 bfq-y  := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
 obj-$(CONFIG_IOSCHED_BFQ)  += bfq.o
 
-obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
 obj-$(CONFIG_BLK_CMDLINE_PARSER)   += cmdline-parser.o
 obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
 obj-$(CONFIG_BLK_MQ_PCI)   += blk-mq-pci.o
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
deleted file mode 100644
index 765aa5357655..
--- a/block/compat_ioctl.c
+++ /dev/null
@@ -1,225 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-static int compat_put_ushort(unsigned long arg, unsigned short val)
-{
-   return put_user(val, (unsigned short __user *)compat_ptr(arg));
-}
-
-static int compat_put_int(unsigned long arg, int val)
-{
-   return put_user(val, (compat_int_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_uint(unsigned long arg, unsigned int val)
-{
-   return put_user(val, (compat_uint_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_long(unsigned long arg, long val)
-{
-   return put_user(val, (compat_long_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
-{
-   return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_u64(unsigned long arg, u64 val)
-{
-   return put_user(val, (compat_u64 __user *)compat_ptr(arg));
-}
-
-struct compat_hd_geometry {
-   unsigned char heads;
-   unsigned char sectors;
-   unsigned short cylinders;
-   u32 start;
-};
-
-static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
-   struct compat_hd_geometry __user *ugeo)
-{
-   struct hd_geometry geo;
-   int ret;
-
-   if (!ugeo)
-   return -EINVAL;
-   if (!disk->fops->getgeo)
-   return -ENOTTY;
-
-   memset(&geo, 0, sizeof(geo));
-   /*
-* We need to set the startsect first, the driver may
-* want to override it.
-*/
-   geo.start = get_start_sect(bdev);
-   ret = disk->fops->getgeo(bdev, &geo);
-   if (ret)
-   return ret;
-
-   ret = copy_to_user(ugeo, &geo, 4);
-   ret |= put_user(geo.start, &ugeo->start);
-   if (ret)
-   ret = -EFAULT;
-
-   return ret;
-}
-
-struct compat_blkpg_ioctl_arg {
-   compat_int_t op;
-   compat_int_t flags;
-   compat_int_t datalen;
-   compat_caddr_t data;
-};
-
-static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
-   unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
-{
-   struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
-   compat_caddr_t udata;
-   compat_int_t n;
-   int err;
-
-   err = get_user(n, &ua32->op);
-   err |= put_user(n, &a->op);
-   err |= get_user(n, &ua32->flags);
-   err |= put_user(n, &a->flags);
-   err |= get_user(n, &ua32->datalen);
-   err |= put_user(n, &a->datalen);
-   err |= get_user(udata, &ua32->data);
-   err |= put_user(compat_ptr(udata), &a->data);
-   if (err)
-   return err;
-
-   return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
-}
-
-#define BLKBSZGET_32   _IOR(0x12, 112, int)
-#define BLKBSZSET_32   _IOW(0x12, 113, int)
-#define BLKGETSIZE64_32_IOR(0x12, 114, int)
-
-/* Most of the generic ioctls are handled in the normal fallback path.
-   This assumes the blkdev's low level compat_ioctl always returns
-   ENOIOCTLCMD for unknown ioctls. */
-long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
-{
-   int ret = -ENOIOCTLCMD;
-   struct inode *inode = file->f_mapping->host;
-   struct block_device *bdev = inode->i_bdev;
-   struct gendisk *disk = bdev->bd_disk;
-   fmode_t mode = file->f_mode;
-   loff_t size;
-   unsigned int max_sectors;
-
-   /*
-* O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
-* to updated it before every ioctl.
-*/
-   if (file->f_flags & O_NDELAY)
-   mode |= FMODE_NDELAY;
-   else
-   

[Y2038] [PATCH v2 18/27] compat_ioctl: scsi: move ioctl handling into drivers

2019-12-17 Thread Arnd Bergmann
Each driver calling scsi_ioctl() gets an equivalent compat_ioctl()
handler that implements the same commands by calling scsi_compat_ioctl().

The scsi_cmd_ioctl() and scsi_cmd_blk_ioctl() functions are compatible
at this point, so any driver that calls those can do so for both native
and compat mode, with the argument passed through compat_ptr().

With this, we can remove the entries from fs/compat_ioctl.c.  The new
code is larger, but should be easier to maintain and keep updated with
newly added commands.

Signed-off-by: Arnd Bergmann 
---
 drivers/block/virtio_blk.c |   3 +
 drivers/scsi/ch.c  |   9 ++-
 drivers/scsi/sd.c  |  50 ++
 drivers/scsi/sg.c  |  44 -
 drivers/scsi/sr.c  |  57 ++--
 drivers/scsi/st.c  |  51 --
 fs/compat_ioctl.c  | 132 +
 7 files changed, 142 insertions(+), 204 deletions(-)

diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 7ffd719d89de..fbbf18ac1d5d 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -405,6 +405,9 @@ static int virtblk_getgeo(struct block_device *bd, struct 
hd_geometry *geo)
 
 static const struct block_device_operations virtblk_fops = {
.ioctl  = virtblk_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl = blkdev_compat_ptr_ioctl,
+#endif
.owner  = THIS_MODULE,
.getgeo = virtblk_getgeo,
 };
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 76751d6c7f0d..ed5f4a6ae270 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -872,6 +872,10 @@ static long ch_ioctl_compat(struct file * file,
unsigned int cmd, unsigned long arg)
 {
scsi_changer *ch = file->private_data;
+   int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
+   file->f_flags & 
O_NDELAY);
+   if (retval)
+   return retval;
 
switch (cmd) {
case CHIOGPARAMS:
@@ -883,7 +887,7 @@ static long ch_ioctl_compat(struct file * file,
case CHIOINITELEM:
case CHIOSVOLTAG:
/* compatible */
-   return ch_ioctl(file, cmd, arg);
+   return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
case CHIOGSTATUS32:
{
struct changer_element_status32 ces32;
@@ -898,8 +902,7 @@ static long ch_ioctl_compat(struct file * file,
return ch_gstatus(ch, ces32.ces_type, data);
}
default:
-   // return scsi_ioctl_compat(ch->device, cmd, (void*)arg);
-   return -ENOIOCTLCMD;
+   return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));
 
}
 }
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index cea625906440..5afb0046b12a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1465,13 +1465,12 @@ static int sd_getgeo(struct block_device *bdev, struct 
hd_geometry *geo)
  * Note: most ioctls are forward onto the block subsystem or further
  * down in the scsi subsystem.
  **/
-static int sd_ioctl(struct block_device *bdev, fmode_t mode,
-   unsigned int cmd, unsigned long arg)
+static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
+  unsigned int cmd, void __user *p)
 {
struct gendisk *disk = bdev->bd_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
-   void __user *p = (void __user *)arg;
int error;
 
SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
@@ -1507,9 +1506,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t 
mode,
break;
default:
error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
-   if (error != -ENOTTY)
-   break;
-   error = scsi_ioctl(sdp, cmd, p);
break;
}
 out:
@@ -1691,39 +1687,31 @@ static void sd_rescan(struct device *dev)
revalidate_disk(sdkp->disk);
 }
 
+static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+   unsigned int cmd, unsigned long arg)
+{
+   void __user *p = (void __user *)arg;
+   int ret;
+
+   ret = sd_ioctl_common(bdev, mode, cmd, p);
+   if (ret != -ENOTTY)
+   return ret;
+
+   return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
+}
 
 #ifdef CONFIG_COMPAT
-/* 
- * This gets directly called from VFS. When the ioctl 
- * is not recognized we go back to the other translation paths. 
- */
 static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
   unsigned int cmd, unsigned long arg)
 {
-   struct gendisk *disk = bdev->bd_disk;
-   struct scsi_disk *sdkp = scsi_disk(disk);
-   struct scsi_device *sdev = sdkp->device;
void

[Y2038] [PATCH v2 16/27] compat_ioctl: bsg: add handler

2019-12-17 Thread Arnd Bergmann
bsg_ioctl() calls into scsi_cmd_ioctl() for a couple of generic commands
and relies on fs/compat_ioctl.c to handle it correctly in compat mode.

Adding a private compat_ioctl() handler avoids that round-trip and lets
us get rid of the generic emulation once this is done.

Note that bsg implements an SG_IO command that is different from the
other drivers and does not need emulation.

Signed-off-by: Arnd Bergmann 
---
 block/bsg.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/bsg.c b/block/bsg.c
index 833c44b3d458..d7bae94b64d9 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -382,6 +382,7 @@ static const struct file_operations bsg_fops = {
.open   =   bsg_open,
.release=   bsg_release,
.unlocked_ioctl =   bsg_ioctl,
+   .compat_ioctl   =   compat_ptr_ioctl,
.owner  =   THIS_MODULE,
.llseek =   default_llseek,
 };
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 21/27] compat_ioctl: move cdrom commands into cdrom.c

2019-12-17 Thread Arnd Bergmann
There is no need for the special cases for the cdrom ioctls any more now,
so make sure that each cdrom driver has a .compat_ioctl() callback and
calls cdrom_compat_ioctl() directly there.

Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c   | 45 --
 drivers/block/paride/pcd.c |  3 +++
 drivers/cdrom/gdrom.c  |  3 +++
 drivers/ide/ide-cd.c   | 36 ++
 drivers/scsi/sr.c  | 10 +++--
 5 files changed, 45 insertions(+), 52 deletions(-)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index cf136bc2c9fc..7cb534d6e767 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -159,42 +159,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:
-   /* CDROM stuff */
-   case CDROMPAUSE:
-   case CDROMRESUME:
-   case CDROMPLAYMSF:
-   case CDROMPLAYTRKIND:
-   case CDROMREADTOCHDR:
-   case CDROMREADTOCENTRY:
-   case CDROMSTOP:
-   case CDROMSTART:
-   case CDROMEJECT:
-   case CDROMVOLCTRL:
-   case CDROMSUBCHNL:
-   case CDROMMULTISESSION:
-   case CDROM_GET_MCN:
-   case CDROMRESET:
-   case CDROMVOLREAD:
-   case CDROMSEEK:
-   case CDROMPLAYBLK:
-   case CDROMCLOSETRAY:
-   case CDROM_DISC_STATUS:
-   case CDROM_CHANGER_NSLOTS:
-   case CDROM_GET_CAPABILITY:
-   case CDROM_SEND_PACKET:
-   /* Ignore cdrom.h about these next 5 ioctls, they absolutely do
-* not take a struct cdrom_read, instead they take a struct cdrom_msf
-* which is compatible.
-*/
-   case CDROMREADMODE2:
-   case CDROMREADMODE1:
-   case CDROMREADRAW:
-   case CDROMREADCOOKED:
-   case CDROMREADALL:
-   /* DVD ioctls */
-   case DVD_READ_STRUCT:
-   case DVD_WRITE_STRUCT:
-   case DVD_AUTH:
arg = (unsigned long)compat_ptr(arg);
/* These intepret arg as an unsigned long, not as a pointer,
 * so we must not do compat_ptr() conversion. */
@@ -210,15 +174,6 @@ static int compat_blkdev_driver_ioctl(struct block_device 
*bdev, fmode_t mode,
case HDIO_SET_ACOUSTIC:
case HDIO_SET_BUSSTATE:
case HDIO_SET_ADDRESS:
-   case CDROMEJECT_SW:
-   case CDROM_SET_OPTIONS:
-   case CDROM_CLEAR_OPTIONS:
-   case CDROM_SELECT_SPEED:
-   case CDROM_SELECT_DISC:
-   case CDROM_MEDIA_CHANGED:
-   case CDROM_DRIVE_STATUS:
-   case CDROM_LOCKDOOR:
-   case CDROM_DEBUG:
break;
default:
/* unknown ioctl number */
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 636bfea2de6f..117cfc8cd05a 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -275,6 +275,9 @@ static const struct block_device_operations pcd_bdops = {
.open   = pcd_block_open,
.release= pcd_block_release,
.ioctl  = pcd_block_ioctl,
+#ifdef CONFIG_COMPAT
+   .ioctl  = blkdev_compat_ptr_ioctl,
+#endif
.check_events   = pcd_block_check_events,
 };
 
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 5b21dc421c94..886b2638c730 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -518,6 +518,9 @@ static const struct block_device_operations gdrom_bdops = {
.release= gdrom_bdops_release,
.check_events   = gdrom_bdops_check_events,
.ioctl  = gdrom_bdops_ioctl,
+#ifdef CONFIG_COMPAT
+   .ioctl  = blkdev_compat_ptr_ioctl,
+#endif
 };
 
 static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id)
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 9d117936bee1..2de6e8ace957 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -25,6 +25,7 @@
 
 #define IDECD_VERSION "5.00"
 
+#include 
 #include 
 #include 
 #include 
@@ -1710,6 +1711,38 @@ static int idecd_ioctl(struct block_device *bdev, 
fmode_t mode,
return ret;
 }
 
+#ifdef CONFIG_COMPAT
+static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode,
+   unsigned int cmd, unsigned long arg)
+{
+   struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
+   int err;
+
+   switch (cmd) {
+   case CDROMSETSPINDOWN:
+   return idecd_set_spindown(&info->devinfo, arg);
+   case CDROMGETSPINDOWN:
+   return idecd_get_spindown(&info->devinfo, arg);
+   default:
+   break;
+   }
+
+   return cdrom_ioctl(&info->devinfo, bdev, mode, cmd,
+  (unsigned long)compat_ptr(arg));
+}
+
+static int idecd_compat_ioctl(struct block_device *bdev, fmode_t mode,
+unsigned int cmd, unsigned long arg)
+{
+   int ret;
+
+   mutex_lock

[Y2038] [PATCH v2 27/27] Documentation: document ioctl interfaces better

2019-12-17 Thread Arnd Bergmann
Documentation/process/botching-up-ioctls.rst was orignally
written as a blog post for DRM driver writers, so it it misses
some points while going into a lot of detail on others.

Try to provide a replacement that addresses typical issues
across a wider range of subsystems, and follows the style of
the core-api documentation better.

Signed-off-by: Arnd Bergmann 
---
 Documentation/core-api/index.rst |   1 +
 Documentation/core-api/ioctl.rst | 248 +++
 2 files changed, 249 insertions(+)
 create mode 100644 Documentation/core-api/ioctl.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index ab0eae1c153a..3f28b2f668be 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -39,6 +39,7 @@ Core utilities
../RCU/index
gcc-plugins
symbol-namespaces
+   ioctl
 
 
 Interfaces for kernel debugging
diff --git a/Documentation/core-api/ioctl.rst b/Documentation/core-api/ioctl.rst
new file mode 100644
index ..99892f96c5cb
--- /dev/null
+++ b/Documentation/core-api/ioctl.rst
@@ -0,0 +1,248 @@
+==
+ioctl based interfaces
+==
+
+ioctl() is the most common way for applications to interface
+with device drivers. It is flexible and easily extended by adding new
+commands and can be passed through character devices, block devices as
+well as sockets and other special file descriptors.
+
+However, it is also very easy to get ioctl command definitions wrong,
+and hard to fix them later without breaking existing applications,
+so this documentation tries to help developers get it right.
+
+Command number definitions
+==
+
+The command number, or request number, is the second argument passed to
+the ioctl system call. While this can be any 32-bit number that uniquely
+identifies an action for a particular driver, there are a number of
+conventions around defining them.
+
+``include/uapi/asm-generic/ioctl.h`` provides four macros for defining
+ioctl commands that follow modern conventions: ``_IO``, ``_IOR``,
+``_IOW``, and ``_IORW``. These should be used for all new commands,
+with the correct parameters:
+
+_IO/_IOR/_IOW/_IOWR
+   The macro name determines whether the argument is used for passing
+   data into kernel (_IOW), from the kernel (_IOR), both (_IOWR) or is
+   not a pointer (_IO). It is possible but not recommended to pass an
+   integer value instead of a pointer with _IO.
+
+type
+   An 8-bit number, often a character literal, specific to a subsystem
+   or driver, and listed in :doc:`../userspace-api/ioctl/ioctl-number`
+
+nr
+  An 8-bit number identifying the specific command, unique for a give
+  value of 'type'
+
+data_type
+  The name of the data type pointed to by the argument, the command number
+  encodes the ``sizeof(data_type)`` value in a 13-bit or 14-bit integer,
+  leading to a limit of 8191 bytes for the maximum size of the argument.
+  Note: do not pass sizeof(data_type) type into _IOR/IOW, as that will
+  lead to encoding sizeof(sizeof(data_type)), i.e. sizeof(size_t).
+
+
+Interface versions
+==
+
+Some subsystems use version numbers in data structures to overload
+commands with different interpretations of the argument.
+
+This is generally a bad idea, since changes to existing commands tend
+to break existing applications.
+
+A better approach is to add a new ioctl command with a new number. The
+old command still needs to be implemented in the kernel for compatibility,
+but this can be a wrapper around the new implementation.
+
+Return code
+===
+
+ioctl commands can return negative error codes as documented in errno(3),
+these get turned into errno values in user space. On success, the return
+code should be zero. It is also possible but not recommended to return
+a positive 'long' value.
+
+When the ioctl callback is called with an unknown command number, the
+handler returns either -ENOTTY or -ENOIOCTLCMD, which also results in
+-ENOTTY being returned from the system call. Some subsystems return
+-ENOSYS or -EINVAL here for historic reasons, but this is wrong.
+
+Prior to Linux-5.5, compat_ioctl handlers were required to return
+-ENOIOCTLCMD in order to use the fallback conversion into native
+commands. As all subsystems are now responsible for handling compat
+mode themselves, this is no longer needed, but it may be important to
+consider when backporting bug fixes to older kernels.
+
+Timestamps
+==
+
+Traditionally, timestamps and timeout values are passed as ``struct
+timespec`` or ``struct timeval``, but these are problematic because of
+incompatible definitions of these structures in user space after the
+move to 64-bit time_t.
+
+The __kernel_timespec type can be used instead to be embedded in other
+data structures when separate second/nanosecond values are desired,
+or passed to user space directly. This is still not ideal though,
+as the structure matches neither the kernel

Re: [Y2038] [PATCH v2 21/24] xfs: quota: move to time64_t interfaces

2019-12-17 Thread Darrick J. Wong
On Tue, Dec 17, 2019 at 04:02:47PM +0100, Arnd Bergmann wrote:
> On Mon, Dec 16, 2019 at 5:52 PM Arnd Bergmann  wrote:
> > On Fri, Dec 13, 2019 at 10:17 PM Darrick J. Wong  
> > wrote:
> >>
> >> Hmm, so one thing that I clean up on the way to bigtime is the total
> >> lack of clamping here.  If (for example) it's September 2105 and
> >> rtbtimelimit is set to 1 year, this will cause an integer overflow.  The
> >> quota timer will be set to 1970 and expire immediately, rather than what
> >> I'd consider the best effort of February 2106.
> 
> One more hing to note (I will add this to the changelog text) is that on

Ok, I'll look for it in the next revision you send out.

By the way, would you mind cc'ing the xfs list on all 24 patches?  They
probably aren't directly relevant to xfs, but it does make it a lot
easier for us to look at the other 21 patches and think "Oh, ok, so
there isn't some core infrastructure change that we're not seeing".

> 32-bit architectures, the limit here is y2038, while on 64-bit
> architectures it's y2106:

Yikes.  I probably just need to send the bigtime series and see what you
all think about the mess I created^W^W^Wway I dealt with all that.

> int xfs_trans_dqresv(...)
> {
>time_t  timer; /* signed 'long' */
>timer = be32_to_cpu(dqp->q_core.d_btimer);
>/* get_seconds() returns unsigned long */
>   if ((timer != 0 && get_seconds() > timer))
> return -EDQUOT;
> }
> 
> > I don't think clamping would be good here, that just replaces
> > one bug with another at the overflow time. If you would like to
> > have something better before this gets extended, I could try to
> > come up with a version that converts it to the nearest 64-bit
> > timestamp, similar to the way that time_before32() in the kernel
> > or the NTP protocol work.
> >
> > If you think it can get extended properly soon, I'd just leave the
> > patch as it is today in order to remove the get_seconds()
> > interface for v5.6.
> 
> I've tried this now, and but this feels wrong: it adds lots of complexity
> for corner cases and is still fragile, e.g. when the time is wrong
> during boot before ntp runs. See that patch below for reference.

Yeah, that is pretty weird to glue the upper 32 bits of the timestamp
onto the expiration timer...

--D

> I also see that quotatool on xfs always uses the old xfs quota
> interface, so it already overflows on the user space side. Fixing
> this properly seems to be a bigger effort than I was planning for
> (on an unpatched 64-bit kernel):
> 
> $ sudo quotatool -b-u  -t 220month  /mnt/tmp -r
> $ rm file ; fallocate -l 11M file
> $ sudo quotatool -d /mnt/tmp -u arnd
> 1000 /mnt/tmp 11264 10240 20480 570239975 2 0 00
> $ sudo quotatool -b-u  -t 222month  /mnt/tmp -r
> $ rm file ; fallocate -l 11M file
> $ sudo quotatool -d /mnt/tmp -u arnd
> 1000 /mnt/tmp 11264 10240 20480 18446744069990008316 2 0 00
> 
>Arnd
> 
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index 9cfd3209f52b..6c9128bb607b 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -98,6 +98,23 @@ xfs_qm_adjust_dqlimits(
> xfs_dquot_set_prealloc_limits(dq);
>  }
> 
> +static __be32 xfs_quota_timeout32(s64 limit)
> +{
> +   time64_t now = ktime_get_real_seconds();
> +   u32 timeout;
> +
> +   /* avoid overflows in out-of-range limits */
> +   if ((u64)limit > S32_MAX)
> +   limit = S32_MAX;
> +   timeout = now + limit;
> +
> +   /* avoid timeout of zero */
> +   if (lower_32_bits(timeout) == 0)
> +   return cpu_to_be32(1);
> +
> +   return cpu_to_be32(lower_32_bits(timeout));
> +}
> +
>  /*
>   * Check the limits and timers of a dquot and start or reset timers
>   * if necessary.
> @@ -137,7 +154,7 @@ xfs_qm_adjust_dqtimers(
> (d->d_blk_hardlimit &&
>  (be64_to_cpu(d->d_bcount) >
>   be64_to_cpu(d->d_blk_hardlimit {
> -   d->d_btimer = cpu_to_be32(ktime_get_real_seconds() +
> +   d->d_btimer = xfs_quota_timeout32(
> mp->m_quotainfo->qi_btimelimit);
> } else {
> d->d_bwarns = 0;
> @@ -160,7 +177,7 @@ xfs_qm_adjust_dqtimers(
> (d->d_ino_hardlimit &&
>  (be64_to_cpu(d->d_icount) >
>   be64_to_cpu(d->d_ino_hardlimit {
> -   d->d_itimer = cpu_to_be32(ktime_get_real_seconds() +
> +   d->d_itimer = xfs_quota_timeout32(
> mp->m_quotainfo->qi_itimelimit);
> } else {
> d->d_iwarns = 0;
> @@ -183,7 +200,7 @@ xfs_qm_adjust_dqtimers(
> (d->d_rtb_hardlimit &&
>  (be64_to_cpu(d->d_rtbcount) >
>   be64_to_cpu(d->d_rtb_hardlimit {
> -  

[Y2038] [PATCH v2 23/27] compat_ioctl: move HDIO ioctl handling into drivers/ide

2019-12-17 Thread Arnd Bergmann
Most of the HDIO ioctls are only used by the obsolete drivers/ide
subsystem, these can be handled by changing ide_cmd_ioctl() to be aware
of compat mode and doing the correct transformations in place and using
it as both native and compat handlers for all drivers.

The SCSI drivers implementing the same commands are already doing
this in the drivers, so the compat_blkdev_driver_ioctl() function
is no longer needed now.

The BLKSECTSET and HDIO_GETGEO_BIG ioctls are not implemented
in any driver any more and no longer need any conversion.

Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c   | 75 --
 drivers/ide/ide-cd.c   | 15 +++
 drivers/ide/ide-disk.c |  1 +
 drivers/ide/ide-floppy_ioctl.c |  7 ++--
 drivers/ide/ide-ioctls.c   | 44 
 drivers/ide/ide-tape.c | 11 +
 6 files changed, 51 insertions(+), 102 deletions(-)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 7cb534d6e767..765aa5357655 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -77,24 +77,6 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct 
block_device *bdev,
return ret;
 }
 
-static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
-   unsigned int cmd, unsigned long arg)
-{
-   unsigned long __user *p;
-   int error;
-
-   p = compat_alloc_user_space(sizeof(unsigned long));
-   error = __blkdev_driver_ioctl(bdev, mode,
-   cmd, (unsigned long)p);
-   if (error == 0) {
-   unsigned int __user *uvp = compat_ptr(arg);
-   unsigned long v;
-   if (get_user(v, p) || put_user(v, uvp))
-   error = -EFAULT;
-   }
-   return error;
-}
-
 struct compat_blkpg_ioctl_arg {
compat_int_t op;
compat_int_t flags;
@@ -128,61 +110,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)
 
-static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
-   unsigned cmd, unsigned long arg)
-{
-   switch (cmd) {
-   case HDIO_GET_UNMASKINTR:
-   case HDIO_GET_MULTCOUNT:
-   case HDIO_GET_KEEPSETTINGS:
-   case HDIO_GET_32BIT:
-   case HDIO_GET_NOWERR:
-   case HDIO_GET_DMA:
-   case HDIO_GET_NICE:
-   case HDIO_GET_WCACHE:
-   case HDIO_GET_ACOUSTIC:
-   case HDIO_GET_ADDRESS:
-   case HDIO_GET_BUSSTATE:
-   return compat_hdio_ioctl(bdev, mode, cmd, arg);
-
-   /*
-* No handler required for the ones below, we just need to
-* convert arg to a 64 bit pointer.
-*/
-   case BLKSECTSET:
-   /*
-* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
-* Some need translations, these do not.
-*/
-   case HDIO_GET_IDENTITY:
-   case HDIO_DRIVE_TASK:
-   case HDIO_DRIVE_CMD:
-   /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
-   case 0x330:
-   arg = (unsigned long)compat_ptr(arg);
-   /* These intepret arg as an unsigned long, not as a pointer,
-* so we must not do compat_ptr() conversion. */
-   case HDIO_SET_MULTCOUNT:
-   case HDIO_SET_UNMASKINTR:
-   case HDIO_SET_KEEPSETTINGS:
-   case HDIO_SET_32BIT:
-   case HDIO_SET_NOWERR:
-   case HDIO_SET_DMA:
-   case HDIO_SET_PIO_MODE:
-   case HDIO_SET_NICE:
-   case HDIO_SET_WCACHE:
-   case HDIO_SET_ACOUSTIC:
-   case HDIO_SET_BUSSTATE:
-   case HDIO_SET_ADDRESS:
-   break;
-   default:
-   /* unknown ioctl number */
-   return -ENOIOCTLCMD;
-   }
-
-   return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
-}
-
 /* Most of the generic ioctls are handled in the normal fallback path.
This assumes the blkdev's low level compat_ioctl always returns
ENOIOCTLCMD for unknown ioctls. */
@@ -293,8 +220,6 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
default:
if (disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
-   if (ret == -ENOIOCTLCMD)
-   ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
return ret;
}
 }
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 2de6e8ace957..284a7a5bad54 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1711,7 +1711,6 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t 
mode,
return ret;
 }
 
-#ifdef CONFIG_COMPAT
 static int idecd_locked_compat_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
 {
@@ -1727,8 +1726,12 @@ static int idecd_locked_compat_ioctl(struct block_device 
*bdev, fm

[Y2038] [PATCH v2 22/27] compat_ioctl: scsi: handle HDIO commands from drivers

2019-12-17 Thread Arnd Bergmann
The ata_sas_scsi_ioctl() function implements a number of HDIO_* commands
for SCSI devices, it is used by all libata drivers as well as a few
drivers that support SAS attached SATA drives.

The only command that is not safe for compat ioctls here is
HDIO_GET_32BIT. Change the implementation to check for in_compat_syscall()
in order to do both cases correctly, and change all callers to use it
as both native and compat callback pointers, including the indirect
callers through sas_ioctl and ata_scsi_ioctl.

Signed-off-by: Arnd Bergmann 
---
 drivers/ata/libata-scsi.c  | 9 +
 drivers/scsi/aic94xx/aic94xx_init.c| 3 +++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +++
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +++
 drivers/scsi/ipr.c | 3 +++
 drivers/scsi/isci/init.c   | 3 +++
 drivers/scsi/mvsas/mv_init.c   | 3 +++
 drivers/scsi/pm8001/pm8001_init.c  | 3 +++
 include/linux/libata.h | 6 ++
 10 files changed, 39 insertions(+)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 58e09ffe8b9c..eb2eb599e602 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -17,6 +17,7 @@
  *  - http://www.t13.org/
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -761,6 +762,10 @@ static int ata_ioc32(struct ata_port *ap)
return 0;
 }
 
+/*
+ * This handles both native and compat commands, so anything added
+ * here must have a compatible argument, or check in_compat_syscall()
+ */
 int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
 unsigned int cmd, void __user *arg)
 {
@@ -773,6 +778,10 @@ int ata_sas_scsi_ioctl(struct ata_port *ap, struct 
scsi_device *scsidev,
spin_lock_irqsave(ap->lock, flags);
val = ata_ioc32(ap);
spin_unlock_irqrestore(ap->lock, flags);
+#ifdef CONFIG_COMPAT
+   if (in_compat_syscall())
+   return put_user(val, (compat_ulong_t __user *)arg);
+#endif
return put_user(val, (unsigned long __user *)arg);
 
case HDIO_SET_32BIT:
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c 
b/drivers/scsi/aic94xx/aic94xx_init.c
index f5781e31f57c..d022407e5645 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -54,6 +54,9 @@ static struct scsi_host_template aic94xx_sht = {
.eh_target_reset_handler= sas_eh_target_reset_handler,
.target_destroy = sas_target_destroy,
.ioctl  = sas_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = sas_ioctl,
+#endif
.track_queue_depth  = 1,
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 3af53cc42bd6..fa25766502a2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1772,6 +1772,9 @@ static struct scsi_host_template sht_v1_hw = {
.eh_target_reset_handler = sas_eh_target_reset_handler,
.target_destroy = sas_target_destroy,
.ioctl  = sas_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = sas_ioctl,
+#endif
.shost_attrs= host_attrs_v1_hw,
.host_reset = hisi_sas_host_reset,
 };
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 61b1e2693b08..545eaff5f3ee 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3551,6 +3551,9 @@ static struct scsi_host_template sht_v2_hw = {
.eh_target_reset_handler = sas_eh_target_reset_handler,
.target_destroy = sas_target_destroy,
.ioctl  = sas_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = sas_ioctl,
+#endif
.shost_attrs= host_attrs_v2_hw,
.host_reset = hisi_sas_host_reset,
 };
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index bf5d5f138437..fa05e612d85a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -3075,6 +3075,9 @@ static struct scsi_host_template sht_v3_hw = {
.eh_target_reset_handler = sas_eh_target_reset_handler,
.target_destroy = sas_target_destroy,
.ioctl  = sas_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = sas_ioctl,
+#endif
.shost_attrs= host_attrs_v3_hw,
.tag_alloc_policy   = BLK_TAG_ALLOC_RR,
.host_reset = hisi_sas_host_reset,
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 079c04bc448a..ae45cbe98ae2 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6727,6 +6727,9 @@ static struct scsi_host_template driver_template = {
.name = "IPR",
.info = ipr_ioa_inf

[Y2038] [PATCH v2 20/27] compat_ioctl: simplify the implementation

2019-12-17 Thread Arnd Bergmann
Now that both native and compat ioctl syscalls are
in the same file, a couple of simplifications can
be made, bringing the implementation closer together:

- do_vfs_ioctl(), ioctl_preallocate(), and compat_ioctl_preallocate()
  can become static, allowing the compiler to optimize better

- slightly update the coding style for consistency between
  the functions.

- rather than listing each command in two switch statements
  for the compat case, just call a single function that has
  all the common commands.

As a side-effect, FS_IOC_RESVSP/FS_IOC_RESVSP64 are now available
to x86 compat tasks, along with FS_IOC_RESVSP_32/FS_IOC_RESVSP64_32.
This is harmless for i386 emulation, and can be considered a bugfix
for x32 emulation, which never supported these in the past.

Signed-off-by: Arnd Bergmann 
---
 fs/internal.h  |   6 --
 fs/ioctl.c | 157 +
 include/linux/falloc.h |   2 -
 include/linux/fs.h |   4 --
 4 files changed, 64 insertions(+), 105 deletions(-)

diff --git a/fs/internal.h b/fs/internal.h
index 4a7da1df573d..d46247850ad7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -180,11 +180,5 @@ extern void mnt_pin_kill(struct mount *m);
  */
 extern const struct dentry_operations ns_dentry_operations;
 
-/*
- * fs/ioctl.c
- */
-extern int do_vfs_ioctl(struct file *file, unsigned int fd, unsigned int cmd,
-   unsigned long arg);
-
 /* direct-io.c: */
 int sb_init_dio_done_wq(struct super_block *sb);
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 8f22f7817edb..7c9a5df5a597 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -467,7 +467,7 @@ EXPORT_SYMBOL(generic_block_fiemap);
  * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
  * are used here, rest are ignored.
  */
-int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
+static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
 {
struct inode *inode = file_inode(filp);
struct space_resv sr;
@@ -495,8 +495,8 @@ int ioctl_preallocate(struct file *filp, int mode, void 
__user *argp)
 /* on ia32 l_start is on a 32-bit boundary */
 #if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
 /* just account for different alignment */
-int compat_ioctl_preallocate(struct file *file, int mode,
-   struct space_resv_32 __user *argp)
+static int compat_ioctl_preallocate(struct file *file, int mode,
+   struct space_resv_32 __user *argp)
 {
struct inode *inode = file_inode(file);
struct space_resv_32 sr;
@@ -521,11 +521,9 @@ int compat_ioctl_preallocate(struct file *file, int mode,
 }
 #endif
 
-static int file_ioctl(struct file *filp, unsigned int cmd,
-   unsigned long arg)
+static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
 {
struct inode *inode = file_inode(filp);
-   int __user *p = (int __user *)arg;
 
switch (cmd) {
case FIBMAP:
@@ -542,7 +540,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
}
 
-   return vfs_ioctl(filp, cmd, arg);
+   return -ENOIOCTLCMD;
 }
 
 static int ioctl_fionbio(struct file *filp, int __user *argp)
@@ -661,53 +659,48 @@ static int ioctl_file_dedupe_range(struct file *file,
 }
 
 /*
- * When you add any new common ioctls to the switches above and below
- * please update compat_sys_ioctl() too.
- *
  * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
+ *
+ * When you add any new common ioctls to the switches above and below,
+ * please ensure they have compatible arguments in compat mode.
  */
-int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
-unsigned long arg)
+static int do_vfs_ioctl(struct file *filp, unsigned int fd,
+   unsigned int cmd, unsigned long arg)
 {
-   int error = 0;
void __user *argp = (void __user *)arg;
struct inode *inode = file_inode(filp);
 
switch (cmd) {
case FIOCLEX:
set_close_on_exec(fd, 1);
-   break;
+   return 0;
 
case FIONCLEX:
set_close_on_exec(fd, 0);
-   break;
+   return 0;
 
case FIONBIO:
-   error = ioctl_fionbio(filp, argp);
-   break;
+   return ioctl_fionbio(filp, argp);
 
case FIOASYNC:
-   error = ioctl_fioasync(fd, filp, argp);
-   break;
+   return ioctl_fioasync(fd, filp, argp);
 
case FIOQSIZE:
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
S_ISLNK(inode->i_mode)) {
loff_t res = inode_get_bytes(inode);
-   error = copy_to_user(argp, &res, sizeof(res)) ?
-   

[Y2038] [PATCH v2 15/27] compat_ioctl: add scsi_compat_ioctl

2019-12-17 Thread Arnd Bergmann
In order to move the compat handling for SCSI ioctl commands out of
fs/compat_ioctl.c into the individual drivers, we need a helper function
first to match the native ioctl handler called by sd, sr, st, etc.

Signed-off-by: Arnd Bergmann 
---
 drivers/scsi/scsi_ioctl.c | 54 +--
 include/scsi/scsi_ioctl.h |  1 +
 2 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 57bcd05605bf..8f3af87b6bb0 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -189,17 +189,7 @@ static int scsi_ioctl_get_pci(struct scsi_device *sdev, 
void __user *arg)
 }
 
 
-/**
- * scsi_ioctl - Dispatch ioctl to scsi device
- * @sdev: scsi device receiving ioctl
- * @cmd: which ioctl is it
- * @arg: data associated with ioctl
- *
- * Description: The scsi_ioctl() function differs from most ioctls in that it
- * does not take a major/minor number as the dev field.  Rather, it takes
- * a pointer to a &struct scsi_device.
- */
-int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user 
*arg)
 {
char scsi_cmd[MAX_COMMAND_SIZE];
struct scsi_sense_hdr sense_hdr;
@@ -266,14 +256,50 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void 
__user *arg)
 return scsi_ioctl_get_pci(sdev, arg);
case SG_SCSI_RESET:
return scsi_ioctl_reset(sdev, arg);
-   default:
-   if (sdev->host->hostt->ioctl)
-   return sdev->host->hostt->ioctl(sdev, cmd, arg);
}
+   return -ENOIOCTLCMD;
+}
+
+/**
+ * scsi_ioctl - Dispatch ioctl to scsi device
+ * @sdev: scsi device receiving ioctl
+ * @cmd: which ioctl is it
+ * @arg: data associated with ioctl
+ *
+ * Description: The scsi_ioctl() function differs from most ioctls in that it
+ * does not take a major/minor number as the dev field.  Rather, it takes
+ * a pointer to a &struct scsi_device.
+ */
+int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+   int ret = scsi_ioctl_common(sdev, cmd, arg);
+
+   if (ret != -ENOIOCTLCMD)
+   return ret;
+
+   if (sdev->host->hostt->ioctl)
+   return sdev->host->hostt->ioctl(sdev, cmd, arg);
+
return -EINVAL;
 }
 EXPORT_SYMBOL(scsi_ioctl);
 
+#ifdef CONFIG_COMPAT
+int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+   int ret = scsi_ioctl_common(sdev, cmd, arg);
+
+   if (ret != -ENOIOCTLCMD)
+   return ret;
+
+   if (sdev->host->hostt->compat_ioctl)
+   return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);
+
+   return ret;
+}
+EXPORT_SYMBOL(scsi_compat_ioctl);
+#endif
+
 /*
  * We can process a reset even when a device isn't fully operable.
  */
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index 5101e987c0ef..4fe69d863b5d 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -44,6 +44,7 @@ typedef struct scsi_fctargaddress {
 int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
int cmd, bool ndelay);
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
+extern int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user 
*arg);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 17/27] compat_ioctl: ide: floppy: add handler

2019-12-17 Thread Arnd Bergmann
Rather than relying on fs/compat_ioctl.c, this adds support
for a compat_ioctl() callback in the ide-floppy driver directly,
which lets it translate the scsi commands.

Signed-off-by: Arnd Bergmann 
---
 drivers/ide/ide-floppy.c   |  4 
 drivers/ide/ide-floppy.h   |  2 ++
 drivers/ide/ide-floppy_ioctl.c | 36 ++
 drivers/ide/ide-gd.c   | 14 +
 include/linux/ide.h|  2 ++
 5 files changed, 58 insertions(+)

diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 1ea2f9e82bf8..1fe1f9d37a51 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -546,4 +547,7 @@ const struct ide_disk_ops ide_atapi_disk_ops = {
.set_doorlock   = ide_set_media_lock,
.do_request = ide_floppy_do_request,
.ioctl  = ide_floppy_ioctl,
+#ifdef CONFIG_COMPAT
+   .compat_ioctl   = ide_floppy_compat_ioctl,
+#endif
 };
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h
index 13c9b4b6d75e..8505a5f58f4e 100644
--- a/drivers/ide/ide-floppy.h
+++ b/drivers/ide/ide-floppy.h
@@ -26,6 +26,8 @@ void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc 
*);
 /* ide-floppy_ioctl.c */
 int ide_floppy_ioctl(ide_drive_t *, struct block_device *, fmode_t,
 unsigned int, unsigned long);
+int ide_floppy_compat_ioctl(ide_drive_t *, struct block_device *, fmode_t,
+   unsigned int, unsigned long);
 
 #ifdef CONFIG_IDE_PROC_FS
 /* ide-floppy_proc.c */
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index 40a2ebe34e1d..4fd70f804d6f 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -302,3 +303,38 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct 
block_device *bdev,
mutex_unlock(&ide_floppy_ioctl_mutex);
return err;
 }
+
+#ifdef CONFIG_COMPAT
+int ide_floppy_compat_ioctl(ide_drive_t *drive, struct block_device *bdev,
+   fmode_t mode, unsigned int cmd, unsigned long arg)
+{
+   struct ide_atapi_pc pc;
+   void __user *argp = compat_ptr(arg);
+   int err;
+
+   mutex_lock(&ide_floppy_ioctl_mutex);
+   if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
+   err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
+   goto out;
+   }
+
+   err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp);
+   if (err != -ENOTTY)
+   goto out;
+
+   /*
+* skip SCSI_IOCTL_SEND_COMMAND (deprecated)
+* and CDROM_SEND_PACKET (legacy) ioctls
+*/
+   if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
+   err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
+
+   /*
+* there is no generic_ide_compat_ioctl(), that is handled
+* through compat_blkdev_ioctl().
+*/
+out:
+   mutex_unlock(&ide_floppy_ioctl_mutex);
+   return err;
+}
+#endif
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index dba9ad5c97b3..1b0270efcce2 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -341,11 +341,25 @@ static int ide_gd_ioctl(struct block_device *bdev, 
fmode_t mode,
return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+static int ide_gd_compat_ioctl(struct block_device *bdev, fmode_t mode,
+  unsigned int cmd, unsigned long arg)
+{
+   struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
+   ide_drive_t *drive = idkp->drive;
+
+   return drive->disk_ops->compat_ioctl(drive, bdev, mode, cmd, arg);
+}
+#endif
+
 static const struct block_device_operations ide_gd_ops = {
.owner  = THIS_MODULE,
.open   = ide_gd_unlocked_open,
.release= ide_gd_release,
.ioctl  = ide_gd_ioctl,
+#ifdef CONFIG_COMPAT
+   .ioctl  = ide_gd_compat_ioctl,
+#endif
.getgeo = ide_gd_getgeo,
.check_events   = ide_gd_check_events,
.unlock_native_capacity = ide_gd_unlock_native_capacity,
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 46b771d6999e..06dae6438557 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -413,6 +413,8 @@ struct ide_disk_ops {
  sector_t);
int (*ioctl)(struct ide_drive_s *, struct block_device *,
 fmode_t, unsigned int, unsigned long);
+   int (*compat_ioctl)(struct ide_drive_s *, struct 
block_device *,
+   fmode_t, unsigned int, unsigned long);
 };
 
 /* ATAPI device flags */
-- 
2.20.0

___
Y2038 mailing l

[Y2038] [PATCH v2 26/27] compat_ioctl: simplify up block/ioctl.c

2019-12-17 Thread Arnd Bergmann
Having separate implementations of blkdev_ioctl() often leads to these
getting out of sync, despite the comment at the top.

Since most of the ioctl commands are compatible, and we try very hard
not to add any new incompatible ones, move all the common bits into a
shared function and leave only the ones that are historically different
in separate functions for native/compat mode.

To deal with the compat_ptr() conversion, pass both the integer
argument and the pointer argument into the new blkdev_common_ioctl()
and make sure to always use the correct one of these.

blkdev_ioctl() is now only kept as a separate exported interfact
for drivers/char/raw.c, which lacks a compat_ioctl variant.
We should probably either move raw.c to staging if there are no
more users, or export blkdev_compat_ioctl() as well.

Signed-off-by: Arnd Bergmann 
---
 block/ioctl.c | 269 ++
 1 file changed, 117 insertions(+), 152 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index d6911a1149f5..127194b9f9bd 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -270,65 +270,45 @@ static int blk_ioctl_zeroout(struct block_device *bdev, 
fmode_t mode,
BLKDEV_ZERO_NOUNMAP);
 }
 
-static int put_ushort(unsigned long arg, unsigned short val)
+static int put_ushort(unsigned short __user *argp, unsigned short val)
 {
-   return put_user(val, (unsigned short __user *)arg);
+   return put_user(val, argp);
 }
 
-static int put_int(unsigned long arg, int val)
+static int put_int(int __user *argp, int val)
 {
-   return put_user(val, (int __user *)arg);
+   return put_user(val, argp);
 }
 
-static int put_uint(unsigned long arg, unsigned int val)
+static int put_uint(unsigned int __user *argp, unsigned int val)
 {
-   return put_user(val, (unsigned int __user *)arg);
+   return put_user(val, argp);
 }
 
-static int put_long(unsigned long arg, long val)
+static int put_long(long __user *argp, long val)
 {
-   return put_user(val, (long __user *)arg);
+   return put_user(val, argp);
 }
 
-static int put_ulong(unsigned long arg, unsigned long val)
+static int put_ulong(unsigned long __user *argp, unsigned long val)
 {
-   return put_user(val, (unsigned long __user *)arg);
+   return put_user(val, argp);
 }
 
-static int put_u64(unsigned long arg, u64 val)
+static int put_u64(u64 __user *argp, u64 val)
 {
-   return put_user(val, (u64 __user *)arg);
+   return put_user(val, argp);
 }
 
 #ifdef CONFIG_COMPAT
-static int compat_put_ushort(unsigned long arg, unsigned short val)
+static int compat_put_long(compat_long_t *argp, long val)
 {
-   return put_user(val, (unsigned short __user *)compat_ptr(arg));
+   return put_user(val, argp);
 }
 
-static int compat_put_int(unsigned long arg, int val)
+static int compat_put_ulong(compat_ulong_t *argp, compat_ulong_t val)
 {
-   return put_user(val, (compat_int_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_uint(unsigned long arg, unsigned int val)
-{
-   return put_user(val, (compat_uint_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_long(unsigned long arg, long val)
-{
-   return put_user(val, (compat_long_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
-{
-   return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
-}
-
-static int compat_put_u64(unsigned long arg, u64 val)
-{
-   return put_user(val, (compat_u64 __user *)compat_ptr(arg));
+   return put_user(val, argp);
 }
 #endif
 
@@ -547,9 +527,10 @@ struct compat_hd_geometry {
u32 start;
 };
 
-static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
-   struct compat_hd_geometry __user *ugeo)
+static int compat_hdio_getgeo(struct block_device *bdev,
+ struct compat_hd_geometry __user *ugeo)
 {
+   struct gendisk *disk = bdev->bd_disk;
struct hd_geometry geo;
int ret;
 
@@ -603,13 +584,13 @@ static int blkdev_bszset(struct block_device *bdev, 
fmode_t mode,
 }
 
 /*
- * always keep this in sync with compat_blkdev_ioctl()
+ * Common commands that are handled the same way on native and compat
+ * user space. Note the separate arg/argp parameters that are needed
+ * to deal with the compat_ptr() conversion.
  */
-int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
-   unsigned long arg)
+static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
+   unsigned cmd, unsigned long arg, void __user 
*argp)
 {
-   void __user *argp = (void __user *)arg;
-   loff_t size;
unsigned int max_sectors;
 
switch (cmd) {
@@ -632,60 +613,39 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, 
unsigned cmd,
case BLKFINISHZONE:
return blkdev_zone_mgmt_ioctl(bdev, mode, cmd, arg);
case BLKGETZONESZ:
- 

[Y2038] [PATCH v2 14/27] compat_ioctl: block: handle cdrom compat ioctl in non-cdrom drivers

2019-12-17 Thread Arnd Bergmann
Various block drivers implement the CDROMMULTISESSION,
CDROM_GET_CAPABILITY, and CDROMEJECT ioctl commands, relying on the
block layer to handle compat_ioctl mode for them.

Move this into the drivers directly as a preparation for simplifying
the block layer later.

When only integer arguments or no arguments are passed, the
same handler can be used for .ioctl and .compat_ioctl, and
when only pointer arguments are passed, the newly added
blkdev_compat_ptr_ioctl can be used.

Signed-off-by: Arnd Bergmann 
---
 drivers/block/floppy.c   | 3 +++
 drivers/block/paride/pd.c| 1 +
 drivers/block/paride/pf.c| 1 +
 drivers/block/sunvdc.c   | 1 +
 drivers/block/xen-blkfront.c | 1 +
 5 files changed, 7 insertions(+)

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 485865fd0412..cd3612e4e2e1 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3879,6 +3879,9 @@ static int fd_compat_ioctl(struct block_device *bdev, 
fmode_t mode, unsigned int
 {
int drive = (long)bdev->bd_disk->private_data;
switch (cmd) {
+   case CDROMEJECT: /* CD-ROM eject */
+   case 0x6470: /* SunOS floppy eject */
+
case FDMSGON:
case FDMSGOFF:
case FDSETEMSGTRESH:
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 6f9ad3fc716f..c0967507d085 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -874,6 +874,7 @@ static const struct block_device_operations pd_fops = {
.open   = pd_open,
.release= pd_release,
.ioctl  = pd_ioctl,
+   .compat_ioctl   = pd_ioctl,
.getgeo = pd_getgeo,
.check_events   = pd_check_events,
.revalidate_disk= pd_revalidate
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 6b7d4cab3687..bb09f21ce21a 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -276,6 +276,7 @@ static const struct block_device_operations pf_fops = {
.open   = pf_open,
.release= pf_release,
.ioctl  = pf_ioctl,
+   .compat_ioctl   = pf_ioctl,
.getgeo = pf_getgeo,
.check_events   = pf_check_events,
 };
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 571612e233fe..39aeebc6837d 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -171,6 +171,7 @@ static const struct block_device_operations vdc_fops = {
.owner  = THIS_MODULE,
.getgeo = vdc_getgeo,
.ioctl  = vdc_ioctl,
+   .compat_ioctl   = blkdev_compat_ptr_ioctl,
 };
 
 static void vdc_blk_queue_start(struct vdc_port *port)
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a74d03913822..23c86350a5ab 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2632,6 +2632,7 @@ static const struct block_device_operations 
xlvbd_block_fops =
.release = blkif_release,
.getgeo = blkif_getgeo,
.ioctl = blkif_ioctl,
+   .compat_ioctl = blkdev_compat_ptr_ioctl,
 };
 
 
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 07/27] compat: provide compat_ptr() on all architectures

2019-12-17 Thread Arnd Bergmann
In order to avoid needless #ifdef CONFIG_COMPAT checks,
move the compat_ptr() definition to linux/compat.h
where it can be seen by any file regardless of the
architecture.

Only s390 needs a special definition, this can use the
self-#define trick we have elsewhere.

Signed-off-by: Arnd Bergmann 
---
 arch/arm64/include/asm/compat.h   | 17 -
 arch/mips/include/asm/compat.h| 18 --
 arch/parisc/include/asm/compat.h  | 17 -
 arch/powerpc/include/asm/compat.h | 17 -
 arch/powerpc/oprofile/backtrace.c |  2 +-
 arch/s390/include/asm/compat.h|  6 +-
 arch/sparc/include/asm/compat.h   | 17 -
 arch/x86/include/asm/compat.h | 17 -
 include/linux/compat.h| 18 ++
 9 files changed, 20 insertions(+), 109 deletions(-)

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 7b4172ce497c..935d2aa231bf 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -114,23 +114,6 @@ typedef u32compat_sigset_word;
 
 #define COMPAT_OFF_T_MAX   0x7fff
 
-/*
- * A pointer passed in from user mode. This should not
- * be used for syscall parameters, just declare them
- * as pointers because the syscall entry code will have
- * appropriately converted them already.
- */
-
-static inline void __user *compat_ptr(compat_uptr_t uptr)
-{
-   return (void __user *)(unsigned long)uptr;
-}
-
-static inline compat_uptr_t ptr_to_compat(void __user *uptr)
-{
-   return (u32)(unsigned long)uptr;
-}
-
 #define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
 #define COMPAT_MINSIGSTKSZ 2048
 
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index c99166eadbde..255afcdd79c9 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -100,24 +100,6 @@ typedef u32compat_sigset_word;
 
 #define COMPAT_OFF_T_MAX   0x7fff
 
-/*
- * A pointer passed in from user mode. This should not
- * be used for syscall parameters, just declare them
- * as pointers because the syscall entry code will have
- * appropriately converted them already.
- */
-
-static inline void __user *compat_ptr(compat_uptr_t uptr)
-{
-   /* cast to a __user pointer via "unsigned long" makes sparse happy */
-   return (void __user *)(unsigned long)(long)uptr;
-}
-
-static inline compat_uptr_t ptr_to_compat(void __user *uptr)
-{
-   return (u32)(unsigned long)uptr;
-}
-
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
struct pt_regs *regs = (struct pt_regs *)
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index e03e3c849f40..2f4f66a3bac0 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -173,23 +173,6 @@ struct compat_shmid64_ds {
 #define COMPAT_ELF_NGREG 80
 typedef compat_ulong_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
 
-/*
- * A pointer passed in from user mode. This should not
- * be used for syscall parameters, just declare them
- * as pointers because the syscall entry code will have
- * appropriately converted them already.
- */
-
-static inline void __user *compat_ptr(compat_uptr_t uptr)
-{
-   return (void __user *)(unsigned long)uptr;
-}
-
-static inline compat_uptr_t ptr_to_compat(void __user *uptr)
-{
-   return (u32)(unsigned long)uptr;
-}
-
 static __inline__ void __user *arch_compat_alloc_user_space(long len)
 {
struct pt_regs *regs = ¤t->thread.regs;
diff --git a/arch/powerpc/include/asm/compat.h 
b/arch/powerpc/include/asm/compat.h
index 74d0db511099..3e3cdfaa76c6 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -96,23 +96,6 @@ typedef u32  compat_sigset_word;
 
 #define COMPAT_OFF_T_MAX   0x7fff
 
-/*
- * A pointer passed in from user mode. This should not
- * be used for syscall parameters, just declare them
- * as pointers because the syscall entry code will have
- * appropriately converted them already.
- */
-
-static inline void __user *compat_ptr(compat_uptr_t uptr)
-{
-   return (void __user *)(unsigned long)uptr;
-}
-
-static inline compat_uptr_t ptr_to_compat(void __user *uptr)
-{
-   return (u32)(unsigned long)uptr;
-}
-
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
struct pt_regs *regs = current->thread.regs;
diff --git a/arch/powerpc/oprofile/backtrace.c 
b/arch/powerpc/oprofile/backtrace.c
index 43245f4a9bcb..6ffcb80cf844 100644
--- a/arch/powerpc/oprofile/backtrace.c
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -9,7 +9,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 #define STACK_SP(STACK)*(STACK)
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 63b46e30b2c3..9547cd5d6cdc 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/inclu

[Y2038] [PATCH v2 25/27] compat_ioctl: block: simplify compat_blkpg_ioctl()

2019-12-17 Thread Arnd Bergmann
There is no need to go through a compat_alloc_user_space()
copy any more, just wrap the function in a small helper that
works the same way for native and compat mode.

Signed-off-by: Arnd Bergmann 
---
 block/ioctl.c | 74 ++-
 1 file changed, 38 insertions(+), 36 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index f8c4e2649335..d6911a1149f5 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -12,12 +12,12 @@
 #include 
 #include 
 
-static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg 
__user *arg)
+static int blkpg_do_ioctl(struct block_device *bdev,
+ struct blkpg_partition __user *upart, int op)
 {
struct block_device *bdevp;
struct gendisk *disk;
struct hd_struct *part, *lpart;
-   struct blkpg_ioctl_arg a;
struct blkpg_partition p;
struct disk_part_iter piter;
long long start, length;
@@ -25,9 +25,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct 
blkpg_ioctl_arg __user
 
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
-   if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
-   return -EFAULT;
-   if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+   if (copy_from_user(&p, upart, sizeof(struct blkpg_partition)))
return -EFAULT;
disk = bdev->bd_disk;
if (bdev != bdev->bd_contains)
@@ -35,7 +33,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct 
blkpg_ioctl_arg __user
partno = p.pno;
if (partno <= 0)
return -EINVAL;
-   switch (a.op) {
+   switch (op) {
case BLKPG_ADD_PARTITION:
start = p.start >> 9;
length = p.length >> 9;
@@ -156,6 +154,39 @@ static int blkpg_ioctl(struct block_device *bdev, struct 
blkpg_ioctl_arg __user
}
 }
 
+static int blkpg_ioctl(struct block_device *bdev,
+  struct blkpg_ioctl_arg __user *arg)
+{
+   struct blkpg_partition __user *udata;
+   int op;
+
+   if (get_user(op, &arg->op) || get_user(udata, &arg->data))
+   return -EFAULT;
+
+   return blkpg_do_ioctl(bdev, udata, op);
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_blkpg_ioctl_arg {
+   compat_int_t op;
+   compat_int_t flags;
+   compat_int_t datalen;
+   compat_caddr_t data;
+};
+
+static int compat_blkpg_ioctl(struct block_device *bdev,
+ struct compat_blkpg_ioctl_arg __user *arg)
+{
+   compat_caddr_t udata;
+   int op;
+
+   if (get_user(op, &arg->op) || get_user(udata, &arg->data))
+   return -EFAULT;
+
+   return blkpg_do_ioctl(bdev, compat_ptr(udata), op);
+}
+#endif
+
 static int blkdev_reread_part(struct block_device *bdev)
 {
int ret;
@@ -676,35 +707,6 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, 
unsigned cmd,
 EXPORT_SYMBOL_GPL(blkdev_ioctl);
 
 #ifdef CONFIG_COMPAT
-struct compat_blkpg_ioctl_arg {
-   compat_int_t op;
-   compat_int_t flags;
-   compat_int_t datalen;
-   compat_caddr_t data;
-};
-
-static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
-   unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
-{
-   struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
-   compat_caddr_t udata;
-   compat_int_t n;
-   int err;
-
-   err = get_user(n, &ua32->op);
-   err |= put_user(n, &a->op);
-   err |= get_user(n, &ua32->flags);
-   err |= put_user(n, &a->flags);
-   err |= get_user(n, &ua32->datalen);
-   err |= put_user(n, &a->datalen);
-   err |= get_user(udata, &ua32->data);
-   err |= put_user(compat_ptr(udata), &a->data);
-   if (err)
-   return err;
-
-   return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
-}
-
 #define BLKBSZGET_32   _IOR(0x12, 112, int)
 #define BLKBSZSET_32   _IOW(0x12, 113, int)
 #define BLKGETSIZE64_32_IOR(0x12, 114, int)
@@ -767,7 +769,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
return blkdev_ioctl(bdev, mode, BLKBSZSET,
(unsigned long)compat_ptr(arg));
case BLKPG:
-   return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
+   return compat_blkpg_ioctl(bdev, compat_ptr(arg));
case BLKRAGET:
case BLKFRAGET:
if (!arg)
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 19/27] compat_ioctl: move sys_compat_ioctl() to ioctl.c

2019-12-17 Thread Arnd Bergmann
The rest of the fs/compat_ioctl.c file is no longer useful now,
so move the actual syscall as planned.

Signed-off-by: Arnd Bergmann 
---
 fs/Makefile   |   2 +-
 fs/compat_ioctl.c | 133 --
 fs/ioctl.c|  90 +++
 3 files changed, 91 insertions(+), 134 deletions(-)
 delete mode 100644 fs/compat_ioctl.c

diff --git a/fs/Makefile b/fs/Makefile
index 1148c555c4d3..98be354fdb61 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_FS_DAX)  += dax.o
 obj-$(CONFIG_FS_ENCRYPTION)+= crypto/
 obj-$(CONFIG_FS_VERITY)+= verity/
 obj-$(CONFIG_FILE_LOCKING)  += locks.o
-obj-$(CONFIG_COMPAT)   += compat.o compat_ioctl.o
+obj-$(CONFIG_COMPAT)   += compat.o
 obj-$(CONFIG_BINFMT_AOUT)  += binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)  += binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)  += binfmt_misc.o
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
deleted file mode 100644
index ab4471f469e6..
--- a/fs/compat_ioctl.c
+++ /dev/null
@@ -1,133 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000  Jakub Jelinek  (ja...@redhat.com)
- * Copyright (C) 1998  Eddie C. Dost  (e...@skynet.be)
- * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
- * Copyright (C) 2003   Pavel Machek (pa...@ucw.cz)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "internal.h"
-
-#include 
-#include 
-
-#include 
-
-COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
-  compat_ulong_t, arg32)
-{
-   unsigned long arg = arg32;
-   struct fd f = fdget(fd);
-   int error = -EBADF;
-   if (!f.file)
-   goto out;
-
-   /* RED-PEN how should LSM module know it's handling 32bit? */
-   error = security_file_ioctl(f.file, cmd, arg);
-   if (error)
-   goto out_fput;
-
-   switch (cmd) {
-   /* these are never seen by ->ioctl(), no argument or int argument */
-   case FIOCLEX:
-   case FIONCLEX:
-   case FIFREEZE:
-   case FITHAW:
-   case FICLONE:
-   goto do_ioctl;
-   /* these are never seen by ->ioctl(), pointer argument */
-   case FIONBIO:
-   case FIOASYNC:
-   case FIOQSIZE:
-   case FS_IOC_FIEMAP:
-   case FIGETBSZ:
-   case FICLONERANGE:
-   case FIDEDUPERANGE:
-   goto found_handler;
-   /*
-* The next group is the stuff handled inside file_ioctl().
-* For regular files these never reach ->ioctl(); for
-* devices, sockets, etc. they do and one (FIONREAD) is
-* even accepted in some cases.  In all those cases
-* argument has the same type, so we can handle these
-* here, shunting them towards do_vfs_ioctl().
-* ->compat_ioctl() will never see any of those.
-*/
-   /* pointer argument, never actually handled by ->ioctl() */
-   case FIBMAP:
-   goto found_handler;
-   /* handled by some ->ioctl(); always a pointer to int */
-   case FIONREAD:
-   goto found_handler;
-   /* these get messy on amd64 due to alignment differences */
-#if defined(CONFIG_X86_64)
-   case FS_IOC_RESVSP_32:
-   case FS_IOC_RESVSP64_32:
-   error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
-   goto out_fput;
-   case FS_IOC_UNRESVSP_32:
-   case FS_IOC_UNRESVSP64_32:
-   error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
-   compat_ptr(arg));
-   goto out_fput;
-   case FS_IOC_ZERO_RANGE_32:
-   error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
-   compat_ptr(arg));
-   goto out_fput;
-#else
-   case FS_IOC_RESVSP:
-   case FS_IOC_RESVSP64:
-   case FS_IOC_UNRESVSP:
-   case FS_IOC_UNRESVSP64:
-   case FS_IOC_ZERO_RANGE:
-   goto found_handler;
-#endif
-
-   default:
-   if (f.file->f_op->compat_ioctl) {
-   error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
-   if (error != -ENOIOCTLCMD)
-   goto out_fput;
-   }
-
-   error = -ENOTTY;
-   goto out_fput;
-   }
-
- found_handler:
-   arg = (unsigned long)compat_ptr(arg);
- do_ioctl:
-   error = do_vfs_ioctl(f.file, fd, cmd, arg);
- out_fput:
-   fdput(f);
- out:
-   return error;
-}
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 2f5e4e5b97e1..8f22

[Y2038] [PATCH v2 02/27] compat_ioctl: block: handle BLKREPORTZONE/BLKRESETZONE

2019-12-17 Thread Arnd Bergmann
These were added to blkdev_ioctl() but not blkdev_compat_ioctl,
so add them now.

Cc:  # v4.10+
Fixes: 3ed05a987e0f ("blk-zoned: implement ioctls")
Reviewed-by: Damien Le Moal 
Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 6ca015f92766..830f91e05fe3 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -354,6 +354,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
 * but we call blkdev_ioctl, which gets the lock for us
 */
case BLKRRPART:
+   case BLKREPORTZONE:
+   case BLKRESETZONE:
return blkdev_ioctl(bdev, mode, cmd,
(unsigned long)compat_ptr(arg));
case BLKBSZSET_32:
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 13/27] compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN

2019-12-17 Thread Arnd Bergmann
This is the only ioctl command that does not have a proper
compat handler. Making the normal implementation do the
right thing is actually very simply, so just do that by
using an in_compat_syscall() check to avoid the special
case in the pkcdvd driver.

Signed-off-by: Arnd Bergmann 
---
 drivers/block/pktcdvd.c | 24 +---
 drivers/cdrom/cdrom.c   |  7 ---
 2 files changed, 5 insertions(+), 26 deletions(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ab4d3be4b646..5f970a7d32c0 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2663,26 +2663,6 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t 
mode, unsigned int cmd,
return ret;
 }
 
-#ifdef CONFIG_COMPAT
-static int pkt_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned 
int cmd, unsigned long arg)
-{
-   switch (cmd) {
-   /* compatible */
-   case CDROMEJECT:
-   case CDROMMULTISESSION:
-   case CDROMREADTOCENTRY:
-   case CDROM_SEND_PACKET: /* compat mode handled in scsi_cmd_ioctl */
-   case SCSI_IOCTL_SEND_COMMAND:
-   return pkt_ioctl(bdev, mode, cmd, (unsigned 
long)compat_ptr(arg));
-
-   /* FIXME: no handler so far */
-   default:
-   case CDROM_LAST_WRITTEN:
-   return -ENOIOCTLCMD;
-   }
-}
-#endif
-
 static unsigned int pkt_check_events(struct gendisk *disk,
 unsigned int clearing)
 {
@@ -2704,9 +2684,7 @@ static const struct block_device_operations pktcdvd_ops = 
{
.open = pkt_open,
.release =  pkt_close,
.ioctl =pkt_ioctl,
-#ifdef CONFIG_COMPAT
-   .compat_ioctl = pkt_compat_ioctl,
-#endif
+   .compat_ioctl = blkdev_compat_ptr_ioctl,
.check_events = pkt_check_events,
 };
 
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 48095025e588..faca0f346fff 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3293,9 +3293,10 @@ static noinline int mmc_ioctl_cdrom_last_written(struct 
cdrom_device_info *cdi,
ret = cdrom_get_last_written(cdi, &last);
if (ret)
return ret;
-   if (copy_to_user((long __user *)arg, &last, sizeof(last)))
-   return -EFAULT;
-   return 0;
+   if (in_compat_syscall())
+   return put_user(last, (__s32 __user *)arg);
+
+   return put_user(last, (long __user *)arg);
 }
 
 static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 12/27] compat_ioctl: move CDROMREADADIO to cdrom.c

2019-12-17 Thread Arnd Bergmann
Again, there is only one file that needs this, so move the conversion
handler into the native implementation.

Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c  | 36 
 drivers/cdrom/cdrom.c | 28 +---
 2 files changed, 25 insertions(+), 39 deletions(-)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 578e04f94619..cf136bc2c9fc 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -95,40 +95,6 @@ static int compat_hdio_ioctl(struct block_device *bdev, 
fmode_t mode,
return error;
 }
 
-struct compat_cdrom_read_audio {
-   union cdrom_addraddr;
-   u8  addr_format;
-   compat_int_tnframes;
-   compat_caddr_t  buf;
-};
-
-static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
-   unsigned int cmd, unsigned long arg)
-{
-   struct cdrom_read_audio __user *cdread_audio;
-   struct compat_cdrom_read_audio __user *cdread_audio32;
-   __u32 data;
-   void __user *datap;
-
-   cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
-   cdread_audio32 = compat_ptr(arg);
-
-   if (copy_in_user(&cdread_audio->addr,
-&cdread_audio32->addr,
-(sizeof(*cdread_audio32) -
- sizeof(compat_caddr_t
-   return -EFAULT;
-
-   if (get_user(data, &cdread_audio32->buf))
-   return -EFAULT;
-   datap = compat_ptr(data);
-   if (put_user(datap, &cdread_audio->buf))
-   return -EFAULT;
-
-   return __blkdev_driver_ioctl(bdev, mode, cmd,
-   (unsigned long)cdread_audio);
-}
-
 struct compat_blkpg_ioctl_arg {
compat_int_t op;
compat_int_t flags;
@@ -178,8 +144,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 CDROMREADAUDIO:
-   return compat_cdrom_read_audio(bdev, mode, cmd, arg);
 
/*
 * No handler required for the ones below, we just need to
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index eebdcbef0578..48095025e588 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3017,9 +3017,31 @@ static noinline int mmc_ioctl_cdrom_read_audio(struct 
cdrom_device_info *cdi,
struct cdrom_read_audio ra;
int lba;
 
-   if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg,
-  sizeof(ra)))
-   return -EFAULT;
+#ifdef CONFIG_COMPAT
+   if (in_compat_syscall()) {
+   struct compat_cdrom_read_audio {
+   union cdrom_addraddr;
+   u8  addr_format;
+   compat_int_tnframes;
+   compat_caddr_t  buf;
+   } ra32;
+
+   if (copy_from_user(&ra32, arg, sizeof(ra32)))
+   return -EFAULT;
+
+   ra = (struct cdrom_read_audio) {
+   .addr   = ra32.addr,
+   .addr_format= ra32.addr_format,
+   .nframes= ra32.nframes,
+   .buf= compat_ptr(ra32.buf),
+   };
+   } else
+#endif
+   {
+   if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg,
+  sizeof(ra)))
+   return -EFAULT;
+   }
 
if (ra.addr_format == CDROM_MSF)
lba = msf_to_lba(ra.addr.msf.minute,
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 08/27] compat: scsi: sg: fix v3 compat read/write interface

2019-12-17 Thread Arnd Bergmann
In the v5.4 merge window, a cleanup patch from Al Viro conflicted
with my rework of the compat handling for sg.c read(). Linus Torvalds
did a correct merge but pointed out that the resulting code is still
unsatisfactory.

I later noticed that the sg_new_read() function still gets the compat
mode wrong, when the 'count' argument is large enough to pass a
compat_sg_io_hdr object, but not a nativ sg_io_hdr.

To address both of these, move the definition of compat_sg_io_hdr
into a scsi/sg.h to make it visible to sg.c and rewrite the logic
for reading req_pack_id as well as the size check to a simpler
version that gets the expected results.

Fixes: c35a5cfb4150 ("scsi: sg: sg_read(): simplify reading ->pack_id of 
userland sg_io_hdr_t")
Fixes: 98aaaec4a150 ("compat_ioctl: reimplement SG_IO handling")
Signed-off-by: Arnd Bergmann 
---
 block/scsi_ioctl.c |  29 +--
 drivers/scsi/sg.c  | 126 +
 include/scsi/sg.h  |  30 +++
 3 files changed, 90 insertions(+), 95 deletions(-)

diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 650bade5ea5a..b61dbf4d8443 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct blk_cmd_filter {
unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
@@ -550,34 +551,6 @@ static inline int blk_send_start_stop(struct request_queue 
*q,
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
 }
 
-#ifdef CONFIG_COMPAT
-struct compat_sg_io_hdr {
-   compat_int_t interface_id;  /* [i] 'S' for SCSI generic (required) 
*/
-   compat_int_t dxfer_direction;   /* [i] data transfer direction  */
-   unsigned char cmd_len;  /* [i] SCSI command length ( <= 16 
bytes) */
-   unsigned char mx_sb_len;/* [i] max length to write to sbp */
-   unsigned short iovec_count; /* [i] 0 implies no scatter gather */
-   compat_uint_t dxfer_len;/* [i] byte count of data transfer */
-   compat_uint_t dxferp;   /* [i], [*io] points to data transfer 
memory
-   or scatter gather list */
-   compat_uptr_t cmdp; /* [i], [*i] points to command to 
perform */
-   compat_uptr_t sbp;  /* [i], [*o] points to sense_buffer 
memory */
-   compat_uint_t timeout;  /* [i] MAX_UINT->no timeout (unit: 
millisec) */
-   compat_uint_t flags;/* [i] 0 -> default, see SG_FLAG... */
-   compat_int_t pack_id;   /* [i->o] unused internally (normally) 
*/
-   compat_uptr_t usr_ptr;  /* [i->o] unused internally */
-   unsigned char status;   /* [o] scsi status */
-   unsigned char masked_status;/* [o] shifted, masked scsi status */
-   unsigned char msg_status;   /* [o] messaging level data (optional) 
*/
-   unsigned char sb_len_wr;/* [o] byte count actually written to 
sbp */
-   unsigned short host_status; /* [o] errors from host adapter */
-   unsigned short driver_status;   /* [o] errors from software driver */
-   compat_int_t resid; /* [o] dxfer_len - actual_transferred */
-   compat_uint_t duration; /* [o] time taken by cmd (unit: 
millisec) */
-   compat_uint_t info; /* [o] auxiliary information */
-};
-#endif
-
 int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp)
 {
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 160748ad9c0f..eace8886d95a 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -405,6 +405,38 @@ sg_release(struct inode *inode, struct file *filp)
return 0;
 }
 
+static int get_sg_io_pack_id(int *pack_id, void __user *buf, size_t count)
+{
+   struct sg_header __user *old_hdr = buf;
+   int reply_len;
+
+   if (count >= SZ_SG_HEADER) {
+   /* negative reply_len means v3 format, otherwise v1/v2 */
+   if (get_user(reply_len, &old_hdr->reply_len))
+   return -EFAULT;
+
+   if (reply_len >= 0)
+   return get_user(*pack_id, &old_hdr->pack_id);
+
+   if (in_compat_syscall() &&
+   count >= sizeof(struct compat_sg_io_hdr)) {
+   struct compat_sg_io_hdr __user *hp = buf;
+
+   return get_user(*pack_id, &hp->pack_id);
+   }
+
+   if (count >= sizeof(struct sg_io_hdr)) {
+   struct sg_io_hdr __user *hp = buf;
+
+   return get_user(*pack_id, &hp->pack_id);
+   }
+   }
+
+   /* no valid header was passed, so ignore the pack_id */
+   *pack_id = -1;
+   return 0;
+}
+
 static ssize_t
 sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 {
@@ -413,8 +445,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, 
loff_t * ppos)
Sg_request *srp;
int

[Y2038] [PATCH v2 06/27] compat: ARM64: always include asm-generic/compat.h

2019-12-17 Thread Arnd Bergmann
In order to use compat_* type defininitions in device drivers
outside of CONFIG_COMPAT, move the inclusion of asm-generic/compat.h
ahead of the #ifdef.

All other architectures already do this.

Acked-by: Will Deacon 
Signed-off-by: Arnd Bergmann 
---
 arch/arm64/include/asm/compat.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index b0d53a265f1d..7b4172ce497c 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -4,6 +4,9 @@
  */
 #ifndef __ASM_COMPAT_H
 #define __ASM_COMPAT_H
+
+#include 
+
 #ifdef CONFIG_COMPAT
 
 /*
@@ -13,8 +16,6 @@
 #include 
 #include 
 
-#include 
-
 #define COMPAT_USER_HZ 100
 #ifdef __AARCH64EB__
 #define COMPAT_UTS_MACHINE "armv8b\0\0"
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 03/27] compat_ioctl: block: handle BLKGETZONESZ/BLKGETNRZONES

2019-12-17 Thread Arnd Bergmann
These were added to blkdev_ioctl() in v4.20 but not blkdev_compat_ioctl,
so add them now.

Cc:  # v4.20+
Fixes: 72cd87576d1d ("block: Introduce BLKGETZONESZ ioctl")
Fixes: 65e4e3eee83d ("block: Introduce BLKGETNRZONES ioctl")
Reviewed-by: Damien Le Moal 
Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 830f91e05fe3..f5c1140b8624 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -356,6 +356,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
case BLKRRPART:
case BLKREPORTZONE:
case BLKRESETZONE:
+   case BLKGETZONESZ:
+   case BLKGETNRZONES:
return blkdev_ioctl(bdev, mode, cmd,
(unsigned long)compat_ptr(arg));
case BLKBSZSET_32:
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 10/27] compat_ioctl: ubd, aoe: use blkdev_compat_ptr_ioctl

2019-12-17 Thread Arnd Bergmann
These drivers implement the HDIO_GET_IDENTITY and CDROMVOLREAD ioctl
commands, which are compatible between 32-bit and 64-bit user space and
traditionally handled by compat_blkdev_driver_ioctl().

As a prerequisite to removing that function, make both drivers use
blkdev_compat_ptr_ioctl() as their .compat_ioctl callback.

Signed-off-by: Arnd Bergmann 
---
 arch/um/drivers/ubd_kern.c | 1 +
 drivers/block/aoe/aoeblk.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 6627d7c30f37..582eb5b1f09b 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -113,6 +113,7 @@ static const struct block_device_operations ubd_blops = {
 .open  = ubd_open,
 .release   = ubd_release,
 .ioctl = ubd_ioctl,
+.compat_ioctl  = blkdev_compat_ptr_ioctl,
.getgeo = ubd_getgeo,
 };
 
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index bd19f8af950b..7b32fb673375 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -329,6 +329,7 @@ static const struct block_device_operations aoe_bdops = {
.open = aoeblk_open,
.release = aoeblk_release,
.ioctl = aoeblk_ioctl,
+   .compat_ioctl = blkdev_compat_ptr_ioctl,
.getgeo = aoeblk_getgeo,
.owner = THIS_MODULE,
 };
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 09/27] compat_ioctl: block: add blkdev_compat_ptr_ioctl

2019-12-17 Thread Arnd Bergmann
A lot of block drivers need only a trivial .compat_ioctl callback.

Add a helper function that can be set as the callback pointer
to only convert the argument using the compat_ptr() conversion
and otherwise assume all input and output data is compatible,
or handled using in_compat_syscall() checks.

This mirrors the compat_ptr_ioctl() helper function used in
character devices.

Signed-off-by: Arnd Bergmann 
---
 block/ioctl.c  | 21 +
 include/linux/blkdev.h |  7 +++
 2 files changed, 28 insertions(+)

diff --git a/block/ioctl.c b/block/ioctl.c
index 5de98b97af2a..e728331d1a5b 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -285,6 +286,26 @@ int __blkdev_driver_ioctl(struct block_device *bdev, 
fmode_t mode,
  */
 EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
 
+#ifdef CONFIG_COMPAT
+/*
+ * This is the equivalent of compat_ptr_ioctl(), to be used by block
+ * drivers that implement only commands that are completely compatible
+ * between 32-bit and 64-bit user space
+ */
+int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode,
+   unsigned cmd, unsigned long arg)
+{
+   struct gendisk *disk = bdev->bd_disk;
+
+   if (disk->fops->ioctl)
+   return disk->fops->ioctl(bdev, mode, cmd,
+(unsigned long)compat_ptr(arg));
+
+   return -ENOIOCTLCMD;
+}
+EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
+#endif
+
 static int blkdev_pr_register(struct block_device *bdev,
struct pr_registration __user *arg)
 {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 47eb22a3b7f9..3e0408618da7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1711,6 +1711,13 @@ struct block_device_operations {
const struct pr_ops *pr_ops;
 };
 
+#ifdef CONFIG_COMPAT
+extern int blkdev_compat_ptr_ioctl(struct block_device *, fmode_t,
+ unsigned int, unsigned long);
+#else
+#define blkdev_compat_ptr_ioctl NULL
+#endif
+
 extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int,
 unsigned long);
 extern int bdev_read_page(struct block_device *, sector_t, struct page *);
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 05/27] compat_ioctl: block: handle Persistent Reservations

2019-12-17 Thread Arnd Bergmann
These were added to blkdev_ioctl() in linux-5.5 but not
blkdev_compat_ioctl, so add them now.

Cc:  # v4.4+
Fixes: bbd3e064362e ("block: add an API for Persistent Reservations")
Signed-off-by: Arnd Bergmann 
---
 block/compat_ioctl.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 5b13e344229c..f16ae92065d7 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -408,6 +408,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
case BLKTRACETEARDOWN: /* compatible */
ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
return ret;
+   case IOC_PR_REGISTER:
+   case IOC_PR_RESERVE:
+   case IOC_PR_RELEASE:
+   case IOC_PR_PREEMPT:
+   case IOC_PR_PREEMPT_ABORT:
+   case IOC_PR_CLEAR:
+   return blkdev_ioctl(bdev, mode, cmd,
+   (unsigned long)compat_ptr(arg));
default:
if (disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [PATCH v2 01/27] pktcdvd: fix regression on 64-bit architectures

2019-12-17 Thread Arnd Bergmann
The support for the compat ioctl did not actually do what it was
supposed to do because of a typo, instead it broke native support for
CDROM_LAST_WRITTEN and CDROM_SEND_PACKET on all architectures with
CONFIG_COMPAT enabled.

Fixes: 1b114b0817cc ("pktcdvd: add compat_ioctl handler")
Signed-off-by: Arnd Bergmann 

Please apply for v5.5, I just noticed the regression while
rebasing some of the patches I created on top.
---
 drivers/block/pktcdvd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ee67bf929fac..861fc65a1b75 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2707,7 +2707,7 @@ static const struct block_device_operations pktcdvd_ops = 
{
.release =  pkt_close,
.ioctl =pkt_ioctl,
 #ifdef CONFIG_COMPAT
-   .ioctl =pkt_compat_ioctl,
+   .compat_ioctl = pkt_compat_ioctl,
 #endif
.check_events = pkt_check_events,
 };
-- 
2.20.0

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [GIT PULL v2 00/27] block, scsi: final compat_ioctl cleanup

2019-12-17 Thread Arnd Bergmann
The following changes since commit e42617b825f8073569da76dc4510bfa019b1c35a:

  Linux 5.5-rc1 (2019-12-08 14:57:55 -0800)

are available in the Git repository at:

  git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground.git 
tags/block-ioctl-cleanup-5.6

for you to fetch changes up to 3462d5c19dac7c062c5a2db727775116e6d2b28e:

  Documentation: document ioctl interfaces better (2019-12-17 22:45:18 +0100)


block, scsi: final compat_ioctl cleanup

This series concludes the work I did for linux-5.5 on the compat_ioctl()
cleanup, killing off fs/compat_ioctl.c and block/compat_ioctl.c by moving
everything into drivers.

Overall this would be a reduction both in complexity and line count, but
as I'm also adding documentation the overall number of lines increases
in the end.

My plan was originally to keep the SCSI and block parts separate.
This did not work easily because of interdependencies: I cannot
do the final SCSI cleanup in a good way without first addressing the
CDROM ioctls, so this is one series that I hope could be merged through
either the block or the scsi git trees, or possibly both if you can
pull in the same branch.

The series comes in these steps:

1. clean up the sg v3 interface as suggested by Linus. I have
   talked about this with Doug Gilbert as well, and he would
   rebase his sg v4 patches on top of "compat: scsi: sg: fix v3
   compat read/write interface"

2. Actually moving handlers out of block/compat_ioctl.c and
   block/scsi_ioctl.c into drivers, mixed in with cleanup
   patches

3. Document how to do this right. I keep getting asked about this,
   and it helps to point to some documentation file.

The branch is based on another one that fixes a couple of bugs found
during the creation of this series.

Changes since the original version [1]:

- move out the bugfixes into a branch for itself
- clean up scsi sg driver further as suggested by Christoph Hellwig
- avoid some ifdefs by moving compat_ptr() out of asm/compat.h
- split out the blkdev_compat_ptr_ioctl function; bug spotted by
  Ben Hutchings
- Improve formatting of documentation

[1] 
https://lore.kernel.org/linux-block/20191211204306.1207817-1-a...@arndb.de/T/#m9f89df30565fc66abbded5d01f4db553b16f129f



Arnd Bergmann (22): (plus five from the first pull request)
  compat: ARM64: always include asm-generic/compat.h
  compat: provide compat_ptr() on all architectures
  compat: scsi: sg: fix v3 compat read/write interface
  compat_ioctl: block: add blkdev_compat_ptr_ioctl
  compat_ioctl: ubd, aoe: use blkdev_compat_ptr_ioctl
  compat_ioctl: move CDROM_SEND_PACKET handling into scsi
  compat_ioctl: move CDROMREADADIO to cdrom.c
  compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN
  compat_ioctl: block: handle cdrom compat ioctl in non-cdrom drivers
  compat_ioctl: add scsi_compat_ioctl
  compat_ioctl: bsg: add handler
  compat_ioctl: ide: floppy: add handler
  compat_ioctl: scsi: move ioctl handling into drivers
  compat_ioctl: move sys_compat_ioctl() to ioctl.c
  compat_ioctl: simplify the implementation
  compat_ioctl: move cdrom commands into cdrom.c
  compat_ioctl: scsi: handle HDIO commands from drivers
  compat_ioctl: move HDIO ioctl handling into drivers/ide
  compat_ioctl: block: move blkdev_compat_ioctl() into ioctl.c
  compat_ioctl: block: simplify compat_blkpg_ioctl()
  compat_ioctl: simplify up block/ioctl.c
  Documentation: document ioctl interfaces better

 Documentation/core-api/index.rst   |   1 +
 Documentation/core-api/ioctl.rst   | 248 +++
 arch/arm64/include/asm/compat.h|  22 +-
 arch/mips/include/asm/compat.h |  18 --
 arch/parisc/include/asm/compat.h   |  17 -
 arch/powerpc/include/asm/compat.h  |  17 -
 arch/powerpc/oprofile/backtrace.c  |   2 +-
 arch/s390/include/asm/compat.h |   6 +-
 arch/sparc/include/asm/compat.h|  17 -
 arch/um/drivers/ubd_kern.c |   1 +
 arch/x86/include/asm/compat.h  |  17 -
 block/Makefile |   1 -
 block/bsg.c|   1 +
 block/compat_ioctl.c   | 411 -
 block/ioctl.c  | 319 +++
 block/scsi_ioctl.c | 214 -
 drivers/ata/libata-scsi.c  |   9 +
 drivers/block/aoe/aoeblk.c |   1 +
 drivers/block/floppy.c |   3 +
 drivers/block/paride/pcd.c |   3 +
 drivers/block/paride/pd.c  |   1 +
 drivers/block/paride/pf.c  |   1 +
 drivers/block/pktcdvd.c|  26 +-
 drivers/block/sunvdc.c |   1 +
 drivers/block/virtio_blk.c |   3 +
 drivers/block/xen-blkfront.c   |   1 +
 drivers/cdrom/cdrom.c  |  35 ++-
 drivers/cdrom/gdrom.c  |   3 +
 drivers/ide/ide-cd.c   

Re: [Y2038] [PATCH 10/24] compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN

2019-12-17 Thread Arnd Bergmann
On Tue, Dec 17, 2019 at 4:20 PM Ben Hutchings
 wrote:
>
> On Wed, 2019-12-11 at 21:42 +0100, Arnd Bergmann wrote:
> > This is the only ioctl command that does not have a proper
> > compat handler. Making the normal implementation do the
> > right thing is actually very simply, so just do that by
> > using an in_compat_syscall() check to avoid the special
> > case in the pkcdvd driver.
> [...]
>
> Since this uses blkdev_compat_ptr_ioctl() it needs to be moved after
> the following patch.
>

Ah right, I obviously reshuffled my patches too much to end up
with the most reasonable order and avoid introducing something
that would be removed again later.

I'll split out the addition of blkdev_compat_ptr_ioctl() into a separate
patch and move that all in front, as I'm no longer sure if there
was another dependency in the other way.

Thanks!

Arnd
___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [GIT PULL, v8] Fix year 2038 issue for sound subsystem

2019-12-17 Thread Arnd Bergmann
The following changes since commit e42617b825f8073569da76dc4510bfa019b1c35a:

  Linux 5.5-rc1 (2019-12-08 14:57:55 -0800)

are available in the Git repository at:

  git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground.git
tags/y2038-alsa-v8-signed

for you to fetch changes up to 1cfaef9617033f38eba9cc725809ed32bcdb3dc5:

  ALSA: bump uapi version numbers (2019-12-13 11:25:58 +0100)


ALSA: Fix year 2038 issue for sound subsystem

This is a series I worked on with Baolin in 2017 and 2018, but we
never quite managed to finish up the last pieces. During the
ALSA developer meetup at ELC-E 2018 in Edinburgh, a decision was
made to go with this approach for keeping best compatibility
with existing source code, and then I failed to follow up by
resending the patches.

Now I have patches for all remaining time_t uses in the kernel,
so it's absolutely time to revisit them. I have done more
review of the patches myself and found a couple of minor issues
that I have fixed up, otherwise the series is still the same as
before.

Conceptually, the idea of these patches is:

- 64-bit applications should see no changes at all, neither
  compile-time nor run-time.

- 32-bit code compiled with a 64-bit time_t currently
  does not work with ALSA, and requires kernel changes and/or
  sound/asound.h changes

- Most 32-bit code using these interfaces will work correctly
  on a modified kernel, with or without the uapi header changes.

- 32-bit code using SNDRV_TIMER_IOCTL_TREAD requires the
  updated header file for 64-bit time_t support

- 32-bit i386 user space with 64-bit time_t is broken for
  SNDRV_PCM_IOCTL_STATUS, SNDRV_RAWMIDI_IOCTL_STATUS and
  SNDRV_PCM_IOCTL_SYNC_PTR because of i386 alignment. This is also
  addressed by the updated uapi header.

- PCM mmap is currently supported on native x86 kernels
  (both 32-bit and 64-bit) but not for compat mode. This series breaks
  the 32-bit native mmap support for 32-bit time_t, but instead allows
  it for 64-bit time_t on both native and compat kernels. This seems to
  be the best trade-off, as mmap support is optional already, and most
  32-bit code runs in compat mode anyway.

- I've tried to avoid breaking compilation of 32-bit code
  as much as possible. Anything that does break however is likely code
  that is already broken on 64-bit time_t and needs source changes to
  fix them.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git
y2038-alsa-v8
[2] 
https://lore.kernel.org/lkml/cak8p3a2os66+iwqyf97qh05w2jp8rmwao8zmkohixqvhvyy...@mail.gmail.com/T/#m6519cb07cfda08adf1dedea6596bb98892b4d5dc

Signed-off-by: Arnd Bergmann 

Changes since v7: (Arnd):
 - Fix a typo found by Ben Hutchings

Changes since v6: (Arnd):
 - Add a patch to update the API versions
 - Hide a timespec reference in #ifndef __KERNEL__ to remove the
   last reference to time_t
 - Use a more readable way to do padding and describe it in the
   changelog
 - Rebase to linux-5.5-rc1, changing include/sound/soc-component.h
   and sound/drivers/aloop.c as needed.

Changes since v5 (Arnd):
 - Rebased to linux-5.4-rc4
 - Updated to completely remove timespec and time_t references from alsa
 - found and fixed a few bugs

Changes since v4 (Baolin):
 - Add patch 5 to change trigger_tstamp member of struct snd_pcm_runtime.
 - Add patch 8 to change internal timespec.
 - Add more explanation in commit message.
 - Use ktime_get_real_ts64() in patch 6.
 - Split common code out into a separate function in patch 6.
 - Fix tu->tread bug in patch 6 and remove #if __BITS_PER_LONG == 64 macro.

Changes since v3:
 - Move struct snd_pcm_status32 to pcm.h file.
 - Modify comments and commit message.
 - Add new patch2 ~ patch6.

Changes since v2:
 - Renamed all structures to make clear.
 - Remove CONFIG_X86_X32 macro and introduced new
compat_snd_pcm_status64_x86_32.

Changes since v1:
 - Add one macro for struct snd_pcm_status_32 which only active in
32bits kernel.
 - Convert pcm_compat.c to use struct snd_pcm_status_64.
 - Convert pcm_native.c to use struct snd_pcm_status_64.


Arnd Bergmann (3):
  ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c
  ALSA: add new 32-bit layout for snd_pcm_mmap_status/control
  ALSA: bump uapi version numbers

Baolin Wang (6):
  ALSA: Replace timespec with timespec64
  ALSA: Avoid using timespec for struct snd_timer_status
  ALSA: Avoid using timespec for struct snd_ctl_elem_value
  ALSA: Avoid using timespec for struct snd_pcm_status
  ALSA: Avoid using timespec for struct snd_rawmidi_status
  ALSA: Avoid using timespec for struct snd_timer_tread

 include/sound/pcm.h   |  74 +
 include/sound/soc-component.h |   4 +-
 include/sound/timer.h |   4 +-
 include/uapi/sound/asound.h   | 145
-
 sound/core/pcm.c

Re: [Y2038] [PATCH v7 0/8] Fix year 2038 issue for sound subsystem

2019-12-17 Thread Arnd Bergmann
On Tue, Dec 17, 2019 at 11:42 AM Takashi Iwai  wrote:
> On Wed, 11 Dec 2019 22:20:16 +0100,
> Arnd Bergmann wrote:

> >
> > I hope I addressed all review comments by now, so please pull this
> > for linux-5.6.
> >
> > A git branch with the same contents is available for testing at [1].
> >
> >  Arnd
>
> I see no issue other than the timer API patch Ben pointed.
>
> Could you resubmit that patch?  Or just submit the whole as v8, I
> don't mind either way.  Then we'll get this done for 5.6.

Can you take this as a pull request? That would be ideal for me,
as I can then use it as a parent for a shared branch with additional
cleanups on top (removing time_t etc) in linux-next. It also provides
a nice place to preserve the series cover letter.

I'm sending you the pull request now, and the last modified patch,
in case you prefer the patch over a git tag.

Thanks,

Arnd
___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


Re: [Y2038] [PATCH 10/24] compat_ioctl: cdrom: handle CDROM_LAST_WRITTEN

2019-12-17 Thread Ben Hutchings
On Wed, 2019-12-11 at 21:42 +0100, Arnd Bergmann wrote:
> This is the only ioctl command that does not have a proper
> compat handler. Making the normal implementation do the
> right thing is actually very simply, so just do that by
> using an in_compat_syscall() check to avoid the special
> case in the pkcdvd driver.
[...]

Since this uses blkdev_compat_ptr_ioctl() it needs to be moved after
the following patch.

Ben.

-- 
Ben Hutchings, Software Developer Codethink Ltd
https://www.codethink.co.uk/ Dale House, 35 Dale Street
 Manchester, M1 2HF, United Kingdom

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


Re: [Y2038] [PATCH v2 20/24] xfs: disallow broken ioctls without compat-32-bit-time

2019-12-17 Thread Arnd Bergmann
On Mon, Dec 16, 2019 at 5:52 PM Darrick J. Wong  wrote:
> On Mon, Dec 16, 2019 at 05:45:29PM +0100, Arnd Bergmann wrote:
> > On Fri, Dec 13, 2019 at 10:05 PM Darrick J. Wong  
> > wrote:
> > What is the timeline for that work now? I'm mainly interested in
> > getting the removal of 'time_t/timeval/timespec' and 'get_seconds()'
> > from the kernel done for v5.6, but it would be good to also have
> > this patch and the extended timestamps in the same version
> > just so we can claim that "all known y2038 issues" are addressed
> > in that release (I'm sure we will run into bugs we don't know yet).
>
> Personally, I think you should push this whenever it's ready.  Are you
> aiming to send all 24 patches as a treewide pull request directly to
> Linus, or would you rather the 2-3 xfs patches go through the xfs tree?

My plan is get as much of the remaining 60 patches into maintainer
trees for v5.6 and then send a pull request for whatever remains that
has not been picked up by anyone.

The 24 patches are the ones that didn't seem worth splitting into a
separate series, aside from these I also have v4l2, alsa and nfsd
pending, plus a final cleanup that removes the then-unused
interfaces.

So if you can pick up the xfs patches, that would help me.

> The y2038 format changes are going to take a while to push through
> review.  If somehow it all gets through review for 5.6 I can always
> apply both and fix the merge damage, but more likely y2038 timestamps is
> a  5.8 EXPERIMENTAL thing.
>
> Or later, given that Dave and I both have years worth of unreviewed
> patch backlog. :(

Ok, I see.

Arnd
___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


Re: [Y2038] [PATCH v2 21/24] xfs: quota: move to time64_t interfaces

2019-12-17 Thread Arnd Bergmann
On Mon, Dec 16, 2019 at 5:52 PM Arnd Bergmann  wrote:
> On Fri, Dec 13, 2019 at 10:17 PM Darrick J. Wong  
> wrote:
>>
>> Hmm, so one thing that I clean up on the way to bigtime is the total
>> lack of clamping here.  If (for example) it's September 2105 and
>> rtbtimelimit is set to 1 year, this will cause an integer overflow.  The
>> quota timer will be set to 1970 and expire immediately, rather than what
>> I'd consider the best effort of February 2106.

One more hing to note (I will add this to the changelog text) is that on
32-bit architectures, the limit here is y2038, while on 64-bit
architectures it's y2106:

int xfs_trans_dqresv(...)
{
   time_t  timer; /* signed 'long' */
   timer = be32_to_cpu(dqp->q_core.d_btimer);
   /* get_seconds() returns unsigned long */
  if ((timer != 0 && get_seconds() > timer))
return -EDQUOT;
}

> I don't think clamping would be good here, that just replaces
> one bug with another at the overflow time. If you would like to
> have something better before this gets extended, I could try to
> come up with a version that converts it to the nearest 64-bit
> timestamp, similar to the way that time_before32() in the kernel
> or the NTP protocol work.
>
> If you think it can get extended properly soon, I'd just leave the
> patch as it is today in order to remove the get_seconds()
> interface for v5.6.

I've tried this now, and but this feels wrong: it adds lots of complexity
for corner cases and is still fragile, e.g. when the time is wrong
during boot before ntp runs. See that patch below for reference.

I also see that quotatool on xfs always uses the old xfs quota
interface, so it already overflows on the user space side. Fixing
this properly seems to be a bigger effort than I was planning for
(on an unpatched 64-bit kernel):

$ sudo quotatool -b-u  -t 220month  /mnt/tmp -r
$ rm file ; fallocate -l 11M file
$ sudo quotatool -d /mnt/tmp -u arnd
1000 /mnt/tmp 11264 10240 20480 570239975 2 0 00
$ sudo quotatool -b-u  -t 222month  /mnt/tmp -r
$ rm file ; fallocate -l 11M file
$ sudo quotatool -d /mnt/tmp -u arnd
1000 /mnt/tmp 11264 10240 20480 18446744069990008316 2 0 00

   Arnd

diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 9cfd3209f52b..6c9128bb607b 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -98,6 +98,23 @@ xfs_qm_adjust_dqlimits(
xfs_dquot_set_prealloc_limits(dq);
 }

+static __be32 xfs_quota_timeout32(s64 limit)
+{
+   time64_t now = ktime_get_real_seconds();
+   u32 timeout;
+
+   /* avoid overflows in out-of-range limits */
+   if ((u64)limit > S32_MAX)
+   limit = S32_MAX;
+   timeout = now + limit;
+
+   /* avoid timeout of zero */
+   if (lower_32_bits(timeout) == 0)
+   return cpu_to_be32(1);
+
+   return cpu_to_be32(lower_32_bits(timeout));
+}
+
 /*
  * Check the limits and timers of a dquot and start or reset timers
  * if necessary.
@@ -137,7 +154,7 @@ xfs_qm_adjust_dqtimers(
(d->d_blk_hardlimit &&
 (be64_to_cpu(d->d_bcount) >
  be64_to_cpu(d->d_blk_hardlimit {
-   d->d_btimer = cpu_to_be32(ktime_get_real_seconds() +
+   d->d_btimer = xfs_quota_timeout32(
mp->m_quotainfo->qi_btimelimit);
} else {
d->d_bwarns = 0;
@@ -160,7 +177,7 @@ xfs_qm_adjust_dqtimers(
(d->d_ino_hardlimit &&
 (be64_to_cpu(d->d_icount) >
  be64_to_cpu(d->d_ino_hardlimit {
-   d->d_itimer = cpu_to_be32(ktime_get_real_seconds() +
+   d->d_itimer = xfs_quota_timeout32(
mp->m_quotainfo->qi_itimelimit);
} else {
d->d_iwarns = 0;
@@ -183,7 +200,7 @@ xfs_qm_adjust_dqtimers(
(d->d_rtb_hardlimit &&
 (be64_to_cpu(d->d_rtbcount) >
  be64_to_cpu(d->d_rtb_hardlimit {
-   d->d_rtbtimer = cpu_to_be32(ktime_get_real_seconds() +
+   d->d_rtbtimer = xfs_quota_timeout32(
mp->m_quotainfo->qi_rtbtimelimit);
} else {
d->d_rtbwarns = 0;
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 1ea82764bf89..2087626b4bee 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -601,6 +601,14 @@ xfs_qm_scall_setqlim(
return error;
 }

+/* Assume timers are within +/- 68 years of current wall clock */
+static time64_t xfs_quota_time32_to_time64(time64_t now, __be32 timer)
+{
+   s32 diff = be32_to_cpu(timer) - lower_32_bits(now);
+
+   return now + diff;
+}
+
 /* Fill out the quota context. */
 static void
 xfs_qm_scall_getquota_fill_qc(
@@ -609,6 +617,8 @@ xfs_qm_scall_getqu

Re: [Y2038] [PATCH v7 0/8] Fix year 2038 issue for sound subsystem

2019-12-17 Thread Takashi Iwai
On Wed, 11 Dec 2019 22:20:16 +0100,
Arnd Bergmann wrote:
> 
> This is a series I worked on with Baolin in 2017 and 2018, but we
> never quite managed to finish up the last pieces. During the
> ALSA developer meetup at ELC-E 2018 in Edinburgh, a decision was
> made to go with this approach for keeping best compatibility
> with existing source code, and then I failed to follow up by
> resending the patches.
> 
> Now I have patches for all remaining time_t uses in the kernel,
> so it's absolutely time to revisit them. I have done more
> review of the patches myself and found a couple of minor issues
> that I have fixed up, otherwise the series is still the same as
> before.
> 
> Conceptually, the idea of these patches is:
> 
> - 64-bit applications should see no changes at all, neither
>   compile-time nor run-time.
> 
> - 32-bit code compiled with a 64-bit time_t currently
>   does not work with ALSA, and requires kernel changes and/or
>   sound/asound.h changes
> 
> - Most 32-bit code using these interfaces will work correctly
>   on a modified kernel, with or without the uapi header changes.
> 
> - 32-bit code using SNDRV_TIMER_IOCTL_TREAD requires the
>   updated header file for 64-bit time_t support
> 
> - 32-bit i386 user space with 64-bit time_t is broken for
>   SNDRV_PCM_IOCTL_STATUS, SNDRV_RAWMIDI_IOCTL_STATUS and
>   SNDRV_PCM_IOCTL_SYNC_PTR because of i386 alignment. This is also
>   addressed by the updated uapi header.
> 
> - PCM mmap is currently supported on native x86 kernels
>   (both 32-bit and 64-bit) but not for compat mode. This series breaks
>   the 32-bit native mmap support for 32-bit time_t, but instead allows
>   it for 64-bit time_t on both native and compat kernels. This seems to
>   be the best trade-off, as mmap support is optional already, and most
>   32-bit code runs in compat mode anyway.
> 
> - I've tried to avoid breaking compilation of 32-bit code
>   as much as possible. Anything that does break however is likely code
>   that is already broken on 64-bit time_t and needs source changes to
>   fix them.
> 
> I hope I addressed all review comments by now, so please pull this
> for linux-5.6.
> 
> A git branch with the same contents is available for testing at [1].
> 
>  Arnd

I see no issue other than the timer API patch Ben pointed.

Could you resubmit that patch?  Or just submit the whole as v8, I
don't mind either way.  Then we'll get this done for 5.6.


Thanks!

Takashi


> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git 
> y2038-alsa-v7
> [2] 
> https://lore.kernel.org/lkml/cak8p3a2os66+iwqyf97qh05w2jp8rmwao8zmkohixqvhvyy...@mail.gmail.com/T/#m6519cb07cfda08adf1dedea6596bb98892b4d5dc
> 
> Changes since v6: (Arnd):
>  - Add a patch to update the API versions
>  - Hide a timespec reference in #ifndef __KERNEL__ to remove the
>last reference to time_t
>  - Use a more readable way to do padding and describe it in the
>changelog
>  - Rebase to linux-5.5-rc1, changing include/sound/soc-component.h
>
>and sound/drivers/aloop.c as needed.
> 
> Changes since v5 (Arnd):
>  - Rebased to linux-5.4-rc4
>  - Updated to completely remove timespec and time_t references from alsa
>  - found and fixed a few bugs
> 
> Changes since v4 (Baolin):
>  - Add patch 5 to change trigger_tstamp member of struct snd_pcm_runtime.
>  - Add patch 8 to change internal timespec.
>  - Add more explanation in commit message.
>  - Use ktime_get_real_ts64() in patch 6.
>  - Split common code out into a separate function in patch 6.
>  - Fix tu->tread bug in patch 6 and remove #if __BITS_PER_LONG == 64 macro.
> 
> Changes since v3:
>  - Move struct snd_pcm_status32 to pcm.h file.
>  - Modify comments and commit message.
>  - Add new patch2 ~ patch6.
> 
> Changes since v2:
>  - Renamed all structures to make clear.
>  - Remove CONFIG_X86_X32 macro and introduced new 
> compat_snd_pcm_status64_x86_32.
> 
> Changes since v1:
>  - Add one macro for struct snd_pcm_status_32 which only active in 32bits 
> kernel.
>  - Convert pcm_compat.c to use struct snd_pcm_status_64.
>  - Convert pcm_native.c to use struct snd_pcm_status_64.
> ---
> 
> Arnd Bergmann (3):
>   ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c
>   ALSA: add new 32-bit layout for snd_pcm_mmap_status/control
>   ALSA: bump uapi version numbers
> 
> Baolin Wang (6):
>   ALSA: Replace timespec with timespec64
>   ALSA: Avoid using timespec for struct snd_timer_status
>   ALSA: Avoid using timespec for struct snd_ctl_elem_value
>   ALSA: Avoid using timespec for struct snd_pcm_status
>   ALSA: Avoid using timespec for struct snd_rawmidi_status
>   ALSA: Avoid using timespec for struct snd_timer_tread
> 
>  include/sound/pcm.h   |  74 ++--
>  include/sound/soc-component.h |   4 +-
>  include/sound/timer.h |   4 +-
>  include/uapi/sound/asound.h   | 145 +--
>  sound/core/pcm.c  |  12 +-
>  sound/core/pcm_compat.c