Commit bce96675 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Martin K. Petersen
Browse files

scsi: ch: Consolidate compat ioctl handling

Merge the native and compat ioctl handlers into a single one using
in_compat_syscall().

Link: https://lore.kernel.org/r/20210724072033.1284840-5-hch@lst.de


Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 44328310
Loading
Loading
Loading
Loading
+22 −51
Original line number Diff line number Diff line
@@ -618,6 +618,12 @@ ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
	return 0;
}

struct changer_element_status32 {
	int		ces_type;
	compat_uptr_t	ces_data;
};
#define CHIOGSTATUS32  _IOW('c', 8, struct changer_element_status32)

static long ch_ioctl(struct file *file,
		    unsigned int cmd, unsigned long arg)
{
@@ -748,7 +754,20 @@ static long ch_ioctl(struct file *file,

		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
	}
#ifdef CONFIG_COMPAT
	case CHIOGSTATUS32:
	{
		struct changer_element_status32 ces32;

		if (copy_from_user(&ces32, argp, sizeof(ces32)))
			return -EFAULT;
		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
			return -EINVAL;

		return ch_gstatus(ch, ces32.ces_type,
				  compat_ptr(ces32.ces_data));
	}
#endif
	case CHIOGELEM:
	{
		struct changer_get_element cge;
@@ -858,59 +877,13 @@ static long ch_ioctl(struct file *file,
	}

	default:
		if (in_compat_syscall())
			return scsi_compat_ioctl(ch->device, cmd, argp);
		return scsi_ioctl(ch->device, cmd, argp);

	}
}

#ifdef CONFIG_COMPAT

struct changer_element_status32 {
	int		ces_type;
	compat_uptr_t	ces_data;
};
#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)

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:
	case CHIOGVPARAMS:
	case CHIOPOSITION:
	case CHIOMOVE:
	case CHIOEXCHANGE:
	case CHIOGELEM:
	case CHIOINITELEM:
	case CHIOSVOLTAG:
		/* compatible */
		return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
	case CHIOGSTATUS32:
	{
		struct changer_element_status32 ces32;
		unsigned char __user *data;

		if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
			return -EFAULT;
		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
			return -EINVAL;

		data = compat_ptr(ces32.ces_data);
		return ch_gstatus(ch, ces32.ces_type, data);
	}
	default:
		return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));

	}
}
#endif

/* ------------------------------------------------------------------------ */

static int ch_probe(struct device *dev)
@@ -1015,9 +988,7 @@ static const struct file_operations changer_fops = {
	.open		= ch_open,
	.release	= ch_release,
	.unlocked_ioctl	= ch_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= ch_ioctl_compat,
#endif
	.compat_ioctl	= compat_ptr_ioctl,
	.llseek		= noop_llseek,
};