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

Commit 650c12c5 authored by Petr Vandrovec's avatar Petr Vandrovec Committed by Stefan Richter
Browse files

ieee1394: raw1394: Add ioctl() for 32bit userland on 64bit kernel



Add compat_ioctl.  Although all structures are more or less same,
raw1394_iso_packets got pointer inside, and raw1394_cycle_timer got unwanted
padding in the middle.  I did not add any translation for ioctls passing array
of integers around as integers seem to have same size (32 bits) on all
architectures supported by Linux.

Signed-off-by: default avatarPetr Vandrovec <petr@vandrovec.name>
Acked-by: default avatarDan Dennedy <dan@dennedy.org>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (split into 3 patches)
parent 883b97ea
Loading
Loading
Loading
Loading
+96 −1
Original line number Diff line number Diff line
@@ -2805,6 +2805,99 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
	return -EINVAL;
}

#ifdef CONFIG_COMPAT
struct raw1394_iso_packets32 {
        __u32 n_packets;
        compat_uptr_t infos;
} __attribute__((packed));

struct raw1394_cycle_timer32 {
        __u32 cycle_timer;
        __u64 local_time;
} __attribute__((packed));

#define RAW1394_IOC_ISO_RECV_PACKETS32          \
        _IOW ('#', 0x25, struct raw1394_iso_packets32)
#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
        _IOW ('#', 0x27, struct raw1394_iso_packets32)
#define RAW1394_IOC_GET_CYCLE_TIMER32           \
        _IOR ('#', 0x30, struct raw1394_cycle_timer32)

static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
                                          struct raw1394_iso_packets32 __user *arg)
{
	compat_uptr_t infos32;
	void *infos;
	long err = -EFAULT;
	struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));

	if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
	    !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
		infos = compat_ptr(infos32);
		if (!copy_to_user(&dst->infos, &infos, sizeof infos))
			err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
	}
	return err;
}

static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
{
	struct raw1394_cycle_timer32 ct;
	int err;

	err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
	if (!err)
		if (copy_to_user(uaddr, &ct, sizeof(ct)))
			err = -EFAULT;
	return err;
}

static long raw1394_compat_ioctl(struct file *file,
				 unsigned int cmd, unsigned long arg)
{
	struct file_info *fi = file->private_data;
	void __user *argp = (void __user *)arg;
	long err;

	lock_kernel();
	switch (cmd) {
	/* These requests have same format as long as 'int' has same size. */
	case RAW1394_IOC_ISO_RECV_INIT:
	case RAW1394_IOC_ISO_RECV_START:
	case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
	case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
	case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
	case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
	case RAW1394_IOC_ISO_RECV_FLUSH:
	case RAW1394_IOC_ISO_XMIT_RECV_STOP:
	case RAW1394_IOC_ISO_XMIT_INIT:
	case RAW1394_IOC_ISO_XMIT_START:
	case RAW1394_IOC_ISO_XMIT_SYNC:
	case RAW1394_IOC_ISO_GET_STATUS:
	case RAW1394_IOC_ISO_SHUTDOWN:
	case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
		err = raw1394_ioctl(NULL, file, cmd, arg);
		break;
	/* These request have different format. */
	case RAW1394_IOC_ISO_RECV_PACKETS32:
		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
		break;
	case RAW1394_IOC_ISO_XMIT_PACKETS32:
		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
		break;
	case RAW1394_IOC_GET_CYCLE_TIMER32:
		err = raw1394_read_cycle_timer32(fi, argp);
		break;
	default:
		err = -EINVAL;
		break;
	}
	unlock_kernel();

	return err;
}
#endif

static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
	struct file_info *fi = file->private_data;
@@ -3044,7 +3137,9 @@ static const struct file_operations raw1394_fops = {
	.write = raw1394_write,
	.mmap = raw1394_mmap,
	.ioctl = raw1394_ioctl,
	// .compat_ioctl = ... someone needs to do this
#ifdef CONFIG_COMPAT
	.compat_ioctl = raw1394_compat_ioctl,
#endif
	.poll = raw1394_poll,
	.open = raw1394_open,
	.release = raw1394_release,