Commit 07705421 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Martin K. Petersen
Browse files

scsi: aacraid: Improve compat_ioctl handlers

The use of compat_alloc_user_space() can be easily replaced by handling
compat arguments in the regular handler, and this will make it work for
big-endian kernels as well, which at the moment get an invalid indirect
pointer argument.

Calling aac_ioctl() instead of aac_compat_do_ioctl() means the compat and
native code paths behave the same way again, which they stopped when the
adapter health check was added only in the native function.

Link: https://lore.kernel.org/r/20201030164450.1253641-1-arnd@kernel.org


Fixes: 572ee53a ("scsi: aacraid: check adapter health")
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 20307458
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/compat.h>
#include <linux/delay.h> /* ssleep prototype */
#include <linux/kthread.h>
#include <linux/uaccess.h>
@@ -226,6 +227,12 @@ static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)
	return status;
}

struct compat_fib_ioctl {
	u32	fibctx;
	s32	wait;
	compat_uptr_t fib;
};

/**
 *	next_getadapter_fib	-	get the next fib
 *	@dev: adapter to use
@@ -243,8 +250,19 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
	struct list_head * entry;
	unsigned long flags;

	if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
	if (in_compat_syscall()) {
		struct compat_fib_ioctl cf;

		if (copy_from_user(&cf, arg, sizeof(struct compat_fib_ioctl)))
			return -EFAULT;

		f.fibctx = cf.fibctx;
		f.wait = cf.wait;
		f.fib = compat_ptr(cf.fib);
	} else {
		if (copy_from_user(&f, arg, sizeof(struct fib_ioctl)))
			return -EFAULT;
	}
	/*
	 *	Verify that the HANDLE passed in was a valid AdapterFibContext
	 *
+2 −59
Original line number Diff line number Diff line
@@ -1182,63 +1182,6 @@ static long aac_cfg_ioctl(struct file *file,
	return aac_do_ioctl(aac, cmd, (void __user *)arg);
}

#ifdef CONFIG_COMPAT
static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
{
	long ret;
	switch (cmd) {
	case FSACTL_MINIPORT_REV_CHECK:
	case FSACTL_SENDFIB:
	case FSACTL_OPEN_GET_ADAPTER_FIB:
	case FSACTL_CLOSE_GET_ADAPTER_FIB:
	case FSACTL_SEND_RAW_SRB:
	case FSACTL_GET_PCI_INFO:
	case FSACTL_QUERY_DISK:
	case FSACTL_DELETE_DISK:
	case FSACTL_FORCE_DELETE_DISK:
	case FSACTL_GET_CONTAINERS:
	case FSACTL_SEND_LARGE_FIB:
		ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
		break;

	case FSACTL_GET_NEXT_ADAPTER_FIB: {
		struct fib_ioctl __user *f;

		f = compat_alloc_user_space(sizeof(*f));
		ret = 0;
		if (clear_user(f, sizeof(*f)))
			ret = -EFAULT;
		if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
			ret = -EFAULT;
		if (!ret)
			ret = aac_do_ioctl(dev, cmd, f);
		break;
	}

	default:
		ret = -ENOIOCTLCMD;
		break;
	}
	return ret;
}

static int aac_compat_ioctl(struct scsi_device *sdev, unsigned int cmd,
			    void __user *arg)
{
	struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
	if (!capable(CAP_SYS_RAWIO))
		return -EPERM;
	return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
}

static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
	if (!capable(CAP_SYS_RAWIO))
		return -EPERM;
	return aac_compat_do_ioctl(file->private_data, cmd, arg);
}
#endif

static ssize_t aac_show_model(struct device *device,
			      struct device_attribute *attr, char *buf)
{
@@ -1523,7 +1466,7 @@ static const struct file_operations aac_cfg_fops = {
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= aac_cfg_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl   = aac_compat_cfg_ioctl,
	.compat_ioctl   = aac_cfg_ioctl,
#endif
	.open		= aac_cfg_open,
	.llseek		= noop_llseek,
@@ -1536,7 +1479,7 @@ static struct scsi_host_template aac_driver_template = {
	.info				= aac_info,
	.ioctl				= aac_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl			= aac_compat_ioctl,
	.compat_ioctl			= aac_ioctl,
#endif
	.queuecommand			= aac_queuecommand,
	.bios_param			= aac_biosparm,