Skip to contentSkip to conversation

reduce code in fs/compat_ioctl.c

PATCH NAK Arnd Bergmann 15 participants 57 messages Nov 5, 2005 – Nov 12, 2005

Subsystems (31)
lore
Share & tools
lore

Arnd Bergmann

author maintainer
#0 lore raw

cover reduce code in fs/compat_ioctl.c

Quoted 9 lines · Christoph Hellwig
Quoted 7 lines · Arnd Bergmann

BTW, I now have a set of 25 patches that moves all handlers from fs/compat_ioctl.c over to the respective drivers and subsystems, but I'm not sure how to best test that.
I intend to at least give it a test run on my Opteron for the whatever ioctls I normally use, but the rest is just guesswork. Christoph, can you review those patches?

Quoted 3 lines

I'm not sure moving everything from fs/compat_ioctl.c is a good idea. Everything that is just in a single driver or subsystem that has common ioctl code - sure. else it doesn't make a lot of sense.

Ok, here is my full set of patches, let's see which ones are sensible and which ones we are better off without.

Getting rid of fs/compat_ioctl.c completely could at least simplify the compat_sys_ioctl() code a bit and would also make sure that we only build the handlers into the kernel that can be used potentially, which reduces the binary size.

The patch set is still largely untested, except for a single compile test, but at least some of the patches are very simple, so maybe I can get a quick ack or nack on them.

In general, I'm just moving over the handlers to the respective subsystem without changing the logic, so the patch should not have any effect on the ioctl operation itself, but it also means that the handlers still use compat_alloc_user_space or get_fs/set_fs when it's not really necessary.

	Arnd <><
 drivers/block/ioctl.c                       |  549 +++++
 drivers/block/loop.c                        |   76
 drivers/block/paride/pcd.c                  |    1
 drivers/block/paride/pd.c                   |    1
 drivers/block/paride/pt.c                   |    1
 drivers/block/pktcdvd.c                     |   20
 drivers/bluetooth/hci_ldisc.c               |   22
 drivers/cdrom/Makefile                      |    2
 drivers/cdrom/aztcd.c                       |    1
 drivers/cdrom/cdu31a.c                      |    1
 drivers/cdrom/cm206.c                       |    1
 drivers/cdrom/compat.c                      |  163 +
 drivers/cdrom/gscd.c                        |    1
 drivers/cdrom/mcdx.c                        |    1
 drivers/cdrom/optcd.c                       |    1
 drivers/cdrom/sbpcd.c                       |    1
 drivers/cdrom/sjcd.c                        |    1
 drivers/cdrom/sonycd535.c                   |    2
 drivers/char/Makefile                       |    1
 drivers/char/compat_mtio.c                  |   81
 drivers/char/ftape/zftape/zftape-init.c     |    1
 drivers/char/n_tty.c                        |    1
 drivers/char/raw.c                          |   91
 drivers/char/tty_io.c                       |  191 +
 drivers/char/viotape.c                      |    1
 drivers/char/vt.c                           |    3
 drivers/char/vt_ioctl.c                     |  195 +
 drivers/i2c/i2c-dev.c                       |  141 +
 drivers/ide/ide-cd.c                        |    1
 drivers/ide/ide-floppy.c                    |    1
 drivers/ide/ide-tape.c                      |    1
 drivers/media/radio/miropcm20-radio.c       |    1
 drivers/media/radio/radio-aimslab.c         |    1
 drivers/media/radio/radio-aztech.c          |    1
 drivers/media/radio/radio-cadet.c           |    1
 drivers/media/radio/radio-gemtek-pci.c      |    1
 drivers/media/radio/radio-gemtek.c          |    1
 drivers/media/radio/radio-maestro.c         |    1
 drivers/media/radio/radio-maxiradio.c       |    1
 drivers/media/radio/radio-rtrack2.c         |    1
 drivers/media/radio/radio-sf16fmi.c         |    1
 drivers/media/radio/radio-sf16fmr2.c        |    1
 drivers/media/radio/radio-terratec.c        |    1
 drivers/media/radio/radio-trust.c           |    1
 drivers/media/radio/radio-typhoon.c         |    1
 drivers/media/radio/radio-zoltrix.c         |    1
 drivers/media/video/Makefile                |    2
 drivers/media/video/arv.c                   |    1
 drivers/media/video/bttv-driver.c           |    1
 drivers/media/video/bw-qcam.c               |    1
 drivers/media/video/c-qcam.c                |    1
 drivers/media/video/compat_ioctl.c          |  318 +++
 drivers/media/video/cpia.c                  |    1
 drivers/media/video/cx88/cx88-video.c       |    2
 drivers/media/video/meye.c                  |    1
 drivers/media/video/pms.c                   |    1
 drivers/media/video/saa5249.c               |    1
 drivers/media/video/saa7134/saa7134-video.c |    2
 drivers/media/video/stradis.c               |    1
 drivers/media/video/w9966.c                 |    1
 drivers/media/video/zoran_driver.c          |    1
 drivers/media/video/zr36120.c               |    1
 drivers/mtd/mtdchar.c                       |   94
 drivers/net/ppp_generic.c                   |  179 +
 drivers/s390/char/tape_char.c               |    1
 drivers/scsi/osst.c                         |    2
 drivers/scsi/sg.c                           |  154 +
 drivers/scsi/sr.c                           |    1
 drivers/scsi/st.c                           |    2
 drivers/usb/core/devio.c                    |  139 +
 drivers/usb/media/dsbr100.c                 |    1
 drivers/usb/media/ov511.c                   |    1
 drivers/usb/media/pwc/pwc-if.c              |    1
 drivers/usb/media/se401.c                   |    1
 drivers/usb/media/stv680.c                  |    1
 drivers/usb/media/usbvideo.c                |    1
 drivers/usb/media/vicam.c                   |    1
 drivers/usb/media/w9968cf.c                 |    1
 drivers/video/fbmem.c                       |  147 +
 fs/autofs/root.c                            |   35
 fs/autofs4/root.c                           |   41
 fs/block_dev.c                              |   10
 fs/cifs/cifsfs.c                            |   10
 fs/cifs/cifsfs.h                            |    2
 fs/cifs/ioctl.c                             |   29
 fs/compat.c                                 |   27
 fs/compat_ioctl.c                           | 2918 ----------------------------
 fs/ext2/dir.c                               |    3
 fs/ext2/ext2.h                              |    1
 fs/ext2/file.c                              |    6
 fs/ext2/ioctl.c                             |   31
 fs/ext3/dir.c                               |    3
 fs/ext3/file.c                              |    3
 fs/ext3/ioctl.c                             |   66
 fs/fat/dir.c                                |   54
 fs/hfsplus/dir.c                            |    4
 fs/hfsplus/hfsplus_fs.h                     |    4
 fs/hfsplus/inode.c                          |    4
 fs/hfsplus/ioctl.c                          |   29
 fs/ncpfs/dir.c                              |    3
 fs/ncpfs/file.c                             |    4
 fs/ncpfs/ioctl.c                            |  241 ++
 fs/reiserfs/dir.c                           |    3
 fs/reiserfs/file.c                          |    4
 fs/reiserfs/ioctl.c                         |   36
 fs/smbfs/dir.c                              |    4
 fs/smbfs/file.c                             |    4
 fs/smbfs/ioctl.c                            |   16
 fs/smbfs/proto.h                            |    1
 fs/xfs/linux-2.6/xfs_ioctl32.c              |   15
 include/linux/cdrom.h                       |    2
 include/linux/compat_ioctl.h                |  387 ---
 include/linux/ext2_fs.h                     |    7
 include/linux/ext3_fs.h                     |    1
 include/linux/fs.h                          |    3
 include/linux/ioctl32.h                     |    2
 include/linux/mtio.h                        |   12
 include/linux/ncp_fs.h                      |    1
 include/linux/net.h                         |    2
 include/linux/reiserfs_fs.h                 |    9
 include/linux/socket.h                      |    4
 include/linux/tty.h                         |    2
 include/linux/tty_driver.h                  |    4
 include/linux/tty_ldisc.h                   |    2
 include/linux/videodev.h                    |    2
 include/net/sock.h                          |    9
 net/atm/common.h                            |    1
 net/atm/ioctl.c                             |  167 +
 net/atm/pvc.c                               |    3
 net/atm/svc.c                               |    3
 net/bluetooth/bnep/sock.c                   |    1
 net/bluetooth/cmtp/sock.c                   |    1
 net/bluetooth/hci_sock.c                    |    1
 net/bluetooth/hidp/sock.c                   |    1
 net/bluetooth/rfcomm/sock.c                 |    1
 net/compat.c                                | 1456 +++++++++----
 net/socket.c                                |    7
 137 files changed, 4527 insertions(+), 3807 deletions(-)

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

author maintainer
#1 lore raw

PATCH 1/25 compat: Remove leftovers from register_ioctl32_conversion

We don't need the semaphore any more since we no longer write to the ioctl32 hash table while the kernel is running.

fs/compat.c +0 -7
Index: linux-2.6.14-rc/fs/compat.c
===================================================================
@@ -268,7 +268,6 @@
 
 #define IOCTL_HASHSIZE 256
 static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
-static DECLARE_RWSEM(ioctl32_sem);
 
 extern struct ioctl_trans ioctl_start[];
 extern int ioctl_table_size;
@@ -390,14 +389,10 @@
 		break;
 	}
 
-	/* When register_ioctl32_conversion is finally gone remove
-	   this lock! -AK */
-	down_read(&ioctl32_sem);
 	for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
 		if (t->cmd == cmd)
 			goto found_handler;
 	}
-	up_read(&ioctl32_sem);
 
 	if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
 	    cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
@@ -417,11 +412,9 @@
 		lock_kernel();
 		error = t->handler(fd, cmd, arg, filp);
 		unlock_kernel();
-		up_read(&ioctl32_sem);
 		goto out_fput;
 	}
 
-	up_read(&ioctl32_sem);
  do_ioctl:
 	error = vfs_ioctl(filp, fd, cmd, arg);
  out_fput:
include/linux/ioctl32.h +0 -2
Index: linux-2.6.14-rc/include/linux/ioctl32.h
===================================================================
@@ -1,8 +1,6 @@
 #ifndef IOCTL32_H
 #define IOCTL32_H 1
 
-#include <linux/compiler.h>	/* for __deprecated */
-
 struct file;
 
 typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,

--

#2 lore raw

Re: [PATCH 01/25] compat: Remove leftovers from register_ioctl32_conversion

Quoted 2 lines · Arnd Bergmann

We don't need the semaphore any more since we no longer write to the ioctl32 hash table while the kernel is running.

Could we *please* get rid of this ridiculous return type of compat_ioctl?

->ioctl() returns 32bit value. Everywhere. On 32 and 64 bit platforms. Having ->compat_ioctl() return value twice wider than not just emulated ->ioctl(), but native one as well...

Let's kill that stupidity before adding fsckloads of new instances.

#3 lore raw

Re: [PATCH 01/25] compat: Remove leftovers from register_ioctl32_conversion

In reply to Arnd Bergmann
Quoted 2 lines · Arnd Bergmann

We don't need the semaphore any more since we no longer write to the ioctl32 hash table while the kernel is running.

Yes good patch. In fact I had a similar patch in one of my trees for a long time, just didn't get around to submit it yet.

-Andi

author maintainer
#4 lore raw

PATCH 2/25 net: move socket ioctl32 to net/compat.c

In reply to Arnd Bergmann

This patch is very experimental and completely untested.

A substantial amount of the compat_ioctl code deals with socked ioctls. This patch moves all socket ioctl conversions over to net/compat.c in order to get it closer to the respective device drivers.

It also adds the infrastructure to do compat_ioctl specific to proto_ops, which will be used in further patches.

Also, the SIOCDEVPRIVATE handling is now local to a single file and can probably be made driver specific in the future.

All the conversion handlers are basically unmodified in order to minimize the risk of silently breaking stuff.

fs/compat_ioctl.c +0 -845
Index: linux-2.6.14-rc/fs/compat_ioctl.c
===================================================================
@@ -413,408 +413,6 @@
 	return err;
 }
 
-#ifdef CONFIG_NET
-static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct compat_timeval __user *up = compat_ptr(arg);
-	struct timeval ktv;
-	mm_segment_t old_fs = get_fs();
-	int err;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
-	set_fs(old_fs);
-	if(!err) {
-		err = put_user(ktv.tv_sec, &up->tv_sec);
-		err |= __put_user(ktv.tv_usec, &up->tv_usec);
-	}
-	return err;
-}
-
-struct ifmap32 {
-	compat_ulong_t mem_start;
-	compat_ulong_t mem_end;
-	unsigned short base_addr;
-	unsigned char irq;
-	unsigned char dma;
-	unsigned char port;
-};
-
-struct ifreq32 {
-#define IFHWADDRLEN     6
-#define IFNAMSIZ        16
-        union {
-                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
-        } ifr_ifrn;
-        union {
-                struct  sockaddr ifru_addr;
-                struct  sockaddr ifru_dstaddr;
-                struct  sockaddr ifru_broadaddr;
-                struct  sockaddr ifru_netmask;
-                struct  sockaddr ifru_hwaddr;
-                short   ifru_flags;
-                compat_int_t     ifru_ivalue;
-                compat_int_t     ifru_mtu;
-                struct  ifmap32 ifru_map;
-                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
-		char	ifru_newname[IFNAMSIZ];
-                compat_caddr_t ifru_data;
-	    /* XXXX? ifru_settings should be here */
-        } ifr_ifru;
-};
-
-struct ifconf32 {
-        compat_int_t	ifc_len;                        /* size of buffer       */
-        compat_caddr_t  ifcbuf;
-};
-
-static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct net_device *dev;
-	struct ifreq32 ifr32;
-	int err;
-
-	if (copy_from_user(&ifr32, compat_ptr(arg), sizeof(ifr32)))
-		return -EFAULT;
-
-	dev = dev_get_by_index(ifr32.ifr_ifindex);
-	if (!dev)
-		return -ENODEV;
-
-	strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
-	dev_put(dev);
-	
-	err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
-	return (err ? -EFAULT : 0);
-}
-
-static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifconf32 ifc32;
-	struct ifconf ifc;
-	struct ifconf __user *uifc;
-	struct ifreq32 __user *ifr32;
-	struct ifreq __user *ifr;
-	unsigned int i, j;
-	int err;
-
-	if (copy_from_user(&ifc32, compat_ptr(arg), sizeof(struct ifconf32)))
-		return -EFAULT;
-
-	if (ifc32.ifcbuf == 0) {
-		ifc32.ifc_len = 0;
-		ifc.ifc_len = 0;
-		ifc.ifc_req = NULL;
-		uifc = compat_alloc_user_space(sizeof(struct ifconf));
-	} else {
-		size_t len =((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
-			sizeof (struct ifreq);
-		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
-		ifc.ifc_len = len;
-		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
-		ifr32 = compat_ptr(ifc32.ifcbuf);
-		for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
-			if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32)))
-				return -EFAULT;
-			ifr++;
-			ifr32++; 
-		}
-	}
-	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
-		return -EFAULT;
-
-	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc);	
-	if (err)
-		return err;
-
-	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) 
-		return -EFAULT;
-
-	ifr = ifc.ifc_req;
-	ifr32 = compat_ptr(ifc32.ifcbuf);
-	for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
-	     i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
-		if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32)))
-			return -EFAULT;
-		ifr32++;
-		ifr++;
-	}
-
-	if (ifc32.ifcbuf == 0) {
-		/* Translate from 64-bit structure multiple to
-		 * a 32-bit one.
-		 */
-		i = ifc.ifc_len;
-		i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
-		ifc32.ifc_len = i;
-	} else {
-		if (i <= ifc32.ifc_len)
-			ifc32.ifc_len = i;
-		else
-			ifc32.ifc_len = i - sizeof (struct ifreq32);
-	}
-	if (copy_to_user(compat_ptr(arg), &ifc32, sizeof(struct ifconf32)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifreq __user *ifr;
-	struct ifreq32 __user *ifr32;
-	u32 data;
-	void __user *datap;
-	
-	ifr = compat_alloc_user_space(sizeof(*ifr));
-	ifr32 = compat_ptr(arg);
-
-	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
-		return -EFAULT;
-
-	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
-		return -EFAULT;
-
-	datap = compat_ptr(data);
-	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
-		return -EFAULT;
-
-	return sys_ioctl(fd, cmd, (unsigned long) ifr);
-}
-
-static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifreq kifr;
-	struct ifreq __user *uifr;
-	struct ifreq32 __user *ifr32 = compat_ptr(arg);
-	mm_segment_t old_fs;
-	int err;
-	u32 data;
-	void __user *datap;
-
-	switch (cmd) {
-	case SIOCBONDENSLAVE:
-	case SIOCBONDRELEASE:
-	case SIOCBONDSETHWADDR:
-	case SIOCBONDCHANGEACTIVE:
-		if (copy_from_user(&kifr, ifr32, sizeof(struct ifreq32)))
-			return -EFAULT;
-
-		old_fs = get_fs();
-		set_fs (KERNEL_DS);
-		err = sys_ioctl (fd, cmd, (unsigned long)&kifr);
-		set_fs (old_fs);
-
-		return err;
-	case SIOCBONDSLAVEINFOQUERY:
-	case SIOCBONDINFOQUERY:
-		uifr = compat_alloc_user_space(sizeof(*uifr));
-		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
-			return -EFAULT;
-
-		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
-			return -EFAULT;
-
-		datap = compat_ptr(data);
-		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
-			return -EFAULT;
-
-		return sys_ioctl (fd, cmd, (unsigned long)uifr);
-	default:
-		return -EINVAL;
-	};
-}
-
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifreq __user *u_ifreq64;
-	struct ifreq32 __user *u_ifreq32 = compat_ptr(arg);
-	char tmp_buf[IFNAMSIZ];
-	void __user *data64;
-	u32 data32;
-
-	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
-			   IFNAMSIZ))
-		return -EFAULT;
-	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
-		return -EFAULT;
-	data64 = compat_ptr(data32);
-
-	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
-
-	/* Don't check these user accesses, just let that get trapped
-	 * in the ioctl handler instead.
-	 */
-	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
-			 IFNAMSIZ))
-		return -EFAULT;
-	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
-		return -EFAULT;
-
-	return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64);
-}
-
-static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ifreq ifr;
-	struct ifreq32 __user *uifr32;
-	struct ifmap32 __user *uifmap32;
-	mm_segment_t old_fs;
-	int err;
-	
-	uifr32 = compat_ptr(arg);
-	uifmap32 = &uifr32->ifr_ifru.ifru_map;
-	switch (cmd) {
-	case SIOCSIFMAP:
-		err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
-		err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-		err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-		err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-		err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
-		err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
-		err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
-		if (err)
-			return -EFAULT;
-		break;
-	default:
-		if (copy_from_user(&ifr, uifr32, sizeof(*uifr32)))
-			return -EFAULT;
-		break;
-	}
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
-	if (!err) {
-		switch (cmd) {
-		/* TUNSETIFF is defined as _IOW, it should be _IORW
-		 * as the data is copied back to user space, but that
-		 * cannot be fixed without breaking all existing apps.
-		 */
-		case TUNSETIFF:
-		case SIOCGIFFLAGS:
-		case SIOCGIFMETRIC:
-		case SIOCGIFMTU:
-		case SIOCGIFMEM:
-		case SIOCGIFHWADDR:
-		case SIOCGIFINDEX:
-		case SIOCGIFADDR:
-		case SIOCGIFBRDADDR:
-		case SIOCGIFDSTADDR:
-		case SIOCGIFNETMASK:
-		case SIOCGIFTXQLEN:
-			if (copy_to_user(uifr32, &ifr, sizeof(*uifr32)))
-				return -EFAULT;
-			break;
-		case SIOCGIFMAP:
-			err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
-			err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-			err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-			err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-			err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
-			err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
-			err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
-			if (err)
-				err = -EFAULT;
-			break;
-		}
-	}
-	return err;
-}
-
-struct rtentry32 {
-        u32   		rt_pad1;
-        struct sockaddr rt_dst;         /* target address               */
-        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
-        struct sockaddr rt_genmask;     /* target network mask (IP)     */
-        unsigned short  rt_flags;
-        short           rt_pad2;
-        u32   		rt_pad3;
-        unsigned char   rt_tos;
-        unsigned char   rt_class;
-        short           rt_pad4;
-        short           rt_metric;      /* +1 for binary compatibility! */
-        /* char * */ u32 rt_dev;        /* forcing the device at add    */
-        u32   		rt_mtu;         /* per route MTU/Window         */
-        u32   		rt_window;      /* Window clamping              */
-        unsigned short  rt_irtt;        /* Initial RTT                  */
-
-};
-
-struct in6_rtmsg32 {
-	struct in6_addr		rtmsg_dst;
-	struct in6_addr		rtmsg_src;
-	struct in6_addr		rtmsg_gateway;
-	u32			rtmsg_type;
-	u16			rtmsg_dst_len;
-	u16			rtmsg_src_len;
-	u32			rtmsg_metric;
-	u32			rtmsg_info;
-	u32			rtmsg_flags;
-	s32			rtmsg_ifindex;
-};
-
-static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	void *r = NULL;
-	struct in6_rtmsg r6;
-	struct rtentry r4;
-	char devname[16];
-	u32 rtdev;
-	mm_segment_t old_fs = get_fs();
-	
-	struct socket *mysock = sockfd_lookup(fd, &ret);
-
-	if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */
-		struct in6_rtmsg32 __user *ur6 = compat_ptr(arg);
-		ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst),
-			3 * sizeof(struct in6_addr));
-		ret |= __get_user (r6.rtmsg_type, &(ur6->rtmsg_type));
-		ret |= __get_user (r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
-		ret |= __get_user (r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
-		ret |= __get_user (r6.rtmsg_metric, &(ur6->rtmsg_metric));
-		ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info));
-		ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags));
-		ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
-		
-		r = (void *) &r6;
-	} else { /* ipv4 */
-		struct rtentry32 __user *ur4 = compat_ptr(arg);
-		ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst),
-					3 * sizeof(struct sockaddr));
-		ret |= __get_user (r4.rt_flags, &(ur4->rt_flags));
-		ret |= __get_user (r4.rt_metric, &(ur4->rt_metric));
-		ret |= __get_user (r4.rt_mtu, &(ur4->rt_mtu));
-		ret |= __get_user (r4.rt_window, &(ur4->rt_window));
-		ret |= __get_user (r4.rt_irtt, &(ur4->rt_irtt));
-		ret |= __get_user (rtdev, &(ur4->rt_dev));
-		if (rtdev) {
-			ret |= copy_from_user (devname, compat_ptr(rtdev), 15);
-			r4.rt_dev = devname; devname[15] = 0;
-		} else
-			r4.rt_dev = NULL;
-
-		r = (void *) &r4;
-	}
-
-	if (ret) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl (fd, cmd, (unsigned long) r);
-	set_fs (old_fs);
-
-out:
-	if (mysock)
-		sockfd_put(mysock);
-
-	return ret;
-}
-#endif
-
 struct hd_geometry32 {
 	unsigned char heads;
 	unsigned char sectors;
@@ -1146,127 +744,6 @@
 	return err;
 }
 
-struct sock_fprog32 {
-	unsigned short	len;
-	compat_caddr_t	filter;
-};
-
-#define PPPIOCSPASS32	_IOW('t', 71, struct sock_fprog32)
-#define PPPIOCSACTIVE32	_IOW('t', 70, struct sock_fprog32)
-
-static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct sock_fprog32 __user *u_fprog32 = compat_ptr(arg);
-	struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
-	void __user *fptr64;
-	u32 fptr32;
-	u16 flen;
-
-	if (get_user(flen, &u_fprog32->len) ||
-	    get_user(fptr32, &u_fprog32->filter))
-		return -EFAULT;
-
-	fptr64 = compat_ptr(fptr32);
-
-	if (put_user(flen, &u_fprog64->len) ||
-	    put_user(fptr64, &u_fprog64->filter))
-		return -EFAULT;
-
-	if (cmd == PPPIOCSPASS32)
-		cmd = PPPIOCSPASS;
-	else
-		cmd = PPPIOCSACTIVE;
-
-	return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
-}
-
-struct ppp_option_data32 {
-	compat_caddr_t	ptr;
-	u32			length;
-	compat_int_t		transmit;
-};
-#define PPPIOCSCOMPRESS32	_IOW('t', 77, struct ppp_option_data32)
-
-struct ppp_idle32 {
-	compat_time_t xmit_idle;
-	compat_time_t recv_idle;
-};
-#define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
-
-static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ppp_idle __user *idle;
-	struct ppp_idle32 __user *idle32;
-	__kernel_time_t xmit, recv;
-	int err;
-
-	idle = compat_alloc_user_space(sizeof(*idle));
-	idle32 = compat_ptr(arg);
-
-	err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
-
-	if (!err) {
-		if (get_user(xmit, &idle->xmit_idle) ||
-		    get_user(recv, &idle->recv_idle) ||
-		    put_user(xmit, &idle32->xmit_idle) ||
-		    put_user(recv, &idle32->recv_idle))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ppp_option_data __user *odata;
-	struct ppp_option_data32 __user *odata32;
-	__u32 data;
-	void __user *datap;
-
-	odata = compat_alloc_user_space(sizeof(*odata));
-	odata32 = compat_ptr(arg);
-
-	if (get_user(data, &odata32->ptr))
-		return -EFAULT;
-
-	datap = compat_ptr(data);
-	if (put_user(datap, &odata->ptr))
-		return -EFAULT;
-
-	if (copy_in_user(&odata->length, &odata32->length,
-			 sizeof(__u32) + sizeof(int)))
-		return -EFAULT;
-
-	return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
-}
-
-static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	int err;
-
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		err = ppp_gidle(fd, cmd, arg);
-		break;
-
-	case PPPIOCSCOMPRESS32:
-		err = ppp_scompress(fd, cmd, arg);
-		break;
-
-	default:
-		do {
-			static int count;
-			if (++count <= 20)
-				printk("ppp_ioctl: Unknown cmd fd(%d) "
-				       "cmd(%08x) arg(%08x)\n",
-				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
-		} while(0);
-		err = -EINVAL;
-		break;
-	};
-
-	return err;
-}
-
 
 struct mtget32 {
 	compat_long_t	mt_type;
@@ -1664,171 +1141,6 @@
 	return err;
 }
 
-struct atmif_sioc32 {
-        compat_int_t	number;
-        compat_int_t	length;
-        compat_caddr_t	arg;
-};
-
-struct atm_iobuf32 {
-	compat_int_t	length;
-	compat_caddr_t	buffer;
-};
-
-#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
-#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
-#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
-#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
-#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
-#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
-#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
-#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
-#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
-#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
-#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
-#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
-#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
-#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
-#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
-#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
-#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
-
-static struct {
-        unsigned int cmd32;
-        unsigned int cmd;
-} atm_ioctl_map[] = {
-        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
-	{ ATM_GETNAMES32,    ATM_GETNAMES },
-        { ATM_GETTYPE32,     ATM_GETTYPE },
-        { ATM_GETESI32,      ATM_GETESI },
-        { ATM_GETADDR32,     ATM_GETADDR },
-        { ATM_RSTADDR32,     ATM_RSTADDR },
-        { ATM_ADDADDR32,     ATM_ADDADDR },
-        { ATM_DELADDR32,     ATM_DELADDR },
-        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
-	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
-	{ ATM_SETESI32,      ATM_SETESI },
-	{ ATM_SETESIF32,     ATM_SETESIF },
-	{ ATM_GETSTAT32,     ATM_GETSTAT },
-	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
-	{ ATM_GETLOOP32,     ATM_GETLOOP },
-	{ ATM_SETLOOP32,     ATM_SETLOOP },
-	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
-};
-
-#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
-
-
-static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct atm_iobuf   __user *iobuf;
-	struct atm_iobuf32 __user *iobuf32;
-	u32 data;
-	void __user *datap;
-	int len, err;
-
-	iobuf = compat_alloc_user_space(sizeof(*iobuf));
-	iobuf32 = compat_ptr(arg);
-
-	if (get_user(len, &iobuf32->length) ||
-	    get_user(data, &iobuf32->buffer))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(len, &iobuf->length) ||
-	    put_user(datap, &iobuf->buffer))
-		return -EFAULT;
-
-	err = sys_ioctl(fd, cmd, (unsigned long)iobuf);
-
-	if (!err) {
-		if (copy_in_user(&iobuf32->length, &iobuf->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-
-	return err;
-}
-
-static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-        struct atmif_sioc   __user *sioc;
-	struct atmif_sioc32 __user *sioc32;
-	u32 data;
-	void __user *datap;
-	int err;
-        
-	sioc = compat_alloc_user_space(sizeof(*sioc));
-	sioc32 = compat_ptr(arg);
-
-	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
-	    get_user(data, &sioc32->arg))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(datap, &sioc->arg))
-		return -EFAULT;
-
-	err = sys_ioctl(fd, cmd, (unsigned long) sioc);
-
-	if (!err) {
-		if (copy_in_user(&sioc32->length, &sioc->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
-{
-        int i;
-        unsigned int cmd = 0;
-        
-	switch (cmd32) {
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atmif_sioc(fd, cmd32, arg);
-	}
-
-	for (i = 0; i < NR_ATM_IOCTL; i++) {
-		if (cmd32 == atm_ioctl_map[i].cmd32) {
-			cmd = atm_ioctl_map[i].cmd;
-			break;
-		}
-	}
-	if (i == NR_ATM_IOCTL)
-	        return -EINVAL;
-        
-        switch (cmd) {
-	case ATM_GETNAMES:
-		return do_atm_iobuf(fd, cmd, arg);
-	    
-	case ATM_GETLINKRATE:
-        case ATM_GETTYPE:
-        case ATM_GETESI:
-        case ATM_GETADDR:
-        case ATM_RSTADDR:
-        case ATM_ADDADDR:
-        case ATM_DELADDR:
-        case ATM_GETCIRANGE:
-	case ATM_SETCIRANGE:
-	case ATM_SETESI:
-	case ATM_SETESIF:
-	case ATM_GETSTAT:
-	case ATM_GETSTATZ:
-	case ATM_GETLOOP:
-	case ATM_SETLOOP:
-	case ATM_QUERYLOOP:
-                return do_atmif_sioc(fd, cmd, arg);
-        }
-
-        return -EINVAL;
-}
-
 static __attribute_used__ int 
 ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -2641,65 +1953,6 @@
 	return sys_ioctl(fd, cmd, (unsigned long)tdata);
 }
 
-struct compat_iw_point {
-	compat_caddr_t pointer;
-	__u16 length;
-	__u16 flags;
-};
-
-static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct iwreq __user *iwr;
-	struct iwreq __user *iwr_u;
-	struct iw_point __user *iwp;
-	struct compat_iw_point __user *iwp_u;
-	compat_caddr_t pointer;
-	__u16 length, flags;
-
-	iwr_u = compat_ptr(arg);
-	iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data;
-	iwr = compat_alloc_user_space(sizeof(*iwr));
-	if (iwr == NULL)
-		return -ENOMEM;
-
-	iwp = &iwr->u.data;
-
-	if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr)))
-		return -EFAULT;
-
-	if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0],
-			   &iwr_u->ifr_ifrn.ifrn_name[0],
-			   sizeof(iwr->ifr_ifrn.ifrn_name)))
-		return -EFAULT;
-
-	if (__get_user(pointer, &iwp_u->pointer) ||
-	    __get_user(length, &iwp_u->length) ||
-	    __get_user(flags, &iwp_u->flags))
-		return -EFAULT;
-
-	if (__put_user(compat_ptr(pointer), &iwp->pointer) ||
-	    __put_user(length, &iwp->length) ||
-	    __put_user(flags, &iwp->flags))
-		return -EFAULT;
-
-	return sys_ioctl(fd, cmd, (unsigned long) iwr);
-}
-
-/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
- * for some operations; this forces use of the newer bridge-utils that
- * use compatiable ioctls
- */
-static int old_bridge_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	u32 tmp;
-
-	if (get_user(tmp, (u32 __user *) arg))
-		return -EFAULT;
-	if (tmp == BRCTL_GET_VERSION)
-		return BRCTL_VERSION + 1;
-	return -EINVAL;
-}
-
 #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
 struct ncp_ioctl_request_32 {
 	u32 function;
@@ -2893,59 +2146,6 @@
 #ifdef DECLARES
 HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
 HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
-#ifdef CONFIG_NET
-HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
-HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
-HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc)
-HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
-
-/* ioctls used by appletalk ddp.c */
-HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCDIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSARP, dev_ifsioc)
-HANDLE_IOCTL(SIOCDARP, dev_ifsioc)
-
-HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
-HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
-HANDLE_IOCTL(TUNSETIFF, dev_ifsioc)
-HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
-HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl)
-HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl)
-HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl)
-HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl)
-HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl)
-HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl)
-HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
-HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
-HANDLE_IOCTL(SIOCBRADDIF, dev_ifsioc)
-HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc)
-/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
-HANDLE_IOCTL(SIOCRTMSG, ret_einval)
-HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
-#endif
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
 HANDLE_IOCTL(BLKRAGET, w_long)
 HANDLE_IOCTL(BLKGETSIZE, w_long)
@@ -2973,10 +2173,6 @@
 HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
 HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
 HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
-HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
@@ -3007,31 +2203,6 @@
 /* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
 HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
-HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
-HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
-HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
 /* block stuff */
 HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
 HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
@@ -3054,22 +2225,6 @@
 HANDLE_IOCTL(I2C_FUNCS, w_long)
 HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
 HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl)
-/* wireless */
-HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
-HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
 
 #if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
 HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
include/linux/compat_ioctl.h +0 -89

107 lines not on this page · raw message

net/compat.c +962 -0

971 lines not on this page · raw message

net/socket.c +4 -3
Index: linux-2.6.14-rc/net/socket.c
===================================================================
@@ -107,8 +107,6 @@
 static int sock_close(struct inode *inode, struct file *file);
 static unsigned int sock_poll(struct file *file,
 			      struct poll_table_struct *wait);
-static long sock_ioctl(struct file *file,
-		      unsigned int cmd, unsigned long arg);
 static int sock_fasync(int fd, struct file *filp, int on);
 static ssize_t sock_readv(struct file *file, const struct iovec *vector,
 			  unsigned long count, loff_t *ppos);
@@ -130,6 +128,9 @@
 	.aio_write =	sock_aio_write,
 	.poll =		sock_poll,
 	.unlocked_ioctl = sock_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = compat_sock_ioctl,
+#endif
 	.mmap =		sock_mmap,
 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
 	.release =	sock_close,
@@ -834,7 +835,7 @@
  *	what to do with it - that's up to the protocol still.
  */
 
-static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
 	struct socket *sock;
 	void __user *argp = (void __user *)arg;
fs/compat.c +7 -13
Index: linux-2.6.14-rc/fs/compat.c
===================================================================
@@ -27,7 +27,6 @@
 #include <linux/ioctl32.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
-#include <linux/sockios.h>	/* for SIOCDEVPRIVATE */
 #include <linux/smb.h>
 #include <linux/smb_mount.h>
 #include <linux/ncp_mount.h>
@@ -46,8 +45,9 @@
 #include <linux/rwsem.h>
 #include <linux/acct.h>
 #include <linux/mm.h>
-
-#include <net/sock.h>		/* siocdevprivate_ioctl */
+#include <linux/security.h>
+#include <linux/highmem.h>
+#include <linux/poll.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -346,6 +346,7 @@
 	int error = -EBADF;
 	struct ioctl_trans *t;
 	int fput_needed;
+	static int count;
 
 	filp = fget_light(fd, &fput_needed);
 	if (!filp)
@@ -394,16 +395,9 @@
 			goto found_handler;
 	}
 
-	if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
-	    cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
-		error = siocdevprivate_ioctl(fd, cmd, arg);
-	} else {
-		static int count;
-
-		if (++count <= 50)
-			compat_ioctl_error(filp, fd, cmd, arg);
-		error = -EINVAL;
-	}
+	if (++count <= 50)
+		compat_ioctl_error(filp, fd, cmd, arg);
+	error = -EINVAL;
 
 	goto out_fput;
 
include/linux/socket.h +4 -0
Index: linux-2.6.14-rc/include/linux/socket.h
===================================================================
@@ -299,6 +299,10 @@
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 
+struct file;
+extern long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+extern long compat_sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
 #endif
 #endif /* not kernel and not glibc */
 #endif /* _LINUX_SOCKET_H */
include/net/sock.h +0 -9
Index: linux-2.6.14-rc/include/net/sock.h
===================================================================
@@ -1365,15 +1365,6 @@
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
-#ifdef CONFIG_NET
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-#else
-static inline int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return -ENODEV;
-}
-#endif
-
 extern void sk_init(void);
 
 #ifdef CONFIG_SYSCTL
include/linux/net.h +2 -0
Index: linux-2.6.14-rc/include/linux/net.h
===================================================================
@@ -142,6 +142,8 @@
 				      struct poll_table_struct *wait);
 	int		(*ioctl)     (struct socket *sock, unsigned int cmd,
 				      unsigned long arg);
+	int		(*compat_ioctl)(struct socket *sock, unsigned int cmd,
+				      unsigned long arg);
 	int		(*listen)    (struct socket *sock, int len);
 	int		(*shutdown)  (struct socket *sock, int flags);
 	int		(*setsockopt)(struct socket *sock, int level,

--

author maintainer
#5 lore raw

PATCH 3/25 net: improve ioctl32 dev_ioctl handling

In reply to Arnd Bergmann

This patch tries to be a bit smarter about net device ioctl emulation. In particular, the wireless extensions are treated as a group in order to make the switch list a little shorter.

net/compat.c +58 -87
Index: linux-cg/net/compat.c
===================================================================
@@ -854,7 +854,7 @@
 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
 		return -EFAULT;
 
-	return sock_ioctl(file, cmd, (unsigned long) u_ifreq64);
+	return dev_ioctl(cmd, u_ifreq64);
 }
 
 static int dev_ifsioc(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1302,13 +1302,14 @@
 	return err;
 }
 
+#ifdef WIRELESS_EXT
 struct compat_iw_point {
 	compat_caddr_t pointer;
 	__u16 length;
 	__u16 flags;
 };
 
-static int do_wireless_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static int do_wireless_ioctl(unsigned int cmd, unsigned long arg)
 {
 	struct iwreq __user *iwr;
 	struct iwreq __user *iwr_u;
@@ -1343,8 +1344,9 @@
 	    __put_user(flags, &iwp->flags))
 		return -EFAULT;
 
-	return sock_ioctl(file, cmd, (unsigned long) iwr);
+	return dev_ioctl(cmd, iwr);
 }
+#endif /* WIRELESS_EXT */
 
 /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
  * for some operations; this forces use of the newer bridge-utils that
@@ -1363,16 +1365,43 @@
 
 long compat_sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
-		return siocdevprivate_ioctl(file, cmd, arg);
+	struct socket *sock;
+	int ret = -ENOIOCTLCMD;
 
-	switch (cmd) {
+	sock = file->private_data;
+	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
+		ret = siocdevprivate_ioctl(file, cmd, arg);
+#ifdef WIRELESS_EXT
+	else if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
+		ret = do_wireless_ioctl(cmd, arg);
+#endif
+	else switch (cmd) {
 #define HANDLE_IOCTL(type, handler) \
-	case type: return handler(file, cmd, arg);
+	case type: ret = handler(file, cmd, arg); break;
 #define COMPATIBLE_IOCTL(type) \
-	case type: return sock_ioctl(file, cmd, arg);
+	case type: ret = sock_ioctl(file, cmd, arg); break;
 #define INVAL_IOCTL(type) \
-	case type: return -EINVAL;
+	case type: ret = -EINVAL; break;
+/* these are handled in sock_ioctl */
+COMPATIBLE_IOCTL(FIOSETOWN)
+COMPATIBLE_IOCTL(SIOCSPGRP)
+COMPATIBLE_IOCTL(FIOGETOWN)
+COMPATIBLE_IOCTL(SIOCGPGRP)
+HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
+HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
+COMPATIBLE_IOCTL(SIOCBRADDBR)
+COMPATIBLE_IOCTL(SIOCBRDELBR)
+COMPATIBLE_IOCTL(SIOCGIFVLAN)
+COMPATIBLE_IOCTL(SIOCSIFVLAN)
+COMPATIBLE_IOCTL(SIOCADDDLCI)
+COMPATIBLE_IOCTL(SIOCDELDLCI)
+	default:
+		if (sock->ops->compat_ioctl)
+			ret = sock->ops->compat_ioctl(sock, cmd, arg);
+	}
+
+	if (ret == -ENOIOCTLCMD)
+		switch (cmd) {
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
 HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
@@ -1393,10 +1422,6 @@
 HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
 
-/* ioctls used by appletalk ddp.c */
-HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc)
-HANDLE_IOCTL(SIOCDIFADDR, dev_ifsioc)
-
 HANDLE_IOCTL(SIOCSARP, dev_ifsioc)
 HANDLE_IOCTL(SIOCDARP, dev_ifsioc)
 
@@ -1456,79 +1481,6 @@
 HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
-/* wireless */
-HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
-HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
-HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
-
-COMPATIBLE_IOCTL(FIOSETOWN)
-COMPATIBLE_IOCTL(SIOCSPGRP)
-COMPATIBLE_IOCTL(FIOGETOWN)
-COMPATIBLE_IOCTL(SIOCGPGRP)
-COMPATIBLE_IOCTL(SIOCATMARK)
-COMPATIBLE_IOCTL(SIOCSIFLINK)
-COMPATIBLE_IOCTL(SIOCSIFENCAP)
-COMPATIBLE_IOCTL(SIOCGIFENCAP)
-COMPATIBLE_IOCTL(SIOCSIFNAME)
-//COMPATIBLE_IOCTL(SIOCSARP)
-COMPATIBLE_IOCTL(SIOCGARP)
-//COMPATIBLE_IOCTL(SIOCDARP)
-COMPATIBLE_IOCTL(SIOCSRARP)
-COMPATIBLE_IOCTL(SIOCGRARP)
-COMPATIBLE_IOCTL(SIOCDRARP)
-COMPATIBLE_IOCTL(SIOCADDDLCI)
-COMPATIBLE_IOCTL(SIOCDELDLCI)
-COMPATIBLE_IOCTL(SIOCGMIIPHY)
-COMPATIBLE_IOCTL(SIOCGMIIREG)
-COMPATIBLE_IOCTL(SIOCSMIIREG)
-COMPATIBLE_IOCTL(SIOCGIFVLAN)
-COMPATIBLE_IOCTL(SIOCSIFVLAN)
-COMPATIBLE_IOCTL(SIOCBRADDBR)
-COMPATIBLE_IOCTL(SIOCBRDELBR)
-/* wireless */
-COMPATIBLE_IOCTL(SIOCSIWCOMMIT)
-COMPATIBLE_IOCTL(SIOCGIWNAME)
-COMPATIBLE_IOCTL(SIOCSIWNWID)
-COMPATIBLE_IOCTL(SIOCGIWNWID)
-COMPATIBLE_IOCTL(SIOCSIWFREQ)
-COMPATIBLE_IOCTL(SIOCGIWFREQ)
-COMPATIBLE_IOCTL(SIOCSIWMODE)
-COMPATIBLE_IOCTL(SIOCGIWMODE)
-COMPATIBLE_IOCTL(SIOCSIWSENS)
-COMPATIBLE_IOCTL(SIOCGIWSENS)
-COMPATIBLE_IOCTL(SIOCSIWRANGE)
-COMPATIBLE_IOCTL(SIOCSIWPRIV)
-COMPATIBLE_IOCTL(SIOCGIWPRIV)
-COMPATIBLE_IOCTL(SIOCSIWSTATS)
-COMPATIBLE_IOCTL(SIOCGIWSTATS)
-COMPATIBLE_IOCTL(SIOCSIWAP)
-COMPATIBLE_IOCTL(SIOCGIWAP)
-COMPATIBLE_IOCTL(SIOCSIWSCAN)
-COMPATIBLE_IOCTL(SIOCSIWRATE)
-COMPATIBLE_IOCTL(SIOCGIWRATE)
-COMPATIBLE_IOCTL(SIOCSIWRTS)
-COMPATIBLE_IOCTL(SIOCGIWRTS)
-COMPATIBLE_IOCTL(SIOCSIWFRAG)
-COMPATIBLE_IOCTL(SIOCGIWFRAG)
-COMPATIBLE_IOCTL(SIOCSIWTXPOW)
-COMPATIBLE_IOCTL(SIOCGIWTXPOW)
-COMPATIBLE_IOCTL(SIOCSIWRETRY)
-COMPATIBLE_IOCTL(SIOCGIWRETRY)
-COMPATIBLE_IOCTL(SIOCSIWPOWER)
-COMPATIBLE_IOCTL(SIOCGIWPOWER)
-/* PPP stuff */
 COMPATIBLE_IOCTL(PPPIOCGFLAGS)
 COMPATIBLE_IOCTL(PPPIOCSFLAGS)
 COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
@@ -1561,6 +1513,25 @@
 /* PPPOX */
 COMPATIBLE_IOCTL(PPPOEIOCSFWD)
 COMPATIBLE_IOCTL(PPPOEIOCDFWD)
+
+/* ioctls used by appletalk ddp.c */
+HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCDIFADDR, dev_ifsioc)
+
+COMPATIBLE_IOCTL(SIOCATMARK)
+COMPATIBLE_IOCTL(SIOCSIFLINK)
+COMPATIBLE_IOCTL(SIOCSIFENCAP)
+COMPATIBLE_IOCTL(SIOCGIFENCAP)
+COMPATIBLE_IOCTL(SIOCSIFNAME)
+//COMPATIBLE_IOCTL(SIOCSARP)
+COMPATIBLE_IOCTL(SIOCGARP)
+//COMPATIBLE_IOCTL(SIOCDARP)
+COMPATIBLE_IOCTL(SIOCSRARP)
+COMPATIBLE_IOCTL(SIOCGRARP)
+COMPATIBLE_IOCTL(SIOCDRARP)
+COMPATIBLE_IOCTL(SIOCGMIIPHY)
+COMPATIBLE_IOCTL(SIOCGMIIREG)
+COMPATIBLE_IOCTL(SIOCSMIIREG)
 	}
-	return -ENOIOCTLCMD;
+	return ret;
 }

--

author maintainer
#6 lore raw

PATCH 4/25 net: move atm ioctl32 to net/atm/ioctl.c

In reply to Arnd Bergmann

This moves all the ATM specific compat ioctls to net/atm. The code is still the same as before, but it would probably be a good idea to simplify this by getting rid of using compat_alloc_user_space.

net/atm/common.h +1 -0
Index: linux-2.6.14-rc/net/atm/common.h
===================================================================
@@ -19,6 +19,7 @@
 		size_t total_len);
 unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait);
 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int vcc_setsockopt(struct socket *sock, int level, int optname,
 		   char __user *optval, int optlen);
 int vcc_getsockopt(struct socket *sock, int level, int optname,
net/atm/ioctl.c +167 -0

170 lines not on this page · raw message

net/atm/pvc.c +3 -0
Index: linux-2.6.14-rc/net/atm/pvc.c
===================================================================
@@ -114,6 +114,9 @@
 	.getname =	pvc_getname,
 	.poll =		vcc_poll,
 	.ioctl =	vcc_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	vcc_compat_ioctl,
+#endif
 	.listen =	sock_no_listen,
 	.shutdown =	pvc_shutdown,
 	.setsockopt =	pvc_setsockopt,
net/atm/svc.c +3 -0
Index: linux-2.6.14-rc/net/atm/svc.c
===================================================================
@@ -625,6 +625,9 @@
 	.getname =	svc_getname,
 	.poll =		vcc_poll,
 	.ioctl =	svc_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = vcc_compat_ioctl,
+#endif
 	.listen =	svc_listen,
 	.shutdown =	svc_shutdown,
 	.setsockopt =	svc_setsockopt,
net/compat.c +2 -193

219 lines not on this page · raw message

--

author maintainer
#7 lore raw

PATCH 5/25 net: move ppp specific ioctl32 handlers

In reply to Arnd Bergmann

This moves all ioctl32 code for ppp close to the
native ioctl implementation.

Index: linux-2.6.14-rc/drivers/net/ppp_generic.c
=================================--- linux-2.6.14-rc.orig/drivers/net/ppp_generic.c 2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/drivers/net/ppp_generic.c 2005-11-05 02:41:29.000000000 +0100
@@ -46,6 +46,8 @@
#include <linux/rwsem.h>
#include <linux/stddef.h>
#include <linux/device.h>
+#include <linux/compat.h>
+
#include <net/slhc_vj.h>
#include <asm/atomic.h>

@@ -837,12 +839,189 @@
return err;
}

+#ifdef CONFIG_COMPAT
+/* FIXME: These could be better integrated into the driver */
+
+struct sock_fprog32 {
+ unsigned short len;
+ compat_caddr_t filter;
+};
+
+#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32)
+#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)
+
+static int ppp_sock_fprog_ioctl_trans(struct file *file, unsigned int cmd, unsigned long arg) +{
+ struct sock_fprog32 __user *u_fprog32 = compat_ptr(arg);
+ struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
+ void __user *fptr64;
+ u32 fptr32;
+ u16 flen;
+
+ if (get_user(flen, &u_fprog32->len) ||
+ get_user(fptr32, &u_fprog32->filter))
+ return -EFAULT;
+
+ fptr64 = compat_ptr(fptr32);
+
+ if (put_user(flen, &u_fprog64->len) ||
+ put_user(fptr64, &u_fprog64->filter))
+ return -EFAULT;
+
+ if (cmd = PPPIOCSPASS32)
+ cmd = PPPIOCSPASS;
+ else
+ cmd = PPPIOCSACTIVE;
+
+ return ppp_ioctl(file->f_dentry->d_inode, file, cmd,
+ (unsigned long) u_fprog64);
+}
+
+struct ppp_option_data32 {
+ compat_caddr_t ptr;
+ u32 length;
+ compat_int_t transmit;
+};
+#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32)
+
+struct ppp_idle32 {
+ compat_time_t xmit_idle;
+ compat_time_t recv_idle;
+};
+#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32)
+
+static int ppp_gidle(struct file *file, unsigned int cmd, unsigned long arg) +{
+ struct ppp_idle __user *idle;
+ struct ppp_idle32 __user *idle32;
+ __kernel_time_t xmit, recv;
+ int err;
+
+ idle = compat_alloc_user_space(sizeof(*idle));
+ idle32 = compat_ptr(arg);
+
+ err = ppp_ioctl(file->f_dentry->d_inode, file, PPPIOCGIDLE, (unsigned long) idle);
+
+ if (!err) {

+		if (get_user(xmit, &idle->xmit_idle) ||
+		    get_user(recv, &idle->recv_idle) ||

+ put_user(xmit, &idle32->xmit_idle) ||
+ put_user(recv, &idle32->recv_idle))
+ err = -EFAULT;
+ }
+ return err;
+}
+
+static int ppp_scompress(struct file *file, unsigned int cmd, unsigned long arg) +{
+ struct ppp_option_data __user *odata;
+ struct ppp_option_data32 __user *odata32;
+ __u32 data;
+ void __user *datap;
+
+ odata = compat_alloc_user_space(sizeof(*odata));
+ odata32 = compat_ptr(arg);
+
+ if (get_user(data, &odata32->ptr))
+ return -EFAULT;
+
+ datap = compat_ptr(data);
+ if (put_user(datap, &odata->ptr))
+ return -EFAULT;
+
+ if (copy_in_user(&odata->length, &odata32->length,
+ sizeof(__u32) + sizeof(int)))
+ return -EFAULT;
+
+ return ppp_ioctl(file->f_dentry->d_inode, file, PPPIOCSCOMPRESS, (unsigned long) odata);
+}
+
+static int ppp_ioctl_trans(struct file *file, unsigned int cmd, unsigned long arg) +{
+ int err;
+
+ switch (cmd) {
+ case PPPIOCGIDLE32:
+ err = ppp_gidle(file, cmd, arg);
+ break;
+
+ case PPPIOCSCOMPRESS32:
+ err = ppp_scompress(file, cmd, arg);
+ break;
+
+ default:
+ do {
+ static int count;
+ if (++count <= 20)
+ printk("ppp_ioctl: Unknown cmd(%08x) arg(%08x)\n",
+ (unsigned int)cmd, (unsigned int)arg);
+ } while(0);
+ err = -EINVAL;
+ break;
+ };
+
+ return err;
+}
+
+static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{
+ int ret;
+ ret = -ENOIOCTLCMD;
+
+ lock_kernel();
+ switch (cmd) {
+ case PPPIOCGIDLE32:
+ case PPPIOCSCOMPRESS32:
+ ret = ppp_ioctl_trans(file, cmd, arg);
+ break;
+
+ case PPPIOCSPASS32:
+ case PPPIOCSACTIVE32:
+ ret = ppp_sock_fprog_ioctl_trans(file, cmd, arg);
+ break;
+
+ case PPPIOCGFLAGS:
+ case PPPIOCSFLAGS:
+ case PPPIOCGASYNCMAP:
+ case PPPIOCSASYNCMAP:
+ case PPPIOCGUNIT:
+ case PPPIOCGRASYNCMAP:
+ case PPPIOCSRASYNCMAP:
+ case PPPIOCGMRU:
+ case PPPIOCSMRU:
+ case PPPIOCSMAXCID:
+ case PPPIOCGXASYNCMAP:
+ case PPPIOCSXASYNCMAP:
+ case PPPIOCXFERUNIT:
+ case PPPIOCGNPMODE:
+ case PPPIOCSNPMODE:
+ case PPPIOCGDEBUG:
+ case PPPIOCSDEBUG:
+ case PPPIOCNEWUNIT:
+ case PPPIOCATTACH:
+ case PPPIOCDETACH:
+ case PPPIOCSMRRU:
+ case PPPIOCCONNECT:
+ case PPPIOCDISCONN:
+ case PPPIOCATTCHAN:
+ case PPPIOCGCHAN:
+ ret = ppp_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ break;
+ }
+ unlock_kernel();
+ return ret;
+}
+#endif
+
static struct file_operations ppp_device_fops = {
.owner = THIS_MODULE,
.read = ppp_read,
.write = ppp_write,
.poll = ppp_poll,
.ioctl = ppp_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ppp_compat_ioctl,
+#endif
.open = ppp_open,
.release = ppp_release
};
Index: linux-2.6.14-rc/net/compat.c
=================================--- linux-2.6.14-rc.orig/net/compat.c 2005-11-05 02:41:28.000000000 +0100
+++ linux-2.6.14-rc/net/compat.c 2005-11-05 02:41:29.000000000 +0100
@@ -1016,126 +1016,6 @@
return ret;
}

-struct sock_fprog32 {
- unsigned short len;
- compat_caddr_t filter;
-};
-
-#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32)
-#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)
-
-static int ppp_sock_fprog_ioctl_trans(struct file *file, unsigned int cmd, unsigned long arg) -{
- struct sock_fprog32 __user *u_fprog32 = compat_ptr(arg);
- struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
- void __user *fptr64;
- u32 fptr32;
- u16 flen;
-
- if (get_user(flen, &u_fprog32->len) ||
- get_user(fptr32, &u_fprog32->filter))
- return -EFAULT;
-
- fptr64 = compat_ptr(fptr32);
-
- if (put_user(flen, &u_fprog64->len) ||
- put_user(fptr64, &u_fprog64->filter))
- return -EFAULT;
-
- if (cmd = PPPIOCSPASS32)
- cmd = PPPIOCSPASS;
- else
- cmd = PPPIOCSACTIVE;
-
- return sock_ioctl(file, cmd, (unsigned long) u_fprog64);
-}
-
-struct ppp_option_data32 {
- compat_caddr_t ptr;
- u32 length;
- compat_int_t transmit;
-};
-#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32)
-
-struct ppp_idle32 {
- compat_time_t xmit_idle;
- compat_time_t recv_idle;
-};
-#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32)
-
-static int ppp_gidle(struct file *file, unsigned int cmd, unsigned long arg) -{
- struct ppp_idle __user *idle;
- struct ppp_idle32 __user *idle32;
- __kernel_time_t xmit, recv;
- int err;
-
- idle = compat_alloc_user_space(sizeof(*idle));
- idle32 = compat_ptr(arg);
-
- err = sock_ioctl(file, PPPIOCGIDLE, (unsigned long) idle);
-
- if (!err) {

-		if (get_user(xmit, &idle->xmit_idle) ||
-		    get_user(recv, &idle->recv_idle) ||

- put_user(xmit, &idle32->xmit_idle) ||
- put_user(recv, &idle32->recv_idle))
- err = -EFAULT;
- }
- return err;
-}
-
-static int ppp_scompress(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct ppp_option_data __user *odata;
- struct ppp_option_data32 __user *odata32;
- __u32 data;
- void __user *datap;
-
- odata = compat_alloc_user_space(sizeof(*odata));
- odata32 = compat_ptr(arg);
-
- if (get_user(data, &odata32->ptr))
- return -EFAULT;
-
- datap = compat_ptr(data);
- if (put_user(datap, &odata->ptr))
- return -EFAULT;
-
- if (copy_in_user(&odata->length, &odata32->length,
- sizeof(__u32) + sizeof(int)))
- return -EFAULT;
-
- return sock_ioctl(file, PPPIOCSCOMPRESS, (unsigned long) odata);
-}
-
-static int ppp_ioctl_trans(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int err;
-
- switch (cmd) {
- case PPPIOCGIDLE32:
- err = ppp_gidle(file, cmd, arg);
- break;
-
- case PPPIOCSCOMPRESS32:
- err = ppp_scompress(file, cmd, arg);
- break;
-
- default:
- do {
- static int count;
- if (++count <= 20)
- printk("ppp_ioctl: Unknown cmd(%08x) arg(%08x)\n",
- (unsigned int)cmd, (unsigned int)arg);
- } while(0);
- err = -EINVAL;
- break;
- };
-
- return err;
-}
-
#ifdef WIRELESS_EXT
struct compat_iw_point {
compat_caddr_t pointer;
@@ -1283,40 +1163,6 @@
/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ INVAL_IOCTL(SIOCRTMSG)
HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
-/* ppp */
-HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
-HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
-COMPATIBLE_IOCTL(PPPIOCGFLAGS)
-COMPATIBLE_IOCTL(PPPIOCSFLAGS)
-COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCGUNIT)
-COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCGMRU)
-COMPATIBLE_IOCTL(PPPIOCSMRU)
-COMPATIBLE_IOCTL(PPPIOCSMAXCID)
-COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
-COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
-/* PPPIOCSCOMPRESS is translated */
-COMPATIBLE_IOCTL(PPPIOCGNPMODE)
-COMPATIBLE_IOCTL(PPPIOCSNPMODE)
-COMPATIBLE_IOCTL(PPPIOCGDEBUG)
-COMPATIBLE_IOCTL(PPPIOCSDEBUG)
-/* PPPIOCSPASS is translated */
-/* PPPIOCSACTIVE is translated */
-/* PPPIOCGIDLE is translated */
-COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
-COMPATIBLE_IOCTL(PPPIOCATTACH)
-COMPATIBLE_IOCTL(PPPIOCDETACH)
-COMPATIBLE_IOCTL(PPPIOCSMRRU)
-COMPATIBLE_IOCTL(PPPIOCCONNECT)
-COMPATIBLE_IOCTL(PPPIOCDISCONN)
-COMPATIBLE_IOCTL(PPPIOCATTCHAN)
-COMPATIBLE_IOCTL(PPPIOCGCHAN)
/* PPPOX */
COMPATIBLE_IOCTL(PPPOEIOCSFWD)
COMPATIBLE_IOCTL(PPPOEIOCDFWD)

--

author maintainer
#8 lore raw

PATCH 6/25 mtd: move ioctl32 code to mtdchar.c

In reply to Arnd Bergmann

The MTD ioctls are all specific to mtdchar.c, so the compat code for them should be there as well.

Also, some of the ioctl commands used in that driver were previously not marked as compatible.

The conversion handlers could be further simplified by not using compat_alloc_user_space any more.

drivers/mtd/mtdchar.c +91 -3
Index: linux-2.6.14-rc/drivers/mtd/mtdchar.c
===================================================================
@@ -6,6 +6,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
@@ -300,8 +301,7 @@
 	wake_up((wait_queue_head_t *)instr->priv);
 }
 
-static int mtd_ioctl(struct inode *inode, struct file *file,
-		     u_int cmd, u_long arg)
+static int mtd_do_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 	struct mtd_info *mtd = TO_MTD(file);
 	void __user *argp = (void __user *)arg;
@@ -626,12 +626,100 @@
 	return ret;
 } /* memory_ioctl */
 
+static long mtd_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	lock_kernel();
+	ret = mtd_do_ioctl(file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
+#ifdef CONFIG_COMPAT
+struct mtd_oob_buf32 {
+	u_int32_t start;
+	u_int32_t length;
+	compat_caddr_t ptr;	/* unsigned char* */
+};
+
+#define MEMWRITEOOB32 	_IOWR('M',3,struct mtd_oob_buf32)
+#define MEMREADOOB32 	_IOWR('M',4,struct mtd_oob_buf32)
+
+static int compat_mtd_rw_oob(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct mtd_oob_buf __user *buf = compat_alloc_user_space(sizeof(*buf));
+	struct mtd_oob_buf32 __user *buf32 = compat_ptr(arg);
+	u32 data;
+	char __user *datap;
+	unsigned int real_cmd;
+	int err;
+
+	real_cmd = (cmd == MEMREADOOB32) ?
+		MEMREADOOB : MEMWRITEOOB;
+
+	if (copy_in_user(&buf->start, &buf32->start,
+			 2 * sizeof(u32)) ||
+	    get_user(data, &buf32->ptr))
+		return -EFAULT;
+	datap = compat_ptr(data);
+	if (put_user(datap, &buf->ptr))
+		return -EFAULT;
+
+	err = mtd_do_ioctl(file, real_cmd, (unsigned long) buf);
+
+	if (!err) {
+		if (copy_in_user(&buf32->start, &buf->start,
+				 2 * sizeof(u32)))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+
+static long compat_mtd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+
+	lock_kernel();
+	switch (cmd) {
+	case MEMWRITEOOB32:
+	case MEMREADOOB32:
+		ret = compat_mtd_rw_oob(file, cmd, arg);
+		break;
+
+	case MEMGETINFO:
+	case MEMERASE:
+	case MEMLOCK:
+	case MEMUNLOCK:
+	case MEMGETREGIONCOUNT:
+	case MEMGETREGIONINFO:
+	case MEMSETOOBSEL:
+	case MEMGETOOBSEL:
+	case MEMGETBADBLOCK:
+	case MEMSETBADBLOCK:
+	case OTPSELECT:
+	case OTPGETREGIONCOUNT:
+	case OTPGETREGIONINFO:
+	case OTPLOCK:
+		ret = mtd_do_ioctl(file, cmd, arg);
+		break;
+	}
+	unlock_kernel();
+
+	return ret;
+}
+#endif
+
 static struct file_operations mtd_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= mtd_lseek,
 	.read		= mtd_read,
 	.write		= mtd_write,
-	.ioctl		= mtd_ioctl,
+	.unlocked_ioctl	= mtd_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= compat_mtd_ioctl,
+#endif
 	.open		= mtd_open,
 	.release	= mtd_close,
 };
fs/compat_ioctl.c +0 -42

54 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -7
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
@@ -656,13 +656,6 @@
 COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
 COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
 COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
-/* MTD */
-COMPATIBLE_IOCTL(MEMGETINFO)
-COMPATIBLE_IOCTL(MEMERASE)
-COMPATIBLE_IOCTL(MEMLOCK)
-COMPATIBLE_IOCTL(MEMUNLOCK)
-COMPATIBLE_IOCTL(MEMGETREGIONCOUNT)
-COMPATIBLE_IOCTL(MEMGETREGIONINFO)
 /* NBD */
 ULONG_IOCTL(NBD_SET_SOCK)
 ULONG_IOCTL(NBD_SET_BLKSIZE)

--

Acked-by on v1 6/25
#9 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 7 lines · Arnd Bergmann

The MTD ioctls are all specific to mtdchar.c, so the compat code for them should be there as well.

Also, some of the ioctl commands used in that driver were previously not marked as compatible.

Quoted 6 lines

The conversion handlers could be further simplified by not using compat_alloc_user_space any more.

Moving crap over to mtdchar.c is a good thing. Complete removal of mtdchar.c might be even better, but at least the crap is relatively self-contained now.

Jörn

Signature · 3 lines
When in doubt, punt.  When somebody actually complains, go back and fix it...
The 90% solution is a good thing.
-- Rob Landley
#10 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 3 lines · Jörn Engel

Moving crap over to mtdchar.c is a good thing. Complete removal of mtdchar.c might be even better, but at least the crap is relatively self-contained now.

Agreed moving the compat_ioctl to mtdchar now that it is possible sounds good.

I can see that argument with respect to mtdblock. But why would removal of mtdchar be a good thing? It is a simple raw access
interface. For those whose flash parts are too small for a filesystem
or when you are doing things that you can't do with a filesystem like making or checking it you need something like mtd char. For embedded folks who don't care you can just compile it out.

Eric

#11 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 9 lines · Eric W. Biederman
Quoted 3 lines · Jörn Engel

Moving crap over to mtdchar.c is a good thing. Complete removal of mtdchar.c might be even better, but at least the crap is relatively self-contained now.

Agreed moving the compat_ioctl to mtdchar now that it is possible sounds good.

Quoted 6 lines

I can see that argument with respect to mtdblock. But why would removal of mtdchar be a good thing? It is a simple raw access
interface. For those whose flash parts are too small for a filesystem
or when you are doing things that you can't do with a filesystem like making or checking it you need something like mtd char. For embedded folks who don't care you can just compile it out.

mtdchar.c is one of the worst drivers inside the kernel. The concept of having a simple char device driver for flash may have its charm, but the actual implementation is horrible. And things like the read-only devices are even unfixable.

mtdblock.c, while being quite a bit more complicated, does not require a ton of ioctls, will not confuse users with minor number 7 actually being device number 3 and magically being read-only despite unix permissions and hardware properties. Plus, it is just a file.

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

Jörn

Signature · 3 lines
A quarrel is quickly settled when deserted by one party; there is
no battle unless there be two.
-- Seneca
#12 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 8 lines · Jörn Engel
Quoted 6 lines · Eric W. Biederman

I can see that argument with respect to mtdblock. But why would removal of mtdchar be a good thing? It is a simple raw access
interface. For those whose flash parts are too small for a filesystem
or when you are doing things that you can't do with a filesystem like making or checking it you need something like mtd char. For embedded folks who don't care you can just compile it out.

Quoted 4 lines

mtdchar.c is one of the worst drivers inside the kernel. The concept of having a simple char device driver for flash may have its charm, but the actual implementation is horrible. And things like the read-only devices are even unfixable.

Sucky implementation isn't a reason for removal. It's a reason to fix sucky implementation.

Quoted 8 lines

mtdblock.c, while being quite a bit more complicated, does not require a ton of ioctls, will not confuse users with minor number 7 actually being device number 3 and magically being read-only despite unix permissions and hardware properties. Plus, it is just a file.

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

It allows users to write an image to a NAND device that has bad blocks and not totally screw it up. This is possible because of those ioctls. The mtdblock stuff knows nothing of this.

I do agree that the read-only devices don't make sense. The code itself probably needs work too. But until someone takes the time to make the mtdblock devices have equivalent functionality, mtdchar needs to stay.

(And mtdblock has it's own set of issues as well. I'd be happy to discuss them, but I think it would be offtopic for this thread.)

josh

#13 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

In reply to Jörn Engel
Quoted 2 lines · Jörn Engel

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

How do you access FLASH specific functionality otherwise ?

case MEMGETINFO:
....
case OTPLOCK:

It may be useless for you, but I doubt that you represent the majority of the MTD user base. Using a RAM simulator is a bit different to the usage of _real_ FLASH.

Look into mtd/utils and figure yourself why it _is_ useful.

The code _is_ ugly and ioctls are out of fashion, but your "remove it" request is just silly as long as you dont provide a reasonable alternative access to those bits.

tglx

#14 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 4 lines · Thomas Gleixner

The code _is_ ugly and ioctls are out of fashion, but your "remove it" request is just silly as long as you dont provide a reasonable alternative access to those bits.

You may have noticed the missing patch and figured that it was not a formal request for removal. Still, I'll be happy when it's gone and am also happy that mtdchar mess is not spread over yet another file anymore. Thanks, Arnd.

Jörn

Signature · 4 lines
Mac is for working, 
Linux is for Networking, 
Windows is for Solitaire! 
-- stolen from dc
#15 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 10 lines · Jörn Engel
Quoted 4 lines · Thomas Gleixner

The code _is_ ugly and ioctls are out of fashion, but your "remove it" request is just silly as long as you dont provide a reasonable alternative access to those bits.

You may have noticed the missing patch and figured that it was not a formal request for removal. Still, I'll be happy when it's gone and am also happy that mtdchar mess is not spread over yet another file anymore. Thanks, Arnd.

I'm deeply impressed by your insight and caring about Linux source code quality. Thanks, Joern.

Complaining about legacy mess is easy blurb. Providing a clean solution is obviously not on your agenda.

tglx

#16 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

In reply to Jörn Engel
Quoted 4 lines · Jörn Engel

mtdblock.c, while being quite a bit more complicated, does not require a ton of ioctls, will not confuse users with minor number 7 actually being device number 3 and magically being read-only despite unix permissions and hardware properties.

MAKEDEV and the documentation and udev ought to be perfectly sufficient to deal with the slight inconvenience caused by the use of minor numbers. The protection afforded by the read-only devices has its uses.

Quoted 2 lines

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

mtdchar allows you to explicitly control erases and per-byte writes. You can't do that with mtdblock. And you might not even want CONFIG_BLK_DEV enabled.

Signature · 1 line
dwmw2
#17 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

In reply to Jörn Engel
Quoted 4 lines · Jörn Engel

mtdchar.c is one of the worst drivers inside the kernel. The concept of having a simple char device driver for flash may have its charm, but the actual implementation is horrible. And things like the read-only devices are even unfixable.

This is a confusing statement, you complain that the implementation is horrible and then go on to complain about the interface to the character device.

The implementation appears small and concise. There are a couple of
FIXMEs but they are all about wishing the interface to the flash chips mapped better to a user space interface. I routinely fix things in the kernel whose implementations are much worse than mtdchar.

Quoted 2 lines

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

I have found just the opposite. It happens to be the only interface
to mtd devices I use. In general when you have flash devices small
enough that you can't use a filesystem without waisting a lot of space (keeping 1 free erase block out of 4 or 8 is a problem). Or when you are doing low-level mucking mtdchar is invaluable.

As for the interface to mtdchar. I agree that the readonly character device is silly, and does weird things to the mtd device minor numbers. I agree that ioctls are not the prettiest interface around, however the raw functionality the ioctls export is needed, and interesting. Some of the functionality would be hard to export even in sysfs the cool ascii replacement for ioctl.

Long term it does look like a sysfs interface to the mtd functionality could suffice.

Eric

#18 lore raw

Re: [PATCH 06/25] mtd: move ioctl32 code to mtdchar.c

Quoted 10 lines · Eric W. Biederman
Quoted 2 lines · Jörn Engel

Can you name a few examples, where mtdchar.c makes sense? I've found it to be quite useless.

I have found just the opposite. It happens to be the only interface
to mtd devices I use. In general when you have flash devices small
enough that you can't use a filesystem without waisting a lot of space (keeping 1 free erase block out of 4 or 8 is a problem). Or when you are doing low-level mucking mtdchar is invaluable.

Josh already convinced me with the Bad Block argument. The hardware already used an OOB scheme to define them. Regular unix files without some sort of OOB data access don't map well to NAND.

Quoted 9 lines

As for the interface to mtdchar. I agree that the readonly character device is silly, and does weird things to the mtd device minor numbers. I agree that ioctls are not the prettiest interface around, however the raw functionality the ioctls export is needed, and interesting. Some of the functionality would be hard to export even in sysfs the cool ascii replacement for ioctl.

Long term it does look like a sysfs interface to the mtd functionality could suffice.

It could. Some time ago I starting coding something up, but got quickly distracted. Might be easier to start from scratch again.

Jörn

Signature · 2 lines
Happiness isn't having what you want, it's wanting what you have.
-- unknown
author maintainer
#19 lore raw

PATCH 7/25 block: move ioctl32 code to drivers/block/ioctl.c

In reply to Arnd Bergmann

Many of the conversion handlers in fs/compat_ioctl.c are specific to block devices, so this patch moves them over to compat_blkdev_ioctl.

This hopefully gives us a slightly more efficient code patch for 32 bit block ioctls, and also enables future cleanups by merging native and compat ioctl implementation.

This patch definitely needs some serious testing.

drivers/block/ioctl.c +539 -1
Index: linux-2.6.14-rc/drivers/block/ioctl.c
===================================================================
@@ -1,8 +1,12 @@
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/sched.h>		/* for capable() */
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
+#include <linux/fd.h>
+#include <linux/hdreg.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
@@ -256,6 +260,438 @@
 	return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+static int w_long(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+
+	set_fs (KERNEL_DS);
+	err = blkdev_ioctl(inode, file, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 __user *)compat_ptr(arg)))
+		return -EFAULT;
+	return err;
+}
+
+static int broken_blkgetsize(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	/* The mkswap binary hard codes it to Intel value :-((( */
+	return w_long(inode, file, BLKGETSIZE, arg);
+}
+
+struct hd_geometry32 {
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	u32 start;
+};
+
+static int compat_hdio_getgeo(struct inode *inode, struct file *file,
+		unsigned int cmd, struct gendisk *disk, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct hd_geometry geo;
+	struct hd_geometry32 __user *ugeo;
+	int err;
+
+	set_fs (KERNEL_DS);
+	err = blkdev_driver_ioctl(inode, file, disk,
+			HDIO_GETGEO, (unsigned long)&geo);
+	set_fs (old_fs);
+	ugeo = compat_ptr(arg);
+	if (!err) {
+		err = copy_to_user (ugeo, &geo, 4);
+		err |= __put_user (geo.start, &ugeo->start);
+	}
+	return err ? -EFAULT : 0;
+}
+
+static int compat_hdio_ioctl(struct inode *inode, struct file *file,
+		struct gendisk *disk, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	unsigned long kval;
+	unsigned int __user *uvp;
+	int error;
+
+	set_fs(KERNEL_DS);
+	error = blkdev_driver_ioctl(inode, file, disk, cmd,
+					(unsigned long)&kval);
+	set_fs(old_fs);
+
+	if (error == 0) {
+		uvp = compat_ptr(arg);
+		if(put_user(kval, uvp))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+struct blkpg_ioctl_arg32 {
+	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, unsigned int cmd,
+				unsigned long arg)
+{
+	struct blkpg_ioctl_arg32 __user *ua32 = compat_ptr(arg);
+	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 blkpg_ioctl(bdev, a);
+}
+
+struct floppy_struct32 {
+	compat_uint_t	size;
+	compat_uint_t	sect;
+	compat_uint_t	head;
+	compat_uint_t	track;
+	compat_uint_t	stretch;
+	unsigned char	gap;
+	unsigned char	rate;
+	unsigned char	spec1;
+	unsigned char	fmt_gap;
+	const compat_caddr_t name;
+};
+
+struct floppy_drive_params32 {
+	char		cmos;
+	compat_ulong_t	max_dtr;
+	compat_ulong_t	hlt;
+	compat_ulong_t	hut;
+	compat_ulong_t	srt;
+	compat_ulong_t	spinup;
+	compat_ulong_t	spindown;
+	unsigned char	spindown_offset;
+	unsigned char	select_delay;
+	unsigned char	rps;
+	unsigned char	tracks;
+	compat_ulong_t	timeout;
+	unsigned char	interleave_sect;
+	struct floppy_max_errors max_errors;
+	char		flags;
+	char		read_track;
+	short		autodetect[8];
+	compat_int_t	checkfreq;
+	compat_int_t	native_format;
+};
+
+struct floppy_drive_struct32 {
+	signed char	flags;
+	compat_ulong_t	spinup_date;
+	compat_ulong_t	select_date;
+	compat_ulong_t	first_read_date;
+	short		probed_format;
+	short		track;
+	short		maxblock;
+	short		maxtrack;
+	compat_int_t	generation;
+	compat_int_t	keep_data;
+	compat_int_t	fd_ref;
+	compat_int_t	fd_device;
+	compat_int_t	last_checked;
+	compat_caddr_t dmabuf;
+	compat_int_t	bufblocks;
+};
+
+struct floppy_fdc_state32 {
+	compat_int_t	spec1;
+	compat_int_t	spec2;
+	compat_int_t	dtr;
+	unsigned char	version;
+	unsigned char	dor;
+	compat_ulong_t	address;
+	unsigned int	rawcmd:2;
+	unsigned int	reset:1;
+	unsigned int	need_configure:1;
+	unsigned int	perp_mode:2;
+	unsigned int	has_fifo:1;
+	unsigned int	driver_version;
+	unsigned char	track[4];
+};
+
+struct floppy_write_errors32 {
+	unsigned int	write_errors;
+	compat_ulong_t	first_error_sector;
+	compat_int_t	first_error_generation;
+	compat_ulong_t	last_error_sector;
+	compat_int_t	last_error_generation;
+	compat_uint_t	badness;
+};
+
+#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
+#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
+#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
+#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
+#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
+#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
+#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
+#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
+#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
+
+static struct {
+	unsigned int	cmd32;
+	unsigned int	cmd;
+} fd_ioctl_trans_table[] = {
+	{ FDSETPRM32, FDSETPRM },
+	{ FDDEFPRM32, FDDEFPRM },
+	{ FDGETPRM32, FDGETPRM },
+	{ FDSETDRVPRM32, FDSETDRVPRM },
+	{ FDGETDRVPRM32, FDGETDRVPRM },
+	{ FDGETDRVSTAT32, FDGETDRVSTAT },
+	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+	{ FDGETFDCSTAT32, FDGETFDCSTAT },
+	{ FDWERRORGET32, FDWERRORGET }
+};
+
+#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
+
+static int compat_fd_ioctl(struct inode *inode, struct file *file,
+		struct gendisk *disk, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	void *karg = NULL;
+	unsigned int kcmd = 0;
+	int i, err;
+
+	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+		if (cmd == fd_ioctl_trans_table[i].cmd32) {
+			kcmd = fd_ioctl_trans_table[i].cmd;
+			break;
+		}
+	if (!kcmd)
+		return -EINVAL;
+
+	switch (cmd) {
+		case FDSETPRM32:
+		case FDDEFPRM32:
+		case FDGETPRM32:
+		{
+			compat_uptr_t name;
+			struct floppy_struct32 __user *uf;
+			struct floppy_struct *f;
+
+			uf = compat_ptr(arg);
+			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETPRM32)
+				break;
+			err = __get_user(f->size, &uf->size);
+			err |= __get_user(f->sect, &uf->sect);
+			err |= __get_user(f->head, &uf->head);
+			err |= __get_user(f->track, &uf->track);
+			err |= __get_user(f->stretch, &uf->stretch);
+			err |= __get_user(f->gap, &uf->gap);
+			err |= __get_user(f->rate, &uf->rate);
+			err |= __get_user(f->spec1, &uf->spec1);
+			err |= __get_user(f->fmt_gap, &uf->fmt_gap);
+			err |= __get_user(name, &uf->name);
+			f->name = compat_ptr(name);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDSETDRVPRM32:
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params32 __user *uf;
+			struct floppy_drive_params *f;
+
+			uf = compat_ptr(arg);
+			f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETDRVPRM32)
+				break;
+			err = __get_user(f->cmos, &uf->cmos);
+			err |= __get_user(f->max_dtr, &uf->max_dtr);
+			err |= __get_user(f->hlt, &uf->hlt);
+			err |= __get_user(f->hut, &uf->hut);
+			err |= __get_user(f->srt, &uf->srt);
+			err |= __get_user(f->spinup, &uf->spinup);
+			err |= __get_user(f->spindown, &uf->spindown);
+			err |= __get_user(f->spindown_offset, &uf->spindown_offset);
+			err |= __get_user(f->select_delay, &uf->select_delay);
+			err |= __get_user(f->rps, &uf->rps);
+			err |= __get_user(f->tracks, &uf->tracks);
+			err |= __get_user(f->timeout, &uf->timeout);
+			err |= __get_user(f->interleave_sect, &uf->interleave_sect);
+			err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
+			err |= __get_user(f->flags, &uf->flags);
+			err |= __get_user(f->read_track, &uf->read_track);
+			err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
+			err |= __get_user(f->checkfreq, &uf->checkfreq);
+			err |= __get_user(f->native_format, &uf->native_format);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+			karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDGETFDCSTAT32:
+			karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDWERRORGET32:
+			karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		default:
+			return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)&karg);
+	set_fs (old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f = karg;
+			struct floppy_struct32 __user *uf = compat_ptr(arg);
+
+			err = __put_user(f->size, &uf->size);
+			err |= __put_user(f->sect, &uf->sect);
+			err |= __put_user(f->head, &uf->head);
+			err |= __put_user(f->track, &uf->track);
+			err |= __put_user(f->stretch, &uf->stretch);
+			err |= __put_user(f->gap, &uf->gap);
+			err |= __put_user(f->rate, &uf->rate);
+			err |= __put_user(f->spec1, &uf->spec1);
+			err |= __put_user(f->fmt_gap, &uf->fmt_gap);
+			err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
+			break;
+		}
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params32 __user *uf;
+			struct floppy_drive_params *f = karg;
+
+			uf = compat_ptr(arg);
+			err = __put_user(f->cmos, &uf->cmos);
+			err |= __put_user(f->max_dtr, &uf->max_dtr);
+			err |= __put_user(f->hlt, &uf->hlt);
+			err |= __put_user(f->hut, &uf->hut);
+			err |= __put_user(f->srt, &uf->srt);
+			err |= __put_user(f->spinup, &uf->spinup);
+			err |= __put_user(f->spindown, &uf->spindown);
+			err |= __put_user(f->spindown_offset, &uf->spindown_offset);
+			err |= __put_user(f->select_delay, &uf->select_delay);
+			err |= __put_user(f->rps, &uf->rps);
+			err |= __put_user(f->tracks, &uf->tracks);
+			err |= __put_user(f->timeout, &uf->timeout);
+			err |= __put_user(f->interleave_sect, &uf->interleave_sect);
+			err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
+			err |= __put_user(f->flags, &uf->flags);
+			err |= __put_user(f->read_track, &uf->read_track);
+			err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
+			err |= __put_user(f->checkfreq, &uf->checkfreq);
+			err |= __put_user(f->native_format, &uf->native_format);
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+		{
+			struct floppy_drive_struct32 __user *uf;
+			struct floppy_drive_struct *f = karg;
+
+			uf = compat_ptr(arg);
+			err = __put_user(f->flags, &uf->flags);
+			err |= __put_user(f->spinup_date, &uf->spinup_date);
+			err |= __put_user(f->select_date, &uf->select_date);
+			err |= __put_user(f->first_read_date, &uf->first_read_date);
+			err |= __put_user(f->probed_format, &uf->probed_format);
+			err |= __put_user(f->track, &uf->track);
+			err |= __put_user(f->maxblock, &uf->maxblock);
+			err |= __put_user(f->maxtrack, &uf->maxtrack);
+			err |= __put_user(f->generation, &uf->generation);
+			err |= __put_user(f->keep_data, &uf->keep_data);
+			err |= __put_user(f->fd_ref, &uf->fd_ref);
+			err |= __put_user(f->fd_device, &uf->fd_device);
+			err |= __put_user(f->last_checked, &uf->last_checked);
+			err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
+			err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
+			break;
+		}
+		case FDGETFDCSTAT32:
+		{
+			struct floppy_fdc_state32 __user *uf;
+			struct floppy_fdc_state *f = karg;
+
+			uf = compat_ptr(arg);
+			err = __put_user(f->spec1, &uf->spec1);
+			err |= __put_user(f->spec2, &uf->spec2);
+			err |= __put_user(f->dtr, &uf->dtr);
+			err |= __put_user(f->version, &uf->version);
+			err |= __put_user(f->dor, &uf->dor);
+			err |= __put_user(f->address, &uf->address);
+			err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
+					   (char *)&f->address + sizeof(f->address), sizeof(int));
+			err |= __put_user(f->driver_version, &uf->driver_version);
+			err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
+			break;
+		}
+		case FDWERRORGET32:
+		{
+			struct floppy_write_errors32 __user *uf;
+			struct floppy_write_errors *f = karg;
+
+			uf = compat_ptr(arg);
+			err = __put_user(f->write_errors, &uf->write_errors);
+			err |= __put_user(f->first_error_sector, &uf->first_error_sector);
+			err |= __put_user(f->first_error_generation, &uf->first_error_generation);
+			err |= __put_user(f->last_error_sector, &uf->last_error_sector);
+			err |= __put_user(f->last_error_generation, &uf->last_error_generation);
+			err |= __put_user(f->badness, &uf->badness);
+			break;
+		}
+		default:
+			break;
+	}
+	if (err)
+		err = -EFAULT;
+
+out:	if (karg) kfree(karg);
+	return err;
+}
+
+
+/* Fix sizeof(sizeof()) breakage */
+#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. */
@@ -263,13 +699,115 @@
 {
 	struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
 	struct gendisk *disk = bdev->bd_disk;
+	struct inode *inode = file->f_mapping->host;
 	int ret = -ENOIOCTLCMD;
-	if (disk->fops->compat_ioctl) {
+
+	switch (cmd) {
+	case BLKRAGET:
+	case BLKGETSIZE:
+	case BLKFRAGET:
+	case BLKSECTGET:
+		ret = w_long(inode, file, cmd, arg);
+		break;
+	case 0x1260:
+		ret = broken_blkgetsize(inode, file, cmd, arg);
+		break;
+	case BLKBSZGET_32:
+		lock_kernel();
+		ret = blkdev_locked_ioctl(file, bdev, BLKBSZGET,
+				(unsigned long)compat_ptr(arg));
+		unlock_kernel();
+		break;
+	case BLKBSZSET_32:
+		lock_kernel();
+		ret = blkdev_locked_ioctl(file, bdev, BLKBSZSET,
+				(unsigned long)compat_ptr(arg));
+		unlock_kernel();
+		break;
+	case BLKGETSIZE64_32:
+		lock_kernel();
+		ret = blkdev_locked_ioctl(file, bdev, BLKGETSIZE64,
+				(unsigned long)compat_ptr(arg));
+		unlock_kernel();
+		break;
+	case BLKROSET:
+	case BLKROGET:
+	case BLKRRPART:
+	case BLKFLSBUF:
+	case BLKSECTSET:
+	case BLKSSZGET:
+	case BLKRASET:
+	case BLKFRASET:
+		ret = blkdev_ioctl(inode, file, cmd, arg);
+		break;
+	case BLKPG:
+		lock_kernel();
+		ret = compat_blkpg_ioctl(bdev, cmd, arg);
+		unlock_kernel();
+		break;
+	case HDIO_GETGEO:
+		ret = compat_hdio_getgeo(inode, file, cmd, disk, arg);
+		break;
+	case HDIO_GET_KEEPSETTINGS:
+	case HDIO_GET_UNMASKINTR:
+	case HDIO_GET_DMA:
+	case HDIO_GET_32BIT:
+	case HDIO_GET_MULTCOUNT:
+	case HDIO_GET_NOWERR:
+	case HDIO_GET_NICE:
+		ret = compat_hdio_ioctl(inode, file, disk, cmd, arg);
+		break;
+	case HDIO_GET_IDENTITY:
+	case HDIO_SET_DMA:
+	case HDIO_SET_UNMASKINTR:
+	case HDIO_SET_NOWERR:
+	case HDIO_SET_32BIT:
+	case HDIO_SET_MULTCOUNT:
+	case HDIO_DRIVE_CMD:
+	case HDIO_DRIVE_TASK:
+	case HDIO_SET_PIO_MODE:
+	case HDIO_SET_NICE:
+		ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+		break;
+	case FDSETPRM32:
+	case FDDEFPRM32:
+	case FDGETPRM32:
+	case FDSETDRVPRM32:
+	case FDGETDRVPRM32:
+	case FDGETDRVSTAT32:
+	case FDPOLLDRVSTAT32:
+	case FDGETFDCSTAT32:
+	case FDWERRORGET32:
+		ret = compat_fd_ioctl(inode, file, disk, cmd, arg);
+		break;
+	case FDMSGON:
+	case FDMSGOFF:
+	case FDSETEMSGTRESH:
+	case FDFLUSH:
+	case FDWERRORCLR:
+	case FDSETMAXERRS:
+	case FDGETMAXERRS:
+	case FDGETDRVTYP:
+	case FDEJECT:
+	case FDCLRPRM:
+	case FDFMTBEG:
+	case FDFMTEND:
+	case FDRESET:
+	case FDTWADDLE:
+	case FDFMTTRK:
+	case FDRAWCMD:
+		ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+		break;
+	}
+
+	if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) {
 		lock_kernel();
 		ret = disk->fops->compat_ioctl(file, cmd, arg);
 		unlock_kernel();
 	}
+
 	return ret;
 }
+#endif
 
 EXPORT_SYMBOL_GPL(blkdev_ioctl);
fs/compat_ioctl.c +0 -452

496 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -39
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
@@ -68,45 +68,6 @@
 /* 0x00 */
 COMPATIBLE_IOCTL(FIBMAP)
 COMPATIBLE_IOCTL(FIGETBSZ)
-/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
- *         Some need translations, these do not.
- */
-COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
-COMPATIBLE_IOCTL(HDIO_SET_DMA)
-COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR)
-COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
-COMPATIBLE_IOCTL(HDIO_SET_32BIT)
-COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
-COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
-COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
-COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
-COMPATIBLE_IOCTL(HDIO_SET_NICE)
-/* 0x02 -- Floppy ioctls */
-COMPATIBLE_IOCTL(FDMSGON)
-COMPATIBLE_IOCTL(FDMSGOFF)
-COMPATIBLE_IOCTL(FDSETEMSGTRESH)
-COMPATIBLE_IOCTL(FDFLUSH)
-COMPATIBLE_IOCTL(FDWERRORCLR)
-COMPATIBLE_IOCTL(FDSETMAXERRS)
-COMPATIBLE_IOCTL(FDGETMAXERRS)
-COMPATIBLE_IOCTL(FDGETDRVTYP)
-COMPATIBLE_IOCTL(FDEJECT)
-COMPATIBLE_IOCTL(FDCLRPRM)
-COMPATIBLE_IOCTL(FDFMTBEG)
-COMPATIBLE_IOCTL(FDFMTEND)
-COMPATIBLE_IOCTL(FDRESET)
-COMPATIBLE_IOCTL(FDTWADDLE)
-COMPATIBLE_IOCTL(FDFMTTRK)
-COMPATIBLE_IOCTL(FDRAWCMD)
-/* 0x12 */
-COMPATIBLE_IOCTL(BLKROSET)
-COMPATIBLE_IOCTL(BLKROGET)
-COMPATIBLE_IOCTL(BLKRRPART)
-COMPATIBLE_IOCTL(BLKFLSBUF)
-COMPATIBLE_IOCTL(BLKSECTSET)
-COMPATIBLE_IOCTL(BLKSSZGET)
-ULONG_IOCTL(BLKRASET)
-ULONG_IOCTL(BLKFRASET)
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
 COMPATIBLE_IOCTL(GET_ARRAY_INFO)

--

author maintainer
#20 lore raw

PATCH 8/25 tty: move ioctl32 code over to vt_ioctl.c and tty_io.c

In reply to Arnd Bergmann

This patch introduces line discipline specific and tty device specific compat_ioctl callbacks as well as moving over all generic tty ioctl and vt ioctl conversion handlers over to the local files that are already responsible for the native ioctls.

drivers/char/vt.c +3 -0
Index: linux-2.6.14-rc/drivers/char/vt.c
===================================================================
@@ -2614,6 +2614,9 @@
 	.flush_chars = con_flush_chars,
 	.chars_in_buffer = con_chars_in_buffer,
 	.ioctl = vt_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = vt_compat_ioctl,
+#endif
 	.stop = con_stop,
 	.start = con_start,
 	.throttle = con_throttle,
drivers/char/vt_ioctl.c +195 -0

204 lines not on this page · raw message

fs/compat_ioctl.c +0 -147

159 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -79

104 lines not on this page · raw message

include/linux/tty.h +2 -0
Index: linux-2.6.14-rc/include/linux/tty.h
===================================================================
@@ -404,6 +404,8 @@
 
 extern int vt_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+extern int vt_compat_ioctl(struct tty_struct *tty, struct file * file,
+			   unsigned int cmd, unsigned long arg);
 
 static inline dev_t tty_devnum(struct tty_struct *tty)
 {
include/linux/tty_driver.h +4 -0
Index: linux-2.6.14-rc/include/linux/tty_driver.h
===================================================================
@@ -132,6 +132,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	int  (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+			unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct termios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
@@ -194,6 +196,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	int  (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct termios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
drivers/char/tty_io.c +108 -2

164 lines not on this page · raw message

include/linux/tty_ldisc.h +2 -0
Index: linux-2.6.14-rc/include/linux/tty_ldisc.h
===================================================================
@@ -126,6 +126,8 @@
 			 const unsigned char * buf, size_t nr);	
 	int	(*ioctl)(struct tty_struct * tty, struct file * file,
 			 unsigned int cmd, unsigned long arg);
+	int	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
+			 unsigned int cmd, unsigned long arg);
 	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
drivers/char/n_tty.c +1 -0
Index: linux-2.6.14-rc/drivers/char/n_tty.c
===================================================================
@@ -1549,6 +1549,7 @@
 	read_chan,		/* read */
 	write_chan,		/* write */
 	n_tty_ioctl,		/* ioctl */
+	NULL,			/* compat_ioctl */
 	n_tty_set_termios,	/* set_termios */
 	normal_poll,		/* poll */
 	NULL,			/* hangup */

--

author maintainer
#21 lore raw

PATCH 9/25 v4l: move ioctl32 handlers to drivers/media/

In reply to Arnd Bergmann

This moves the 32 bit ioctl compatibility handlers for Video4Linux into a new file and adds explicit calls to them to each v4l device driver.

Unfortunately, there does not seem to be any code handling the v4l2 ioctls, so quite often the code goes through two separate conversions, first from 32 bit v4l to 64 bit v4l, and from there to 64 bit v4l2. My patch does not change that, so there is still much room for improvement.

Also, some drivers have additional ioctl numbers, for which the conversion should be handled internally to that driver.

drivers/media/radio/miropcm20-radio.c +1 -0
Index: linux-cg/drivers/media/radio/miropcm20-radio.c
===================================================================
@@ -220,6 +220,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= pcm20_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-aimslab.c +1 -0
Index: linux-cg/drivers/media/radio/radio-aimslab.c
===================================================================
@@ -299,6 +299,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl	        = rt_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-aztech.c +1 -0
Index: linux-cg/drivers/media/radio/radio-aztech.c
===================================================================
@@ -256,6 +256,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= az_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-cadet.c +1 -0
Index: linux-cg/drivers/media/radio/radio-cadet.c
===================================================================
@@ -490,6 +490,7 @@
 	.release       	= cadet_release,
 	.read		= cadet_read,
 	.ioctl		= cadet_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-gemtek-pci.c +1 -0
Index: linux-cg/drivers/media/radio/radio-gemtek-pci.c
===================================================================
@@ -301,6 +301,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= gemtek_pci_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-gemtek.c +1 -0
Index: linux-cg/drivers/media/radio/radio-gemtek.c
===================================================================
@@ -233,6 +233,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= gemtek_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-maestro.c +1 -0
Index: linux-cg/drivers/media/radio/radio-maestro.c
===================================================================
@@ -72,6 +72,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= radio_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-maxiradio.c +1 -0
Index: linux-cg/drivers/media/radio/radio-maxiradio.c
===================================================================
@@ -80,6 +80,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl	        = radio_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 static struct video_device maxiradio_radio =
drivers/media/radio/radio-rtrack2.c +1 -0
Index: linux-cg/drivers/media/radio/radio-rtrack2.c
===================================================================
@@ -199,6 +199,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= rt_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-sf16fmi.c +1 -0
Index: linux-cg/drivers/media/radio/radio-sf16fmi.c
===================================================================
@@ -225,6 +225,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= fmi_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-sf16fmr2.c +1 -0
Index: linux-cg/drivers/media/radio/radio-sf16fmr2.c
===================================================================
@@ -356,6 +356,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl          = fmr2_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-terratec.c +1 -0
Index: linux-cg/drivers/media/radio/radio-terratec.c
===================================================================
@@ -276,6 +276,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= tt_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-trust.c +1 -0
Index: linux-cg/drivers/media/radio/radio-trust.c
===================================================================
@@ -255,6 +255,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= tr_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-typhoon.c +1 -0
Index: linux-cg/drivers/media/radio/radio-typhoon.c
===================================================================
@@ -261,6 +261,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= typhoon_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/radio/radio-zoltrix.c +1 -0
Index: linux-cg/drivers/media/radio/radio-zoltrix.c
===================================================================
@@ -313,6 +313,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl		= zol_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/video/Makefile +1 -1
Index: linux-cg/drivers/media/video/Makefile
===================================================================
@@ -9,7 +9,7 @@
 zr36067-objs	:=	zoran_procfs.o zoran_device.o \
 			zoran_driver.o zoran_card.o
 tuner-objs	:=	tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl.o
 
 obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
 	tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o
drivers/media/video/arv.c +1 -0
Index: linux-cg/drivers/media/video/arv.c
===================================================================
@@ -750,6 +750,7 @@
 	.release	= video_exclusive_release,
 	.read		= ar_read,
 	.ioctl		= ar_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek		= no_llseek,
 };
 
drivers/media/video/bttv-driver.c +1 -0
Index: linux-cg/drivers/media/video/bttv-driver.c
===================================================================
@@ -3083,6 +3083,7 @@
 	.open	  = bttv_open,
 	.release  = bttv_release,
 	.ioctl	  = bttv_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek	  = no_llseek,
 	.read	  = bttv_read,
 	.mmap	  = bttv_mmap,
drivers/media/video/bw-qcam.c +1 -0
Index: linux-cg/drivers/media/video/bw-qcam.c
===================================================================
@@ -875,6 +875,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl          = qcam_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.read		= qcam_read,
 	.llseek         = no_llseek,
 };
drivers/media/video/c-qcam.c +1 -0
Index: linux-cg/drivers/media/video/c-qcam.c
===================================================================
@@ -687,6 +687,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl          = qcam_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.read		= qcam_read,
 	.llseek         = no_llseek,
 };
drivers/media/video/compat_ioctl.c new file +318 -0

318 lines not on this page · raw message

drivers/media/video/cpia.c +1 -0
Index: linux-cg/drivers/media/video/cpia.c
===================================================================
@@ -3807,6 +3807,7 @@
 	.read		= cpia_read,
 	.mmap		= cpia_mmap,
 	.ioctl          = cpia_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
drivers/media/video/cx88/cx88-video.c +2 -0
Index: linux-cg/drivers/media/video/cx88/cx88-video.c
===================================================================
@@ -1736,6 +1736,7 @@
 	.poll          = video_poll,
 	.mmap	       = video_mmap,
 	.ioctl	       = video_ioctl,
+	.compat_ioctl  = v4l_compat_ioctl,
 	.llseek        = no_llseek,
 };
 
@@ -1763,6 +1764,7 @@
 	.open          = video_open,
 	.release       = video_release,
 	.ioctl         = radio_ioctl,
+	.compat_ioctl  = v4l_compat_ioctl,
 	.llseek        = no_llseek,
 };
 
drivers/media/video/meye.c +1 -0
Index: linux-cg/drivers/media/video/meye.c
===================================================================
@@ -1754,6 +1754,7 @@
 	.release	= meye_release,
 	.mmap		= meye_mmap,
 	.ioctl		= meye_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.poll		= meye_poll,
 	.llseek		= no_llseek,
 };
drivers/media/video/pms.c +1 -0
Index: linux-cg/drivers/media/video/pms.c
===================================================================
@@ -883,6 +883,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl          = pms_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.read           = pms_read,
 	.llseek         = no_llseek,
 };
drivers/media/video/saa7134/saa7134-video.c +2 -0
Index: linux-cg/drivers/media/video/saa7134/saa7134-video.c
===================================================================
@@ -2214,6 +2214,7 @@
 	.poll     = video_poll,
 	.mmap	  = video_mmap,
 	.ioctl	  = video_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek   = no_llseek,
 };
 
@@ -2223,6 +2224,7 @@
 	.open	  = video_open,
 	.release  = video_release,
 	.ioctl	  = radio_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek   = no_llseek,
 };
 
drivers/media/video/stradis.c +1 -0
Index: linux-cg/drivers/media/video/stradis.c
===================================================================
@@ -1974,6 +1974,7 @@
 	.open		= saa_open,
 	.release	= saa_release,
 	.ioctl		= saa_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.read		= saa_read,
 	.llseek		= no_llseek,
 	.write		= saa_write,
drivers/media/video/w9966.c +1 -0
Index: linux-cg/drivers/media/video/w9966.c
===================================================================
@@ -187,6 +187,7 @@
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
 	.ioctl          = w9966_v4l_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.read           = w9966_v4l_read,
 	.llseek         = no_llseek,
 };
drivers/media/video/zoran_driver.c +1 -0
Index: linux-cg/drivers/media/video/zoran_driver.c
===================================================================
@@ -4678,6 +4678,7 @@
 	.open = zoran_open,
 	.release = zoran_close,
 	.ioctl = zoran_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek = no_llseek,
 	.read = zoran_read,
 	.write = zoran_write,
drivers/media/video/zr36120.c +1 -0
Index: linux-cg/drivers/media/video/zr36120.c
===================================================================
@@ -1490,6 +1490,7 @@
 	.write		= zoran_write,
 	.poll		= zoran_poll,
 	.ioctl		= zoran_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.mmap		= zoran_mmap,
 	.minor		= -1,
 };
drivers/usb/media/dsbr100.c +1 -0
Index: linux-cg/drivers/usb/media/dsbr100.c
===================================================================
@@ -127,6 +127,7 @@
 	.open =		usb_dsbr100_open,
 	.release =     	usb_dsbr100_close,
 	.ioctl =        usb_dsbr100_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek =       no_llseek,
 };
 
drivers/usb/media/ov511.c +1 -0
Index: linux-cg/drivers/usb/media/ov511.c
===================================================================
@@ -4774,6 +4774,7 @@
 	.read =		ov51x_v4l1_read,
 	.mmap =		ov51x_v4l1_mmap,
 	.ioctl =	ov51x_v4l1_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek =	no_llseek,
 };
 
drivers/usb/media/pwc/pwc-if.c +1 -0
Index: linux-cg/drivers/usb/media/pwc/pwc-if.c
===================================================================
@@ -154,6 +154,7 @@
 	.poll =		pwc_video_poll,
 	.mmap =		pwc_video_mmap,
 	.ioctl =        pwc_video_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
drivers/usb/media/se401.c +1 -0
Index: linux-cg/drivers/usb/media/se401.c
===================================================================
@@ -1193,6 +1193,7 @@
         .read =         se401_read,
         .mmap =         se401_mmap,
 	.ioctl =        se401_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek =       no_llseek,
 };
 static struct video_device se401_template = {
drivers/usb/media/stv680.c +1 -0
Index: linux-cg/drivers/usb/media/stv680.c
===================================================================
@@ -1343,6 +1343,7 @@
 	.read =		stv680_read,
 	.mmap =		stv680_mmap,
 	.ioctl =        stv680_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek =       no_llseek,
 };
 static struct video_device stv680_template = {
drivers/usb/media/usbvideo.c +1 -0
Index: linux-cg/drivers/usb/media/usbvideo.c
===================================================================
@@ -953,6 +953,7 @@
 	.read =   usbvideo_v4l_read,
 	.mmap =   usbvideo_v4l_mmap,
 	.ioctl =  usbvideo_v4l_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.llseek = no_llseek,
 };
 static struct video_device usbvideo_template = {
drivers/usb/media/vicam.c +1 -0
Index: linux-cg/drivers/usb/media/vicam.c
===================================================================
@@ -1236,6 +1236,7 @@
 	.read		= vicam_read,
 	.mmap		= vicam_mmap,
 	.ioctl		= vicam_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek		= no_llseek,
 };
 
drivers/usb/media/w9968cf.c +1 -0
Index: linux-cg/drivers/usb/media/w9968cf.c
===================================================================
@@ -3491,6 +3491,7 @@
 	.release = w9968cf_release,
 	.read =    w9968cf_read,
 	.ioctl =   w9968cf_ioctl,
+	.compat_ioctl = v4l_compat_ioctl,
 	.mmap =    w9968cf_mmap,
 	.llseek =  no_llseek,
 };
drivers/media/video/saa5249.c +1 -0
Index: linux-cg/drivers/media/video/saa5249.c
===================================================================
@@ -709,6 +709,7 @@
 	.open		= saa5249_open,
 	.release       	= saa5249_release,
 	.ioctl          = saa5249_ioctl,
+	.compat_ioctl	= v4l_compat_ioctl,
 	.llseek         = no_llseek,
 };
 
fs/compat_ioctl.c +0 -246

258 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -26
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -100,32 +100,6 @@
 COMPATIBLE_IOCTL(TUNSETDEBUG)
 COMPATIBLE_IOCTL(TUNSETPERSIST)
 COMPATIBLE_IOCTL(TUNSETOWNER)
-/* Little v */
-/* Little v, the video4linux ioctls (conflict?) */
-COMPATIBLE_IOCTL(VIDIOCGCAP)
-COMPATIBLE_IOCTL(VIDIOCGCHAN)
-COMPATIBLE_IOCTL(VIDIOCSCHAN)
-COMPATIBLE_IOCTL(VIDIOCGPICT)
-COMPATIBLE_IOCTL(VIDIOCSPICT)
-COMPATIBLE_IOCTL(VIDIOCCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCKEY)
-COMPATIBLE_IOCTL(VIDIOCGAUDIO)
-COMPATIBLE_IOCTL(VIDIOCSAUDIO)
-COMPATIBLE_IOCTL(VIDIOCSYNC)
-COMPATIBLE_IOCTL(VIDIOCMCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCGMBUF)
-COMPATIBLE_IOCTL(VIDIOCGUNIT)
-COMPATIBLE_IOCTL(VIDIOCGCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCSCAPTURE)
-/* BTTV specific... */
-COMPATIBLE_IOCTL(_IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]))
-COMPATIBLE_IOCTL(_IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int))
-COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int))
 /* Little p (/dev/rtc, /dev/envctrl, etc.) */
 COMPATIBLE_IOCTL(RTC_AIE_ON)
 COMPATIBLE_IOCTL(RTC_AIE_OFF)
include/linux/videodev.h +2 -0
Index: linux-cg/include/linux/videodev.h
===================================================================
@@ -90,6 +90,8 @@
 			  unsigned int cmd, unsigned long arg,
 			  int (*func)(struct inode *inode, struct file *file,
 				      unsigned int cmd, void *arg));
+extern long v4l_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg);
 #endif /* __KERNEL__ */
 
 #define VID_TYPE_CAPTURE	1	/* Can capture */

--

#22 lore raw

Re: [PATCH 09/25] v4l: move ioctl32 handlers to drivers/media/

Arnd,

Em Sáb, 2005-11-05 às 17:26 +0100, Arnd Bergmann escreveu:

Quoted 4 lines

anexo Documento somente texto (compat_vidio.diff) This moves the 32 bit ioctl compatibility handlers for Video4Linux into a new file and adds explicit calls to them to each v4l device driver.

Thanks for your patch, but IMHO, it should't be applied on mainstream.
It would be better if we apply it on V4L tree and do some work on it to improve handling the compat stuff.

Quoted 6 lines

Unfortunately, there does not seem to be any code handling the v4l2 ioctls, so quite often the code goes through two separate conversions, first from 32 bit v4l to 64 bit v4l, and from there to 64 bit v4l2. My patch does not change that, so there is still much room for improvement.

As you mentioned, some changes would be required to make it more
robust. Also, we are introducing some newer devices that would require also conversion (already on -mm tree).
On the other hand, compat_ioctl.c is not a good name, since there is
v4l1-compat.c, meant to handle compat ioctl between the old API and the newer one.

Quoted 4 lines

Also, some drivers have additional ioctl numbers, for which the conversion should be handled internally to that driver.

This is an interesting question: current version only handles V4L1
ioctls:

+#define VIDIOCGTUNER32         _IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32         _IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32           _IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32           _IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32          _IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32          _IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32          _IOR('v',14, u32)
+#define VIDIOCSFREQ32          _IOW('v',15, u32)

+
The intention is to depreciate V4L1 old api (from 2.4 series), in favor
of V4L2 API. The old API have several issues and doesn't support some video standards variations used on several countries.

Newer drivers (em28xx, cx88, saa7134), used by the modern boards don't
directly implement the old API anymore. All calls are directed to v4l1-compat, that translates into V4L2 calls. We are also testing some patches to use this way also for bttv drivers. The intention is to make v4l1 obsolete and remove from kernel, maybe for 2.6.18 or 2.6.20.

We should seriously check this patch, to see if it does make sense with
current implemented ioctls.

Quoted 4 lines

Cheers,
Mauro.

author maintainer
#23 lore raw

Re: [PATCH 09/25] v4l: move ioctl32 handlers to drivers/media/

Quoted 9 lines · Mauro Carvalho Chehab

Em Sáb, 2005-11-05 às 17:26 +0100, Arnd Bergmann escreveu:

Quoted 4 lines

anexo Documento somente texto (compat_vidio.diff) This moves the 32 bit ioctl compatibility handlers for Video4Linux into a new file and adds explicit calls to them to each v4l device driver.

Thanks for your patch, but IMHO, it should't be applied on mainstream.
It would be better if we apply it on V4L tree and do some work on it to improve handling the compat stuff.

Sure, that sounds reasonable.

Quoted 11 lines
Quoted 5 lines

Unfortunately, there does not seem to be any code handling the v4l2 ioctls, so quite often the code goes through two separate conversions, first from 32 bit v4l to 64 bit v4l, and from there to 64 bit v4l2. My patch does not change that, so there is still much room for improvement.

As you mentioned, some changes would be required to make it more
robust. Also, we are introducing some newer devices that would require also conversion (already on -mm tree).
On the other hand, compat_ioctl.c is not a good name, since there is
v4l1-compat.c, meant to handle compat ioctl between the old API and the newer one.

Yes, I noticed that. The problem is that compat_ioctl is the conventional name for 32 bit compatibility ioctl handlers in many other places, so is was already confusing before my patch.

Maybe it makes sense to name the new file ioctl32 instead, as that is also used in other places.

Quoted 16 lines
Quoted 3 lines

Also, some drivers have additional ioctl numbers, for which the conversion should be handled internally to that driver.

This is an interesting question: current version only handles V4L1
ioctls:

drivers/media/video/compat_ioctl.c new file +9 -0
+#define VIDIOCGTUNER32         _IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32         _IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32           _IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32           _IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32          _IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32          _IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32          _IOR('v',14, u32)
+#define VIDIOCSFREQ32          _IOW('v',15, u32)
+
Quoted 3 lines

The intention is to depreciate V4L1 old api (from 2.4 series), in favor
of V4L2 API. The old API have several issues and doesn't support some video standards variations used on several countries.

You should really do that only after the V4L2 ioctl32 conversion has been added. I'm personally watching TV going through both ioctl conversion layers (xawtv finds 32 bit V4L2 is not implemented, falls back to 32 bit V4L1, that is converted in the kernel to 64 bit V4L1 and then to 64 bit V4L2 when it reaches the driver).

Quoted 8 lines

Newer drivers (em28xx, cx88, saa7134), used by the modern boards don't
directly implement the old API anymore. All calls are directed to v4l1-compat, that translates into V4L2 calls. We are also testing some patches to use this way also for bttv drivers. The intention is to make v4l1 obsolete and remove from kernel, maybe for 2.6.18 or 2.6.20.

We should seriously check this patch, to see if it does make sense with
current implemented ioctls.

Note that my patch does not change any behavior relative to 2.6.14 vanilla, it just moves the conversion handlers to a different place.

	Arnd <><
#24 lore raw

Re: [PATCH 09/25] v4l: move ioctl32 handlers to drivers/media/

Arnd,

We've applied on V4L CVS. There are some fixes for it to work as
expected. We are currently working on it. I intend to submit all stuff after the fixes.

Cheers,
Mauro.

Em Seg, 2005-11-07 às 11:17 +0100, Arnd Bergmann escreveu:

Quoted 13 lines · Mauro Carvalho Chehab
Quoted 9 lines

Em Sáb, 2005-11-05 às 17:26 +0100, Arnd Bergmann escreveu:

Quoted 4 lines

anexo Documento somente texto (compat_vidio.diff) This moves the 32 bit ioctl compatibility handlers for Video4Linux into a new file and adds explicit calls to them to each v4l device driver.

Thanks for your patch, but IMHO, it should't be applied on mainstream.
It would be better if we apply it on V4L tree and do some work on it to improve handling the compat stuff.

Sure, that sounds reasonable.

author maintainer
#25 lore raw

PATCH 10/25 fs: move ext2 ioctl32 handlers into file systems

In reply to Arnd Bergmann

The same ioctls (originally from ext2) are used on ext2, ext3, hfsplus, cifs, reiserfs and xfs. Since they are really compatible between 32 and 64 bit except for the ioctl number, the conversion handler is trivial and I copy it to each of these file systems in order to eventually get rid of fs/compat_ioctl.c completely.

Ext3 and reiserfs actually have some more ioctl numbers that have the same problem as the others, so I'm adding the conversion for those in the same place.

XFS already handled these ioctl numbers in its existing ioctl32 code, but appeared to get it wrong.

fs/compat_ioctl.c +0 -22
Index: linux-cg/fs/compat_ioctl.c
===================================================================
@@ -126,12 +126,6 @@
 
 #ifdef CODE
 
-/* Aiee. Someone does not find a difference between int and long */
-#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
-#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
-#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
-#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
-
 static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
@@ -163,18 +157,6 @@
 	return err;
 }
 
-static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	/* These are just misnamed, they actually get/put from/to user an int */
-	switch (cmd) {
-	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
-	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
-	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
-	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
-	}
-	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
-}
-
 struct fb_fix_screeninfo32 {
 	char			id[16];
         compat_caddr_t	smem_start;
@@ -1313,10 +1295,6 @@
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
 #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
 HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
-HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
-HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
 /* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
 HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
fs/ext2/ioctl.c +31 -0
Index: linux-cg/fs/ext2/ioctl.c
===================================================================
@@ -10,6 +10,7 @@
 #include "ext2.h"
 #include <linux/time.h>
 #include <linux/sched.h>
+#include <linux/compat.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
@@ -79,3 +80,33 @@
 		return -ENOTTY;
 	}
 }
+
+#ifdef CONFIG_COMPAT
+long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS:
+		cmd = EXT2_IOC_GETFLAGS;
+		break;
+	case EXT2_IOC32_SETFLAGS:
+		cmd = EXT2_IOC_SETFLAGS;
+		break;
+	case EXT2_IOC32_GETVERSION:
+		cmd = EXT2_IOC_GETVERSION;
+		break;
+	case EXT2_IOC32_SETVERSION:
+		cmd = EXT2_IOC_SETVERSION;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	lock_kernel();
+	ret = ext2_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+	unlock_kernel();
+	return ret;
+}
+#endif
fs/ext3/ioctl.c +65 -1

77 lines not on this page · raw message

fs/ext2/dir.c +3 -0
Index: linux-cg/fs/ext2/dir.c
===================================================================
@@ -669,5 +669,8 @@
 	.read		= generic_read_dir,
 	.readdir	= ext2_readdir,
 	.ioctl		= ext2_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext2_compat_ioctl,
+#endif
 	.fsync		= ext2_sync_file,
 };
fs/ext2/file.c +6 -0
Index: linux-cg/fs/ext2/file.c
===================================================================
@@ -46,6 +46,9 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.ioctl		= ext2_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext2_compat_ioctl,
+#endif
 	.mmap		= generic_file_mmap,
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
@@ -61,6 +64,9 @@
 	.read		= xip_file_read,
 	.write		= xip_file_write,
 	.ioctl		= ext2_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext2_compat_ioctl,
+#endif
 	.mmap		= xip_file_mmap,
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
fs/ext3/dir.c +3 -0
Index: linux-cg/fs/ext3/dir.c
===================================================================
@@ -44,6 +44,9 @@
 	.read		= generic_read_dir,
 	.readdir	= ext3_readdir,		/* we take BKL. needed?*/
 	.ioctl		= ext3_ioctl,		/* BKL held */
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext3_compat_ioctl,
+#endif
 	.fsync		= ext3_sync_file,	/* BKL held */
 #ifdef CONFIG_EXT3_INDEX
 	.release	= ext3_release_dir,
fs/ext3/file.c +3 -0
Index: linux-cg/fs/ext3/file.c
===================================================================
@@ -114,6 +114,9 @@
 	.readv		= generic_file_readv,
 	.writev		= generic_file_writev,
 	.ioctl		= ext3_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ext3_compat_ioctl,
+#endif
 	.mmap		= generic_file_mmap,
 	.open		= generic_file_open,
 	.release	= ext3_release_file,
fs/xfs/linux-2.6/xfs_ioctl32.c +12 -3
Index: linux-cg/fs/xfs/linux-2.6/xfs_ioctl32.c
===================================================================
@@ -34,6 +34,11 @@
 #define  _NATIVE_IOC(cmd, type) \
 	  _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
 
+/* broken ext2 ioctl numbers */
+#define XFS_IOC_GETVERSION32 _IOR('v', 1, int)
+#define XFS_IOC_GETXFLAGS32 _IOR('f', 1, int)
+#define XFS_IOC_SETXFLAGS32 _IOW('f', 2, int)
+
 #if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
 #define BROKEN_X86_ALIGNMENT
 /* on ia32 l_start is on a 32-bit boundary */
@@ -115,12 +120,16 @@
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 
 	switch (cmd) {
+	/* these take an int as their argument, not a long */
+	case XFS_IOC_GETVERSION32:
+	case XFS_IOC_GETXFLAGS32:
+	case XFS_IOC_SETXFLAGS32:
+		cmd = _NATIVE_IOC(cmd, long);
+		break;
+
 	case XFS_IOC_DIOINFO:
 	case XFS_IOC_FSGEOMETRY_V1:
 	case XFS_IOC_FSGEOMETRY:
-	case XFS_IOC_GETVERSION:
-	case XFS_IOC_GETXFLAGS:
-	case XFS_IOC_SETXFLAGS:
 	case XFS_IOC_FSGETXATTR:
 	case XFS_IOC_FSSETXATTR:
 	case XFS_IOC_FSGETXATTRA:
fs/cifs/ioctl.c +28 -1
Index: linux-cg/fs/cifs/ioctl.c
===================================================================
@@ -21,6 +21,8 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
 #include "cifspdu.h"
@@ -109,4 +111,29 @@
 
 	FreeXid(xid);
 	return rc;
-} 
+}
+
+#ifdef CONFIG_COMPAT
+long cifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS:
+		cmd = EXT2_IOC_GETFLAGS;
+		break;
+	case EXT2_IOC32_SETFLAGS:
+		cmd = EXT2_IOC_SETFLAGS;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	lock_kernel();
+	ret = cifs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+	unlock_kernel();
+	return ret;
+}
+
+#endif
fs/hfsplus/dir.c +4 -0
Index: linux-cg/fs/hfsplus/dir.c
===================================================================
@@ -8,6 +8,7 @@
  * Handling of directories
  */
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
@@ -479,6 +480,9 @@
 	.read		= generic_read_dir,
 	.readdir	= hfsplus_readdir,
 	.ioctl          = hfsplus_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= hfsplus_compat_ioctl,
+#endif
 	.llseek		= generic_file_llseek,
 	.release	= hfsplus_dir_release,
 };
fs/hfsplus/hfsplus_fs.h +4 -0
Index: linux-cg/fs/hfsplus/hfsplus_fs.h
===================================================================
@@ -249,6 +249,8 @@
  * chattr/lsattr */
 #define HFSPLUS_IOC_EXT2_GETFLAGS	_IOR('f', 1, long)
 #define HFSPLUS_IOC_EXT2_SETFLAGS	_IOW('f', 2, long)
+#define HFSPLUS_IOC_EXT2_GETFLAGS32	_IOR('f', 1, int)
+#define HFSPLUS_IOC_EXT2_SETFLAGS32	_IOW('f', 2, int)
 
 #define EXT2_FLAG_IMMUTABLE		0x00000010 /* Immutable file */
 #define EXT2_FLAG_APPEND		0x00000020 /* writes to file may only append */
@@ -336,6 +338,8 @@
 /* ioctl.c */
 int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 		  unsigned long arg);
+long hfsplus_compat_ioctl(struct file *filp, unsigned int cmd,
+		  unsigned long arg);
 int hfsplus_setxattr(struct dentry *dentry, const char *name,
 		     const void *value, size_t size, int flags);
 ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
fs/hfsplus/inode.c +4 -0
Index: linux-cg/fs/hfsplus/inode.c
===================================================================
@@ -8,6 +8,7 @@
  * Inode handling routines
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -310,6 +311,9 @@
 	.open		= hfsplus_file_open,
 	.release	= hfsplus_file_release,
 	.ioctl          = hfsplus_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= hfsplus_compat_ioctl,
+#endif
 };
 
 struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
fs/hfsplus/ioctl.c +29 -0
Index: linux-cg/fs/hfsplus/ioctl.c
===================================================================
@@ -12,6 +12,8 @@
  * hfsplus ioctls
  */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/xattr.h>
@@ -82,6 +84,33 @@
 	}
 }
 
+#ifdef CONFIG_COMPAT
+long hfsplus_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	switch (cmd) {
+	case HFSPLUS_IOC_EXT2_GETFLAGS32:
+		cmd = HFSPLUS_IOC_EXT2_GETFLAGS;
+		break;
+	case HFSPLUS_IOC_EXT2_SETFLAGS32:
+		cmd = HFSPLUS_IOC_EXT2_SETFLAGS;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	arg = (unsigned long) compat_ptr(arg);
+	lock_kernel();
+	ret = hfsplus_ioctl(inode, file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
+#endif
+
 int hfsplus_setxattr(struct dentry *dentry, const char *name,
 		     const void *value, size_t size, int flags)
 {
fs/reiserfs/dir.c +3 -0
Index: linux-cg/fs/reiserfs/dir.c
===================================================================
@@ -23,6 +23,9 @@
 	.readdir = reiserfs_readdir,
 	.fsync = reiserfs_dir_fsync,
 	.ioctl = reiserfs_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = reiserfs_compat_ioctl,
+#endif
 };
 
 static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
fs/reiserfs/file.c +4 -0
Index: linux-cg/fs/reiserfs/file.c
===================================================================
@@ -2,6 +2,7 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
+#include <linux/config.h>
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/reiserfs_acl.h>
@@ -1551,6 +1552,9 @@
 	.read = generic_file_read,
 	.write = reiserfs_file_write,
 	.ioctl = reiserfs_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = reiserfs_compat_ioctl,
+#endif
 	.mmap = generic_file_mmap,
 	.release = reiserfs_file_release,
 	.fsync = reiserfs_sync_file,
fs/reiserfs/ioctl.c +36 -0
Index: linux-cg/fs/reiserfs/ioctl.c
===================================================================
@@ -2,6 +2,8 @@
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/fs.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/time.h>
@@ -93,6 +95,40 @@
 	}
 }
 
+#ifdef CONFIG_COMPAT
+long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret;
+
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case REISERFS_IOC32_UNPACK:
+		cmd = REISERFS_IOC_UNPACK;
+		break;
+	case REISERFS_IOC32_GETFLAGS:
+		cmd = REISERFS_IOC_GETFLAGS;
+		break;
+	case REISERFS_IOC32_SETFLAGS:
+		cmd = REISERFS_IOC_SETFLAGS;
+		break;
+	case REISERFS_IOC32_GETVERSION:
+		cmd = REISERFS_IOC_GETVERSION;
+		break;
+	case REISERFS_IOC32_SETVERSION:
+		cmd = REISERFS_IOC_SETVERSION;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	lock_kernel();
+	ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
+	unlock_kernel();
+	return ret;
+}
+#endif
+
 /*
 ** reiserfs_unpack
 ** Function try to convert tail from direct item into indirect.
include/linux/ext2_fs.h +7 -0
Index: linux-cg/include/linux/ext2_fs.h
===================================================================
@@ -204,6 +204,13 @@
 #define	EXT2_IOC_SETFLAGS		_IOW('f', 2, long)
 #define	EXT2_IOC_GETVERSION		_IOR('v', 1, long)
 #define	EXT2_IOC_SETVERSION		_IOW('v', 2, long)
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT2_IOC32_GETFLAGS		_IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS		_IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION		_IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION		_IOW('v', 2, int)
 
 /*
  * Structure of an inode on the disk
include/linux/reiserfs_fs.h +9 -0
Index: linux-cg/include/linux/reiserfs_fs.h
===================================================================
@@ -2180,6 +2180,8 @@
 /* prototypes from ioctl.c */
 int reiserfs_ioctl(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg);
+long reiserfs_compat_ioctl(struct file *filp,
+		   unsigned int cmd, unsigned long arg);
 
 /* ioctl's command */
 #define REISERFS_IOC_UNPACK		_IOW(0xCD,1,long)
@@ -2190,6 +2192,13 @@
 #define REISERFS_IOC_GETVERSION		EXT2_IOC_GETVERSION
 #define REISERFS_IOC_SETVERSION		EXT2_IOC_SETVERSION
 
+/* the 32 bit compat definitions with int argument */
+#define REISERFS_IOC32_UNPACK		_IOW(0xCD, 1, int)
+#define REISERFS_IOC32_GETFLAGS		EXT2_IOC32_GETFLAGS
+#define REISERFS_IOC32_SETFLAGS		EXT2_IOC32_SETFLAGS
+#define REISERFS_IOC32_GETVERSION	EXT2_IOC32_GETVERSION
+#define REISERFS_IOC32_SETVERSION	EXT2_IOC32_SETVERSION
+
 /* Locking primitives */
 /* Right now we are still falling back to (un)lock_kernel, but eventually that
    would evolve into real per-fs locks */
fs/cifs/cifsfs.c +10 -0
Index: linux-cg/fs/cifs/cifsfs.c
===================================================================
@@ -23,6 +23,7 @@
 
 /* Note that BB means BUGBUG (ie something to fix eventually) */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -600,6 +601,9 @@
 	.sendfile = generic_file_sendfile,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = cifs_compat_ioctl,
+#endif /* CONFIG_COMPAT */
 #endif /* CONFIG_CIFS_POSIX */
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -624,6 +628,9 @@
 	.sendfile = generic_file_sendfile, /* BB removeme BB */
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = cifs_compat_ioctl,
+#endif /* CONFIG_COMPAT */
 #endif /* CONFIG_CIFS_POSIX */
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -639,6 +646,9 @@
 	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
         .ioctl  = cifs_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = cifs_compat_ioctl,
+#endif /* CONFIG_COMPAT */
 };
 
 static void
fs/cifs/cifsfs.h +2 -0
Index: linux-cg/fs/cifs/cifsfs.h
===================================================================
@@ -97,5 +97,7 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
+extern long cifs_compat_ioctl(struct file * filep, unsigned int command,
+			      unsigned long arg);
 #define CIFS_VERSION   "1.39"
 #endif				/* _CIFSFS_H */
fs/ext2/ext2.h +1 -0
Index: linux-cg/fs/ext2/ext2.h
===================================================================
@@ -137,6 +137,7 @@
 /* ioctl.c */
 extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
 		       unsigned long);
+extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
include/linux/ext3_fs.h +1 -0
Index: linux-cg/include/linux/ext3_fs.h
===================================================================
@@ -792,6 +792,7 @@
 /* ioctl.c */
 extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
 		       unsigned long);
+extern long ext3_compat_ioctl (struct file *, unsigned int, unsigned long);
 
 /* namei.c */
 extern int ext3_orphan_add(handle_t *, struct inode *);

--

#26 lore raw

Re: [PATCH 10/25] fs: move ext2 ioctl32 handlers into file systems

Quoted 5 lines · Arnd Bergmann

The same ioctls (originally from ext2) are used on ext2, ext3, hfsplus, cifs, reiserfs and xfs. Since they are really compatible between 32 and 64 bit except for the ioctl number, the conversion handler is trivial and I copy it to each of these file systems in order to eventually get rid of fs/compat_ioctl.c completely.

NACK, this is completely idiotic. Duplicating handlers is the very last thing we want. I actually have patches to move handling some of those ioctls into generic code, but that's a different story.

author maintainer
#27 lore raw

Re: [PATCH 10/25] fs: move ext2 ioctl32 handlers into file systems

Quoted 3 lines · Christoph Hellwig

NACK, this is completely idiotic.  Duplicating handlers is the very last thing we want.  I actually have patches to move handling some of those ioctls into generic code, but that's a different story.

Ok, I'll drop this patch then, except for the ext3 parts that fix an actual problem of missing conversion handlers.

What is your opinion on the xfs bit. The current code is somewhat broken, since XFS_IOC_{GET,SET}{VERSION,XFLAGS} are not really compatible. Should those three lines simply be removed?

	Arnd <><
fs/xfs/linux-2.6/xfs_ioctl32.c 2005-11-05 02:45:35.000000000 +0100 renamed from fs/xfs/linux-2.6/xfs_ioctl32.c 2005-11-05 02:44:55.000000000 +0100 +12 -3
@@ -34,6 +34,11 @@
 #define  _NATIVE_IOC(cmd, type) \
          _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
 
+/* broken ext2 ioctl numbers */
+#define XFS_IOC_GETVERSION32 _IOR('v', 1, int)
+#define XFS_IOC_GETXFLAGS32 _IOR('f', 1, int)
+#define XFS_IOC_SETXFLAGS32 _IOW('f', 2, int)
+
 #if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
 #define BROKEN_X86_ALIGNMENT
 /* on ia32 l_start is on a 32-bit boundary */
@@ -115,12 +120,16 @@
        vnode_t         *vp = LINVFS_GET_VP(inode);
 
        switch (cmd) {
+       /* these take an int as their argument, not a long */
+       case XFS_IOC_GETVERSION32:
+       case XFS_IOC_GETXFLAGS32:
+       case XFS_IOC_SETXFLAGS32:
+               cmd = _NATIVE_IOC(cmd, long);
+               break;
+
        case XFS_IOC_DIOINFO:
        case XFS_IOC_FSGEOMETRY_V1:
        case XFS_IOC_FSGEOMETRY:
-       case XFS_IOC_GETVERSION:
-       case XFS_IOC_GETXFLAGS:
-       case XFS_IOC_SETXFLAGS:
        case XFS_IOC_FSGETXATTR:
        case XFS_IOC_FSSETXATTR:
        case XFS_IOC_FSGETXATTRA:
author maintainer
#28 lore raw

PATCH 11/25 framebuffer: move ioctl32 code to fbmem.c

In reply to Arnd Bergmann

The frame buffer layer already had some code dealing with compat ioctls, this patch moves over the remaining code from fs/compat_ioctl.c

drivers/video/fbmem.c +142 -5
Index: linux-2.6.14-rc/drivers/video/fbmem.c
===================================================================
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
+#include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -829,18 +830,154 @@
 }
 
 #ifdef CONFIG_COMPAT
+struct fb_fix_screeninfo32 {
+	char			id[16];
+	compat_caddr_t		smem_start;
+	u32			smem_len;
+	u32			type;
+	u32			type_aux;
+	u32			visual;
+	u16			xpanstep;
+	u16			ypanstep;
+	u16			ywrapstep;
+	u32			line_length;
+	compat_caddr_t		mmio_start;
+	u32			mmio_len;
+	u32			accel;
+	u16			reserved[3];
+};
+
+struct fb_cmap32 {
+	u32			start;
+	u32			len;
+	compat_caddr_t	red;
+	compat_caddr_t	green;
+	compat_caddr_t	blue;
+	compat_caddr_t	transp;
+};
+
+static int fb_getput_cmap(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct fb_cmap_user __user *cmap;
+	struct fb_cmap32 __user *cmap32;
+	__u32 data;
+	int err;
+
+	cmap = compat_alloc_user_space(sizeof(*cmap));
+	cmap32 = compat_ptr(arg);
+
+	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
+		return -EFAULT;
+
+	if (get_user(data, &cmap32->red) ||
+	    put_user(compat_ptr(data), &cmap->red) ||
+	    get_user(data, &cmap32->green) ||
+	    put_user(compat_ptr(data), &cmap->green) ||
+	    get_user(data, &cmap32->blue) ||
+	    put_user(compat_ptr(data), &cmap->blue) ||
+	    get_user(data, &cmap32->transp) ||
+	    put_user(compat_ptr(data), &cmap->transp))
+		return -EFAULT;
+
+	err = fb_ioctl(inode, file, cmd, (unsigned long) cmap);
+
+	if (!err) {
+		if (copy_in_user(&cmap32->start,
+				 &cmap->start,
+				 2 * sizeof(__u32)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
+				  struct fb_fix_screeninfo32 __user *fix32)
+{
+	__u32 data;
+	int err;
+
+	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
+
+	data = (__u32) (unsigned long) fix->smem_start;
+	err |= put_user(data, &fix32->smem_start);
+
+	err |= put_user(fix->smem_len, &fix32->smem_len);
+	err |= put_user(fix->type, &fix32->type);
+	err |= put_user(fix->type_aux, &fix32->type_aux);
+	err |= put_user(fix->visual, &fix32->visual);
+	err |= put_user(fix->xpanstep, &fix32->xpanstep);
+	err |= put_user(fix->ypanstep, &fix32->ypanstep);
+	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
+	err |= put_user(fix->line_length, &fix32->line_length);
+
+	data = (__u32) (unsigned long) fix->mmio_start;
+	err |= put_user(data, &fix32->mmio_start);
+
+	err |= put_user(fix->mmio_len, &fix32->mmio_len);
+	err |= put_user(fix->accel, &fix32->accel);
+	err |= copy_to_user(fix32->reserved, fix->reserved,
+			    sizeof(fix->reserved));
+
+	return err;
+}
+
+static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs;
+	struct fb_fix_screeninfo fix;
+	struct fb_fix_screeninfo32 __user *fix32;
+	int err;
+
+	fix32 = compat_ptr(arg);
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = fb_ioctl(inode, file, cmd, (unsigned long) &fix);
+	set_fs(old_fs);
+
+	if (!err)
+		err = do_fscreeninfo_to_user(&fix, fix32);
+
+	return err;
+}
+
 static long
 fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	int fbidx = iminor(file->f_dentry->d_inode);
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = iminor(inode);
 	struct fb_info *info = registered_fb[fbidx];
 	struct fb_ops *fb = info->fbops;
-	long ret;
+	long ret = -ENOIOCTLCMD;
 
-	if (fb->fb_compat_ioctl == NULL)
-		return -ENOIOCTLCMD;
 	lock_kernel();
-	ret = fb->fb_compat_ioctl(file, cmd, arg, info);
+	switch(cmd) {
+	case FBIOGET_VSCREENINFO:
+	case FBIOPUT_VSCREENINFO:
+	case FBIOPAN_DISPLAY:
+	case FBIOGET_CON2FBMAP:
+	case FBIOPUT_CON2FBMAP:
+		arg = (unsigned long) compat_ptr(arg);
+	case FBIOBLANK:
+		ret = fb_ioctl(inode, file, cmd, arg);
+		break;
+
+	case FBIOGET_FSCREENINFO:
+		ret = fb_get_fscreeninfo(inode, file, cmd, arg);
+		break;
+
+	case FBIOGETCMAP:
+	case FBIOPUTCMAP:
+		ret = fb_getput_cmap(inode, file, cmd, arg);
+		break;
+
+	default:
+		if (fb->fb_compat_ioctl)
+			ret = fb->fb_compat_ioctl(file, cmd, arg, info);
+		break;
+	}
 	unlock_kernel();
 	return ret;
 }
fs/compat_ioctl.c +0 -143

155 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -7
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
@@ -10,13 +10,6 @@
 #define ULONG_IOCTL(cmd)  HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
 #endif
 
-/* Big F */
-COMPATIBLE_IOCTL(FBIOBLANK)
-COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
-COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO)
-COMPATIBLE_IOCTL(FBIOPAN_DISPLAY)
-COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP)
-COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP)
 /* Little f */
 COMPATIBLE_IOCTL(FIOCLEX)
 COMPATIBLE_IOCTL(FIONCLEX)

--

#29 lore raw

Re: [PATCH 11/25] framebuffer: move ioctl32 code to fbmem.c

Quoted 3 lines · Arnd Bergmann

The frame buffer layer already had some code dealing with compat ioctls, this patch moves over the remaining code from fs/compat_ioctl.c

This is fine with me.

Tony

author maintainer
#30 lore raw

PATCH 12/25 scsi: move SG_IO ioctl32 code to sg.c

In reply to Arnd Bergmann

The sg driver already has a compat_ioctl function, so the conversion handler for SG_IO can easily be moved in there as well. It still uses compat_alloc_user_space, so it can probably be simplified by using merging the conversion handler with the native method.

drivers/scsi/sg.c +154 -0
Index: linux-2.6.14-rc/drivers/scsi/sg.c
===================================================================
@@ -31,6 +31,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
+#include <linux/compat.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -1087,6 +1088,156 @@
 }
 
 #ifdef CONFIG_COMPAT
+
+typedef struct sg_io_hdr32 {
+	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 */
+} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
+
+typedef struct sg_iovec32 {
+	compat_uint_t iov_base;
+	compat_uint_t iov_len;
+} sg_iovec32_t;
+
+static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count)
+{
+	sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1);
+	sg_iovec32_t __user *iov32 = dxferp;
+	int i;
+
+	for (i = 0; i < iovec_count; i++) {
+		u32 base, len;
+
+		if (get_user(base, &iov32[i].iov_base) ||
+		    get_user(len, &iov32[i].iov_len) ||
+		    put_user(compat_ptr(base), &iov[i].iov_base) ||
+		    put_user(len, &iov[i].iov_len))
+			return -EFAULT;
+	}
+
+	if (put_user(iov, &sgio->dxferp))
+		return -EFAULT;
+	return 0;
+}
+
+static int sg_ioctl_trans(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	sg_io_hdr_t __user *sgio;
+	sg_io_hdr32_t __user *sgio32;
+	u16 iovec_count;
+	u32 data;
+	void __user *dxferp;
+	int err;
+
+	sgio32 = compat_ptr(arg);
+	if (get_user(iovec_count, &sgio32->iovec_count))
+		return -EFAULT;
+
+	{
+		void __user *top = compat_alloc_user_space(0);
+		void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
+				       (iovec_count * sizeof(sg_iovec_t)));
+		if (new > top)
+			return -EINVAL;
+
+		sgio = new;
+	}
+
+	/* Ok, now construct.  */
+	if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
+			 (2 * sizeof(int)) +
+			 (2 * sizeof(unsigned char)) +
+			 (1 * sizeof(unsigned short)) +
+			 (1 * sizeof(unsigned int))))
+		return -EFAULT;
+
+	if (get_user(data, &sgio32->dxferp))
+		return -EFAULT;
+	dxferp = compat_ptr(data);
+	if (iovec_count) {
+		if (sg_build_iovec(sgio, dxferp, iovec_count))
+			return -EFAULT;
+	} else {
+		if (put_user(dxferp, &sgio->dxferp))
+			return -EFAULT;
+	}
+
+	{
+		unsigned char __user *cmdp;
+		unsigned char __user *sbp;
+
+		if (get_user(data, &sgio32->cmdp))
+			return -EFAULT;
+		cmdp = compat_ptr(data);
+
+		if (get_user(data, &sgio32->sbp))
+			return -EFAULT;
+		sbp = compat_ptr(data);
+
+		if (put_user(cmdp, &sgio->cmdp) ||
+		    put_user(sbp, &sgio->sbp))
+			return -EFAULT;
+	}
+
+	if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+			 3 * sizeof(int)))
+		return -EFAULT;
+
+	if (get_user(data, &sgio32->usr_ptr))
+		return -EFAULT;
+	if (put_user(compat_ptr(data), &sgio->usr_ptr))
+		return -EFAULT;
+
+	if (copy_in_user(&sgio->status, &sgio32->status,
+			 (4 * sizeof(unsigned char)) +
+			 (2 * sizeof(unsigned (short))) +
+			 (3 * sizeof(int))))
+		return -EFAULT;
+
+	lock_kernel();
+	err = sg_ioctl(file->f_dentry->d_inode, file,
+			cmd, (unsigned long) sgio);
+	unlock_kernel();
+
+	if (err >= 0) {
+		void __user *datap;
+
+		if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
+				 sizeof(int)) ||
+		    get_user(datap, &sgio->usr_ptr) ||
+		    put_user((u32)(unsigned long)datap,
+			     &sgio32->usr_ptr) ||
+		    copy_in_user(&sgio32->status, &sgio->status,
+				 (4 * sizeof(unsigned char)) +
+				 (2 * sizeof(unsigned short)) +
+				 (3 * sizeof(int))))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+
 static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
 	Sg_device *sdp;
@@ -1096,6 +1247,9 @@
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
 
+	if (cmd_in == SG_IO)
+		return sg_ioctl_trans(filp, cmd_in, arg);
+
 	sdev = sdp->device;
 	if (sdev->host->hostt->compat_ioctl) { 
 		int ret;
fs/compat_ioctl.c +0 -147

159 lines not on this page · raw message

--

#31 lore raw

Re: [PATCH 12/25] scsi: move SG_IO ioctl32 code to sg.c

Quoted 6 lines · Arnd Bergmann

plain text document attachment (sg-ioctl.diff) The sg driver already has a compat_ioctl function, so the conversion handler for SG_IO can easily be moved in there as well. It still uses compat_alloc_user_space, so it can probably be simplified by using merging the conversion handler with the native method.

This is the wrong place, isn't it? SG_IO is also in drivers/block/scsi_ioctl.c which isn't modular, so shouldn't this be in there?

James

author maintainer
#32 lore raw

Re: [PATCH 12/25] scsi: move SG_IO ioctl32 code to sg.c

Quoted 4 lines · James Bottomley

This is the wrong place, isn't it?  SG_IO is also in drivers/block/scsi_ioctl.c which isn't modular, so shouldn't this be in there?

Yes, you're right. That patch broke compat SG_IO for the other scsi drivers. I'll do a new one.

	Arnd <><
author maintainer
#33 lore raw

PATCH 13/25 loop: move ioctl32 code to loop.c

In reply to Arnd Bergmann

The loop device driver is the only user of its ioctl commands, so we can move the conversion handlers for 32 bit emulation into the driver itself.

This patch just moves over the function, it would probably be a good idea to get rid of get_fs/set_fs calls here by integrating better with the driver.

drivers/block/loop.c +76 -0
Index: linux-2.6.14-rc/drivers/block/loop.c
===================================================================
@@ -51,6 +51,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
@@ -1164,6 +1165,78 @@
 	return err;
 }
 
+#ifdef CONFIG_COMPAT
+struct loop_info32 {
+	compat_int_t	lo_number;      /* ioctl r/o */
+	compat_dev_t	lo_device;      /* ioctl r/o */
+	compat_ulong_t	lo_inode;       /* ioctl r/o */
+	compat_dev_t	lo_rdevice;     /* ioctl r/o */
+	compat_int_t	lo_offset;
+	compat_int_t	lo_encrypt_type;
+	compat_int_t	lo_encrypt_key_size;    /* ioctl w/o */
+	compat_int_t	lo_flags;       /* ioctl r/o */
+	char		lo_name[LO_NAME_SIZE];
+	unsigned char	lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+	compat_ulong_t	lo_init[2];
+	char		reserved[4];
+};
+
+static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	mm_segment_t old_fs = get_fs();
+	struct loop_info l;
+	struct loop_info32 __user *ul;
+	int err = -ENOIOCTLCMD;
+
+	ul = compat_ptr(arg);
+
+	lock_kernel();
+	switch(cmd) {
+	case LOOP_SET_STATUS:
+		err = get_user(l.lo_number, &ul->lo_number);
+		err |= __get_user(l.lo_device, &ul->lo_device);
+		err |= __get_user(l.lo_inode, &ul->lo_inode);
+		err |= __get_user(l.lo_rdevice, &ul->lo_rdevice);
+		err |= __copy_from_user(&l.lo_offset, &ul->lo_offset,
+		        8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+		if (err) {
+			err = -EFAULT;
+		} else {
+			set_fs (KERNEL_DS);
+			err = lo_ioctl(inode, file, cmd, (unsigned long)&l);
+			set_fs (old_fs);
+		}
+		break;
+	case LOOP_GET_STATUS:
+		set_fs (KERNEL_DS);
+		err = lo_ioctl(inode, file, cmd, (unsigned long)&l);
+		set_fs (old_fs);
+		if (!err) {
+			err = put_user(l.lo_number, &ul->lo_number);
+			err |= __put_user(l.lo_device, &ul->lo_device);
+			err |= __put_user(l.lo_inode, &ul->lo_inode);
+			err |= __put_user(l.lo_rdevice, &ul->lo_rdevice);
+			err |= __copy_to_user(&ul->lo_offset, &l.lo_offset,
+				(unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+			if (err)
+				err = -EFAULT;
+		}
+		break;
+	case LOOP_CLR_FD:
+	case LOOP_GET_STATUS64:
+	case LOOP_SET_STATUS64:
+		arg = (unsigned long) compat_ptr(arg);
+	case LOOP_SET_FD:
+	case LOOP_CHANGE_FD:
+		err = lo_ioctl(inode, file, cmd, arg);
+		break;
+	}
+	unlock_kernel();
+	return err;
+}
+#endif
+
 static int lo_open(struct inode *inode, struct file *file)
 {
 	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1191,6 +1264,9 @@
 	.open =		lo_open,
 	.release =	lo_release,
 	.ioctl =	lo_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	lo_compat_ioctl,
+#endif
 };
 
 /*
fs/compat_ioctl.c +0 -67

79 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -6
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
@@ -204,12 +204,6 @@
 COMPATIBLE_IOCTL(DVD_AUTH)
 /* pktcdvd */
 COMPATIBLE_IOCTL(PACKET_CTRL_CMD)
-/* Big L */
-ULONG_IOCTL(LOOP_SET_FD)
-ULONG_IOCTL(LOOP_CHANGE_FD)
-COMPATIBLE_IOCTL(LOOP_CLR_FD)
-COMPATIBLE_IOCTL(LOOP_GET_STATUS64)
-COMPATIBLE_IOCTL(LOOP_SET_STATUS64)
 /* Big A */
 /* sparc only */
 /* Big Q for sound/OSS */

--

#34 lore raw

Re: [PATCH 13/25] loop: move ioctl32 code to loop.c

Quoted 7 lines · Arnd Bergmann

The loop device driver is the only user of its ioctl commands, so we can move the conversion handlers for 32 bit emulation into the driver itself.

This patch just moves over the function, it would probably be a good idea to get rid of get_fs/set_fs calls here by integrating better with the driver.

Yes. just moving over is pointless. for things like loop where there's just one driver implementing the api moving it there does make sense, but please bring the compat layer up to standards first.

author maintainer
#35 lore raw

PATCH 14/25 smbfs: simplify compat_ioctl handling

In reply to Arnd Bergmann

smbfs already handles SMB_IOC_GETMOUNTUID with both 16 and 32 bit arguments, so the compatibility wrapper is not needed any more. The only other ioctl used in smbfs is SMB_IOC_NEWCONN, which is compatible as well.

This simply introduces a new compat_ioctl function that calls the regular smb_ioctl function.

fs/compat_ioctl.c +0 -21
Index: linux-2.6.14-rc/fs/compat_ioctl.c
===================================================================
@@ -331,24 +331,6 @@
 	return err;
 }
 
-static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	__kernel_uid_t kuid;
-	int err;
-
-	cmd = SMB_IOC_GETMOUNTUID;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
-	set_fs(old_fs);
-
-	if (err >= 0)
-		err = put_user(kuid, (compat_uid_t __user *)compat_ptr(arg));
-
-	return err;
-}
-
 static __attribute_used__ int 
 ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -938,9 +920,6 @@
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
 HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
-/* One SMB ioctl needs translations. */
-#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
-HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
 /* vfat */
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
fs/smbfs/ioctl.c +16 -0
Index: linux-2.6.14-rc/fs/smbfs/ioctl.c
===================================================================
@@ -7,6 +7,8 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
@@ -65,3 +67,17 @@
 
 	return result;
 }
+
+#ifdef CONFIG_COMPAT
+/* All three ioctl numbers above are compatible */
+long
+smb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int result;
+	lock_kernel();
+	arg = (unsigned long) compat_ptr(arg);
+	result = smb_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+	unlock_kernel();
+	return result;
+}
+#endif
include/linux/compat_ioctl.h +0 -2
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
@@ -379,8 +379,6 @@
 /* Raw devices */
 COMPATIBLE_IOCTL(RAW_SETBIND)
 COMPATIBLE_IOCTL(RAW_GETBIND)
-/* SMB ioctls which do not need any translations */
-COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
 /* NCP ioctls which do not need any translations */
 COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
 COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
fs/smbfs/file.c +4 -0
Index: linux-2.6.14-rc/fs/smbfs/file.c
===================================================================
@@ -7,6 +7,7 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
+#include <linux/config.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -408,6 +409,9 @@
 	.read		= smb_file_read,
 	.write		= smb_file_write,
 	.ioctl		= smb_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= smb_compat_ioctl,
+#endif
 	.mmap		= smb_file_mmap,
 	.open		= smb_file_open,
 	.release	= smb_file_release,
fs/smbfs/proto.h +1 -0
Index: linux-2.6.14-rc/fs/smbfs/proto.h
===================================================================
@@ -68,6 +68,7 @@
 extern struct inode_operations smb_file_inode_operations;
 /* ioctl.c */
 extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+extern long smb_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 /* smbiod.c */
 extern void smbiod_wake_up(void);
 extern int smbiod_register_server(struct smb_sb_info *server);
fs/smbfs/dir.c +4 -0
Index: linux-2.6.14-rc/fs/smbfs/dir.c
===================================================================
@@ -7,6 +7,7 @@
  *  Please add a note about your changes to smbfs in the ChangeLog file.
  */
 
+#include <linux/config.h>
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -39,6 +40,9 @@
 	.read		= generic_read_dir,
 	.readdir	= smb_readdir,
 	.ioctl		= smb_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= smb_compat_ioctl,
+#endif
 	.open		= smb_dir_open,
 };
 

--

author maintainer
#36 lore raw

PATCH 15/25 autofs: move ioctl32 to autofs{,4}/root.c

In reply to Arnd Bergmann

All autofs ioctl calls are simple to convert for 32 bit compatibility. This just moves the handler into the file system code.

fs/autofs/root.c +35 -0
Index: linux-cg/fs/autofs/root.c
===================================================================
@@ -10,6 +10,8 @@
  *
  * ------------------------------------------------------------------------- */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
@@ -24,11 +26,15 @@
 static int autofs_root_rmdir(struct inode *,struct dentry *);
 static int autofs_root_mkdir(struct inode *,struct dentry *,int);
 static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
+static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 
 struct file_operations autofs_root_operations = {
 	.read		= generic_read_dir,
 	.readdir	= autofs_root_readdir,
 	.ioctl		= autofs_root_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= autofs_root_compat_ioctl,
+#endif
 };
 
 struct inode_operations autofs_root_inode_operations = {
@@ -562,3 +568,32 @@
 		return -ENOSYS;
 	}
 }
+
+#ifdef CONFIG_COMPAT
+/* AUTOFS */
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+
+static long autofs_root_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case AUTOFS_IOC_SETTIMEOUT32:
+		cmd = AUTOFS_IOC_SETTIMEOUT;
+	case AUTOFS_IOC_CATATONIC:
+	case AUTOFS_IOC_PROTOVER:
+	case AUTOFS_IOC_EXPIRE:
+		arg = (unsigned long) compat_ptr(arg);
+	case AUTOFS_IOC_READY:
+	case AUTOFS_IOC_FAIL:
+		lock_kernel();
+		ret = autofs_root_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+#endif
fs/autofs4/root.c +41 -0

62 lines not on this page · raw message

fs/compat_ioctl.c +0 -7
Index: linux-cg/fs/compat_ioctl.c
===================================================================
@@ -337,11 +337,6 @@
 	return -EINVAL;
 }
 
-static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
-}
-
 /* Bluetooth ioctls */
 #define HCIUARTSETPROTO	_IOW('U', 200, int)
 #define HCIUARTGETPROTO	_IOR('U', 201, int)
@@ -918,8 +913,6 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
-HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
 /* vfat */
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
include/linux/compat_ioctl.h +0 -11
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -360,17 +360,6 @@
 COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
 COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
 COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* AUTOFS */
-ULONG_IOCTL(AUTOFS_IOC_READY)
-ULONG_IOCTL(AUTOFS_IOC_FAIL)
-COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)

--

maintainer
#37 lore raw

Re: [PATCH 15/25] autofs: move ioctl32 to autofs{,4}/root.c

Quoted 3 lines · Arnd Bergmann

All autofs ioctl calls are simple to convert for 32 bit compatibility. This just moves the handler into the file system code.

I have a couple of concerns with these patches.

I'm not sure if I like conditional compilation in the code proper but I'll leave it to you to make the final decision since your running with the change. Is there a reason the definitions can't simply be left in place?

Its been a while since I trawled through the compat ioctl code (please point me to the right place) but with this change I think that the AUTOFS_IOC_SETTIMEOUT32 is redundant. Consider a conditional define for AUTOFS_IOC_SETTIMEOUT in include/linux/auto_fs.h instead. Both autofs and autofs4 use that definition.

The lock_kernel()/unlock_kernel() in the autofs4 patch is ineffective as the BKL is not used for syncronisation anywhere else in autofs4. If removing it causes problems I need to know about'em so I can fix'em (hopefully).

Can't see any other obvious issues.

Ian

Quoted 2 lines
CC [email protected] ... also please
Quoted 191 lines

Index: linux-cg/fs/autofs/root.c
===================================================================

fs/autofs/root.c +35 -0
@@ -10,6 +10,8 @@
  *
  * ------------------------------------------------------------------------- */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
@@ -24,11 +26,15 @@
 static int autofs_root_rmdir(struct inode *,struct dentry *);
 static int autofs_root_mkdir(struct inode *,struct dentry *,int);
 static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
+static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 
 struct file_operations autofs_root_operations = {
 	.read		= generic_read_dir,
 	.readdir	= autofs_root_readdir,
 	.ioctl		= autofs_root_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= autofs_root_compat_ioctl,
+#endif
 };
 
 struct inode_operations autofs_root_inode_operations = {
@@ -562,3 +568,32 @@
 		return -ENOSYS;
 	}
 }
+
+#ifdef CONFIG_COMPAT
+/* AUTOFS */
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+
+static long autofs_root_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case AUTOFS_IOC_SETTIMEOUT32:
+		cmd = AUTOFS_IOC_SETTIMEOUT;
+	case AUTOFS_IOC_CATATONIC:
+	case AUTOFS_IOC_PROTOVER:
+	case AUTOFS_IOC_EXPIRE:
+		arg = (unsigned long) compat_ptr(arg);
+	case AUTOFS_IOC_READY:
+	case AUTOFS_IOC_FAIL:
+		lock_kernel();
+		ret = autofs_root_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+#endif

Index: linux-cg/fs/autofs4/root.c
===================================================================

fs/autofs4/root.c +41 -0
@@ -12,6 +12,8 @@
  *
  * ------------------------------------------------------------------------- */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
@@ -24,6 +26,7 @@
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
+static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static int autofs4_dir_close(struct inode *inode, struct file *file);
 static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
@@ -37,6 +40,9 @@
 	.read		= generic_read_dir,
 	.readdir	= autofs4_root_readdir,
 	.ioctl		= autofs4_root_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= autofs4_root_compat_ioctl,
+#endif
 };
 
 struct file_operations autofs4_dir_operations = {
@@ -817,3 +823,38 @@
 		return -ENOSYS;
 	}
 }
+
+#ifdef CONFIG_COMPAT
+/* AUTOFS */
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+
+static long autofs4_root_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case AUTOFS_IOC_SETTIMEOUT32:
+		cmd = AUTOFS_IOC_SETTIMEOUT;
+	case AUTOFS_IOC_CATATONIC:
+	case AUTOFS_IOC_PROTOVER:
+	case AUTOFS_IOC_EXPIRE:
+	case AUTOFS_IOC_EXPIRE_MULTI:
+	case AUTOFS_IOC_PROTOSUBVER:
+	case AUTOFS_IOC_ASKREGHOST:
+	case AUTOFS_IOC_TOGGLEREGHOST:
+	case AUTOFS_IOC_ASKUMOUNT:
+		arg = (unsigned long) compat_ptr(arg);
+	case AUTOFS_IOC_READY:
+	case AUTOFS_IOC_FAIL:
+		lock_kernel();
+		ret = autofs4_root_ioctl(file->f_dentry->d_inode,
+					 file, cmd, arg);
+		unlock_kernel();
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+#endif

Index: linux-cg/fs/compat_ioctl.c
===================================================================

fs/compat_ioctl.c +0 -7
@@ -337,11 +337,6 @@
 	return -EINVAL;
 }
 
-static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
-}
-
 /* Bluetooth ioctls */
 #define HCIUARTSETPROTO	_IOW('U', 200, int)
 #define HCIUARTGETPROTO	_IOR('U', 201, int)
@@ -918,8 +913,6 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
-HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
 /* vfat */
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
 HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)

Index: linux-cg/include/linux/compat_ioctl.h
===================================================================

include/linux/compat_ioctl.h +0 -13
@@ -360,17 +360,6 @@
 COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
 COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
 COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* AUTOFS */
-ULONG_IOCTL(AUTOFS_IOC_READY)
-ULONG_IOCTL(AUTOFS_IOC_FAIL)
-COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
-COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
-COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
 
--
 
-

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

author maintainer
#38 lore raw

Re: [PATCH 15/25] autofs: move ioctl32 to autofs{,4}/root.c

Quoted 5 lines · Ian Kent

On Sat, 5 Nov 2005, Arnd Bergmann wrote:

I'm not sure if I like conditional compilation in the code proper but I'll leave it to you to make the final decision since your running with the change. Is there a reason the definitions can't simply be left in place?

I think the compat_ptr() macro is not defined on architectures that don't have 32 bit compat code, but we could change that.

Quoted 5 lines

Its been a while since I trawled through the compat ioctl code (please point me to the right place) but with this change I think that the AUTOFS_IOC_SETTIMEOUT32 is redundant. Consider a conditional define for AUTOFS_IOC_SETTIMEOUT in include/linux/auto_fs.h instead. Both autofs and autofs4 use that definition.

The point here is that the two are different on 64 bit platforms, since sizeof (int) != sizeof (long). You also can't do

switch (cmd) {
case AUTOFS_IOC_SETTIMEOUT32:
case AUTOFS_IOC_SETTIMEOUT:

	return do_stuff();
}

because then gcc would complain about duplicate case targets on 32 bit targets.

Quoted 4 lines

The lock_kernel()/unlock_kernel() in the autofs4 patch is ineffective as the BKL is not used for syncronisation anywhere else in autofs4. If removing it causes problems I need to know about'em so I can fix'em (hopefully).

I used the BKL here in order to maintain the current semantics, because ioctl is always called with BKL held, and compat_ioctl is called without it.

If you are sure you don't need the BKL, then you should also replace ".ioctl = ..." with ".unlocked_ioctl = ...".

	Arnd <><
maintainer
#39 lore raw

Re: [PATCH 15/25] autofs: move ioctl32 to autofs{,4}/root.c

Quoted 19 lines · Arnd Bergmann
Quoted 5 lines · Ian Kent

On Sat, 5 Nov 2005, Arnd Bergmann wrote:

I'm not sure if I like conditional compilation in the code proper but I'll leave it to you to make the final decision since your running with the change. Is there a reason the definitions can't simply be left in place?

I think the compat_ptr() macro is not defined on architectures that don't have 32 bit compat code, but we could change that.

Quoted 5 lines

Its been a while since I trawled through the compat ioctl code (please point me to the right place) but with this change I think that the AUTOFS_IOC_SETTIMEOUT32 is redundant. Consider a conditional define for AUTOFS_IOC_SETTIMEOUT in include/linux/auto_fs.h instead. Both autofs and autofs4 use that definition.

The point here is that the two are different on 64 bit platforms, since sizeof (int) != sizeof (long). You also can't do

Quoted 8 lines

switch (cmd) {
case AUTOFS_IOC_SETTIMEOUT32:
case AUTOFS_IOC_SETTIMEOUT:

	return do_stuff();
}

because then gcc would complain about duplicate case targets on 32 bit targets.

I was thinking that if the module was compiled for 64bit then the 64bit definition would prevail and visa versa.

eg. In the include file.

#ifdef COMPAT_IOCTL
#define AUTOFS_IOC_SETTIMEOUT(..., unsigned int)
#else
#define AUTOFS_IOC_SETTIMEOUT(...,unsigned long)
#endif

I think I'm going to have to investigate further following the implementation.

Quoted 9 lines
Quoted 5 lines

The lock_kernel()/unlock_kernel() in the autofs4 patch is ineffective as the BKL is not used for syncronisation anywhere else in autofs4. If removing it causes problems I need to know about'em so I can fix'em (hopefully).

I used the BKL here in order to maintain the current semantics, because ioctl is always called with BKL held, and compat_ioctl is called without it.

Of course a sensible approach.

Quoted 3 lines

If you are sure you don't need the BKL, then you should also replace ".ioctl = ..." with ".unlocked_ioctl = ...".

Yep. I'll check and amend it later.
After all it will be part of the module then.

Thanks
Ian

maintainer
#40 lore raw

Re: [PATCH 15/25] autofs: move ioctl32 to autofs{,4}/root.c

Quoted 24 lines · Ian Kent
Quoted 10 lines
Quoted 6 lines

Its been a while since I trawled through the compat ioctl code (please point me to the right place) but with this change I think that the AUTOFS_IOC_SETTIMEOUT32 is redundant. Consider a conditional define for AUTOFS_IOC_SETTIMEOUT in include/linux/auto_fs.h instead. Both autofs and autofs4 use that definition.

The point here is that the two are different on 64 bit platforms, since sizeof (int) != sizeof (long). You also can't do

Quoted 8 lines

switch (cmd) {
case AUTOFS_IOC_SETTIMEOUT32:
case AUTOFS_IOC_SETTIMEOUT:

	return do_stuff();
}

because then gcc would complain about duplicate case targets on 32 bit targets.

I was thinking that if the module was compiled for 64bit then the 64bit definition would prevail and visa versa.

eg. In the include file.

Quoted 8 lines

#ifdef COMPAT_IOCTL
#define AUTOFS_IOC_SETTIMEOUT(..., unsigned int)
#else
#define AUTOFS_IOC_SETTIMEOUT(...,unsigned long)
#endif

I think I'm going to have to investigate further following the implementation.

Yes. I see now, stupid suggestion.

Quoted 7 lines
Quoted 4 lines

If you are sure you don't need the BKL, then you should also replace ".ioctl = ..." with ".unlocked_ioctl = ...".

Yep. I'll check and amend it later.
After all it will be part of the module then.

Yep. I'll do that.

Ian

author maintainer
#41 lore raw

PATCH 16/25 ncpfs: move ioctl32 code to fs/ncpfs/ioctl.c

In reply to Arnd Bergmann

The ncp specific compat ioctls are clearly local to one file system, so the code can better live there.

This could be further improved by getting rid of get_fs/set_fs in the future.

fs/compat_ioctl.c +0 -197
Index: linux-cg/fs/compat_ioctl.c
===================================================================
@@ -718,193 +718,6 @@
 	return sys_ioctl(fd, cmd, (unsigned long)tdata);
 }
 
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-struct ncp_ioctl_request_32 {
-	u32 function;
-	u32 size;
-	compat_caddr_t data;
-};
-
-struct ncp_fs_info_v2_32 {
-	s32 version;
-	u32 mounted_uid;
-	u32 connection;
-	u32 buffer_size;
-
-	u32 volume_number;
-	u32 directory_id;
-
-	u32 dummy1;
-	u32 dummy2;
-	u32 dummy3;
-};
-
-struct ncp_objectname_ioctl_32
-{
-	s32		auth_type;
-	u32		object_name_len;
-	compat_caddr_t	object_name;	/* an userspace data, in most cases user name */
-};
-
-struct ncp_privatedata_ioctl_32
-{
-	u32		len;
-	compat_caddr_t	data;		/* ~1000 for NDS */
-};
-
-#define	NCP_IOC_NCPREQUEST_32		_IOR('n', 1, struct ncp_ioctl_request_32)
-#define NCP_IOC_GETMOUNTUID2_32		_IOW('n', 2, u32)
-#define NCP_IOC_GET_FS_INFO_V2_32	_IOWR('n', 4, struct ncp_fs_info_v2_32)
-#define NCP_IOC_GETOBJECTNAME_32	_IOWR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_SETOBJECTNAME_32	_IOR('n', 9, struct ncp_objectname_ioctl_32)
-#define NCP_IOC_GETPRIVATEDATA_32	_IOWR('n', 10, struct ncp_privatedata_ioctl_32)
-#define NCP_IOC_SETPRIVATEDATA_32	_IOR('n', 10, struct ncp_privatedata_ioctl_32)
-
-static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ncp_ioctl_request_32 n32;
-	struct ncp_ioctl_request __user *p = compat_alloc_user_space(sizeof(*p));
-
-	if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)) ||
-	    put_user(n32.function, &p->function) ||
-	    put_user(n32.size, &p->size) ||
-	    put_user(compat_ptr(n32.data), &p->data))
-		return -EFAULT;
-
-	return sys_ioctl(fd, NCP_IOC_NCPREQUEST, (unsigned long)p);
-}
-
-static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	__kernel_uid_t kuid;
-	int err;
-
-	cmd = NCP_IOC_GETMOUNTUID2;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
-	set_fs(old_fs);
-
-	if (!err)
-		err = put_user(kuid,
-			       (unsigned int __user *) compat_ptr(arg));
-
-	return err;
-}
-
-static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct ncp_fs_info_v2_32 n32;
-	struct ncp_fs_info_v2 n;
-	int err;
-
-	if (copy_from_user(&n32, compat_ptr(arg), sizeof(n32)))
-		return -EFAULT;
-	if (n32.version != NCP_GET_FS_INFO_VERSION_V2)
-		return -EINVAL;
-	n.version = NCP_GET_FS_INFO_VERSION_V2;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n);
-	set_fs(old_fs);
-
-	if (!err) {
-		n32.version = n.version;
-		n32.mounted_uid = n.mounted_uid;
-		n32.connection = n.connection;
-		n32.buffer_size = n.buffer_size;
-		n32.volume_number = n.volume_number;
-		n32.directory_id = n.directory_id;
-		n32.dummy1 = n.dummy1;
-		n32.dummy2 = n.dummy2;
-		n32.dummy3 = n.dummy3;
-		err = copy_to_user(compat_ptr(arg), &n32, sizeof(n32)) ? -EFAULT : 0;
-	}
-	return err;
-}
-
-static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-	struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
-	s32 auth_type;
-	u32 name_len;
-	int err;
-
-	if (copy_from_user(&n32, p32, sizeof(n32)) ||
-	    put_user(n32.object_name_len, &p->object_name_len) ||
-	    put_user(compat_ptr(n32.object_name), &p->object_name))
-		return -EFAULT;
-
-	err = sys_ioctl(fd, NCP_IOC_GETOBJECTNAME, (unsigned long)p);
-        if (err)
-		return err;
-
-	if (get_user(auth_type, &p->auth_type) ||
-	    put_user(auth_type, &p32->auth_type) ||
-	    get_user(name_len, &p->object_name_len) ||
-	    put_user(name_len, &p32->object_name_len))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ncp_objectname_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-	struct ncp_objectname_ioctl __user *p = compat_alloc_user_space(sizeof(*p));
-
-	if (copy_from_user(&n32, p32, sizeof(n32)) ||
-	    put_user(n32.auth_type, &p->auth_type) ||
-	    put_user(n32.object_name_len, &p->object_name_len) ||
-	    put_user(compat_ptr(n32.object_name), &p->object_name))
-		return -EFAULT;
-
-	return sys_ioctl(fd, NCP_IOC_SETOBJECTNAME, (unsigned long)p);
-}
-
-static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ncp_privatedata_ioctl_32 n32, __user *p32 = compat_ptr(arg);
-	struct ncp_privatedata_ioctl __user *p =
-		compat_alloc_user_space(sizeof(*p));
-	u32 len;
-	int err;
-
-	if (copy_from_user(&n32, p32, sizeof(n32)) ||
-	    put_user(n32.len, &p->len) ||
-	    put_user(compat_ptr(n32.data), &p->data))
-		return -EFAULT;
-
-	err = sys_ioctl(fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)p);
-        if (err)
-		return err;
-
-	if (get_user(len, &p->len) ||
-	    put_user(len, &p32->len))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct ncp_privatedata_ioctl_32 n32;
-	struct ncp_privatedata_ioctl_32 __user *p32 = compat_ptr(arg);
-	struct ncp_privatedata_ioctl __user *p =
-		compat_alloc_user_space(sizeof(*p));
-
-	if (copy_from_user(&n32, p32, sizeof(n32)) ||
-	    put_user(n32.len, &p->len) ||
-	    put_user(compat_ptr(n32.data), &p->data))
-		return -EFAULT;
-
-	return sys_ioctl(fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)p);
-}
-#endif
-
 #undef CODE
 #endif
 
@@ -937,15 +750,5 @@
 HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
 HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl)
 
-#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
-HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
-HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2)
-HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2)
-HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname)
-HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname)
-HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
-HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
-#endif
-
 #undef DECLARES
 #endif
fs/ncpfs/dir.c +3 -0
Index: linux-cg/fs/ncpfs/dir.c
===================================================================
@@ -54,6 +54,9 @@
 	.read		= generic_read_dir,
 	.readdir	= ncp_readdir,
 	.ioctl		= ncp_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ncp_compat_ioctl,
+#endif
 };
 
 struct inode_operations ncp_dir_inode_operations =
fs/ncpfs/file.c +4 -0
Index: linux-cg/fs/ncpfs/file.c
===================================================================
@@ -9,6 +9,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#include <linux/config.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -289,6 +290,9 @@
 	.read		= ncp_file_read,
 	.write		= ncp_file_write,
 	.ioctl		= ncp_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ncp_compat_ioctl,
+#endif
 	.mmap		= ncp_mmap,
 	.release	= ncp_release,
 	.fsync		= ncp_fsync,
fs/ncpfs/ioctl.c +239 -2

256 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -12
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -368,18 +368,6 @@
 /* Raw devices */
 COMPATIBLE_IOCTL(RAW_SETBIND)
 COMPATIBLE_IOCTL(RAW_GETBIND)
-/* NCP ioctls which do not need any translations */
-COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
-COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
-COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED)
-COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED)
-COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK)
-COMPATIBLE_IOCTL(NCP_IOC_GETROOT)
-COMPATIBLE_IOCTL(NCP_IOC_SETROOT)
-COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS)
-COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS)
-COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL)
-COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL)
 /* Little a */
 COMPATIBLE_IOCTL(ATMSIGD_CTRL)
 COMPATIBLE_IOCTL(ATMARPD_CTRL)
include/linux/ncp_fs.h +1 -0
Index: linux-cg/include/linux/ncp_fs.h
===================================================================
@@ -244,6 +244,7 @@
 
 /* linux/fs/ncpfs/ioctl.c */
 int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long ncp_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* linux/fs/ncpfs/sock.c */
 int ncp_request2(struct ncp_server *server, int function,

--

author maintainer
#42 lore raw

PATCH 17/25 vfat: move ioctl32 code to fs/fat/dir.c

In reply to Arnd Bergmann

The vfat compat ioctls are clearly local to a single file system, so the code can better be part of that file system.

This can be further improved in the future by getting rid of get_fs/set_fs calls.

fs/compat_ioctl.c +0 -48
Index: linux-2.6.14-rc/fs/compat_ioctl.c
===================================================================
@@ -356,51 +356,6 @@
 #define HIDPGETCONNLIST	_IOR('H', 210, int)
 #define HIDPGETCONNINFO	_IOR('H', 211, int)
 
-#define	VFAT_IOCTL_READDIR_BOTH32	_IOR('r', 1, struct compat_dirent[2])
-#define	VFAT_IOCTL_READDIR_SHORT32	_IOR('r', 2, struct compat_dirent[2])
-
-static long
-put_dirent32 (struct dirent *d, struct compat_dirent __user *d32)
-{
-        if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
-                return -EFAULT;
-
-        __put_user(d->d_ino, &d32->d_ino);
-        __put_user(d->d_off, &d32->d_off);
-        __put_user(d->d_reclen, &d32->d_reclen);
-        if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
-		return -EFAULT;
-
-        return 0;
-}
-
-static int vfat_ioctl32(unsigned fd, unsigned cmd, unsigned long arg)
-{
-	struct compat_dirent __user *p = compat_ptr(arg);
-	int ret;
-	mm_segment_t oldfs = get_fs();
-	struct dirent d[2];
-
-	switch(cmd)
-	{
-        	case VFAT_IOCTL_READDIR_BOTH32:
-                	cmd = VFAT_IOCTL_READDIR_BOTH;
-                	break;
-        	case VFAT_IOCTL_READDIR_SHORT32:
-                	cmd = VFAT_IOCTL_READDIR_SHORT;
-                	break;
-	}
-
-	set_fs(KERNEL_DS);
-	ret = sys_ioctl(fd,cmd,(unsigned long)&d);
-	set_fs(oldfs);
-	if (ret >= 0) {
-		ret |= put_dirent32(&d[0], p);
-		ret |= put_dirent32(&d[1], p + 1);
-	}
-	return ret;
-}
-
 #define REISERFS_IOC_UNPACK32               _IOW(0xCD,1,int)
 
 static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr)
@@ -726,9 +681,6 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-/* vfat */
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
-HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
 HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
 /* Raw devices */
 HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
fs/fat/dir.c +54 -0

70 lines not on this page · raw message

--

maintainer
#43 lore raw

Re: [PATCH 17/25] vfat: move ioctl32 code to fs/fat/dir.c

fs/fat/dir.c line 777

Quoted 4 lines · Arnd Bergmann
fs/fat/dir.c +4 -0
+#ifdef CONFIG_COMPAT
+/* vfat */
+#define	VFAT_IOCTL_READDIR_BOTH32	_IOR('r', 1, struct compat_dirent[2])
+#define	VFAT_IOCTL_READDIR_SHORT32	_IOR('r', 2, struct compat_dirent[2])
          ^^^^^^

Please use a SPACE after #define, and kill a useless "/* vfat */".

fs/fat/dir.c line 789

Quoted 11 lines
fs/fat/dir.c +11 -0
+static long
+put_dirent32(struct dirent *d, struct compat_dirent __user * d32)
+{
+	if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
+		return -EFAULT;
+
+	__put_user(d->d_ino, &d32->d_ino);
+	__put_user(d->d_off, &d32->d_off);
+	__put_user(d->d_reclen, &d32->d_reclen);
+	if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
+		return -EFAULT;

Why don't we need to check the return value of __put_user()?

fs/fat/dir.c line 817

Quoted 6 lines
fs/fat/dir.c +6 -0
+	set_fs(KERNEL_DS);
+	ret = fat_dir_ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long) &d);
+	set_fs(oldfs);
+	if (ret >= 0) {
+		ret |= put_dirent32(&d[0], p);
+		ret |= put_dirent32(&d[1], p + 1);

If "ret" is not 0, we can't use "|=" here?

This patch seems to have bugs, although original one too.

Signature · 1 line
OGAWA Hirofumi <[email protected]>
author maintainer
#44 lore raw

Re: [PATCH 17/25] vfat: move ioctl32 code to fs/fat/dir.c

Quoted 9 lines · OGAWA Hirofumi

fs/fat/dir.c line 777

Quoted 4 lines · Arnd Bergmann
fs/fat/dir.c +4 -0
+#ifdef CONFIG_COMPAT
+/* vfat */
+#define	VFAT_IOCTL_READDIR_BOTH32	_IOR('r', 1, struct compat_dirent[2])
+#define	VFAT_IOCTL_READDIR_SHORT32	_IOR('r', 2, struct compat_dirent[2])
          ^^^^^^

Please use a SPACE after #define, and kill a useless "/* vfat */".

ok.

Quoted 5 lines
Quoted 5 lines
fs/fat/dir.c +5 -0
+static long
+put_dirent32(struct dirent *d, struct compat_dirent __user * d32)
+{
+	if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
+		return -EFAULT;
Quoted 8 lines

fs/fat/dir.c line 789

Quoted 6 lines
fs/fat/dir.c +6 -0
+
+	__put_user(d->d_ino, &d32->d_ino);
+	__put_user(d->d_off, &d32->d_off);
+	__put_user(d->d_reclen, &d32->d_reclen);
+	if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
+		return -EFAULT;

Why don't we need to check the return value of __put_user()?

This is a bug in the code that I copied over, and it needs to be fixed, thanks.

Quoted 10 lines

fs/fat/dir.c line 817

Quoted 6 lines
fs/fat/dir.c +6 -0
+	set_fs(KERNEL_DS);
+	ret = fat_dir_ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long) &d);
+	set_fs(oldfs);
+	if (ret >= 0) {
+		ret |= put_dirent32(&d[0], p);
+		ret |= put_dirent32(&d[1], p + 1);

If "ret" is not 0, we can't use "|=" here?

This patch seems to have bugs, although original one too.

Right. In my patches I tried to change as little as possible to avoid introducing new bugs, but this one is already so broken, that it's better to do a clean implementation from scratch.

	Arnd <><
#45 lore raw

Re: [PATCH 17/25] vfat: move ioctl32 code to fs/fat/dir.c

In reply to Arnd Bergmann

fs/fat/dir.c line 777

Quoted 4 lines
fs/fat/dir.c +4 -0
+#ifdef CONFIG_COMPAT
+/* vfat */
+#define	VFAT_IOCTL_READDIR_BOTH32	_IOR('r', 1, struct compat_dirent[2])
+#define	VFAT_IOCTL_READDIR_SHORT32	_IOR('r', 2, struct compat_dirent[2])

these should be moved close to the original VFAT ioctl defintions. And there's no need to put them under ifdef.

fs/fat/dir.c line 787

Quoted 9 lines
fs/fat/dir.c +9 -0
+static long
+put_dirent32(struct dirent *d, struct compat_dirent __user * d32)
+{
+	if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
+		return -EFAULT;
+
+	__put_user(d->d_ino, &d32->d_ino);
+	__put_user(d->d_off, &d32->d_off);
+	__put_user(d->d_reclen, &d32->d_reclen);

missing error checks.

fs/fat/dir.c line 799

Quoted 6 lines
fs/fat/dir.c +6 -0
+static long fat_dir_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct compat_dirent __user *p = compat_ptr(arg);
+	int ret;
+	mm_segment_t oldfs = get_fs();
+	struct dirent d[2];

please use proper compat_alloc_user_space here.

Quoted 4 lines
fs/fat/dir.c +4 -0
+	switch (cmd) {
+	case VFAT_IOCTL_READDIR_BOTH32:
+		cmd = VFAT_IOCTL_READDIR_BOTH;
+		break;

fs/fat/dir.c line 814

Quoted 10 lines
fs/fat/dir.c +10 -0
+	case VFAT_IOCTL_READDIR_SHORT32:
+		cmd = VFAT_IOCTL_READDIR_SHORT;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	set_fs(KERNEL_DS);
+	ret = fat_dir_ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long) &d);
+	set_fs(oldfs);

In fact there's even a much better way to implement this, let the ioctls call __fat_readdir directly with a filldir callback that directly works in compat_dirent structures.

author maintainer
#46 lore raw

Re: [PATCH 17/25] vfat: move ioctl32 code to fs/fat/dir.c

Quoted 7 lines · Christoph Hellwig
Quoted 3 lines

+     set_fs(KERNEL_DS);
+     ret = fat_dir_ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long) &d); +     set_fs(oldfs);

In fact there's even a much better way to implement this, let the ioctls call __fat_readdir directly with a filldir callback that directly works in compat_dirent structures.

Yes, I'll do that.

	Arnd <><
author maintainer
#47 lore raw

PATCH 18/25 raw: move ioctl32 code to raw.c

In reply to Arnd Bergmann

The two ioctl commands for the raw driver are not used anywhere outside of raw.c, so move the compat handler there as well.

Since they were previously registered both as compatible and with a conversion handler, it is not clear if this ever worked before.

Forwarding ioctl commands to the underlying block device needs adaptations here as well because of the earlier block device compat ioctl patch.

drivers/char/raw.c +91 -0
Index: linux-cg/drivers/char/raw.c
===================================================================
@@ -8,6 +8,8 @@
  * device are used to bind the other minor numbers to block devices.
  */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/devfs_fs_kernel.h>
@@ -125,6 +127,16 @@
 	return blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
 }
 
+#ifdef CONFIG_COMPAT
+static long
+raw_compat_ioctl(struct file *filp, unsigned int command, unsigned long arg)
+{
+	struct block_device *bdev = filp->private_data;
+
+	return compat_blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
+}
+#endif
+
 static void bind_device(struct raw_config_request *rq)
 {
 	class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
@@ -238,6 +250,79 @@
 	return err;
 }
 
+#ifdef CONFIG_COMPAT
+/* Raw devices */
+struct raw32_config_request {
+	compat_int_t raw_minor;
+	__u64 block_major;
+	__u64 block_minor;
+} __attribute__ ((packed));
+
+static int get_raw32_request(struct raw_config_request *req,
+			     struct raw32_config_request __user * user_req)
+{
+	int ret;
+
+	if (!access_ok
+	    (VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
+		return -EFAULT;
+
+	ret = __get_user(req->raw_minor, &user_req->raw_minor);
+	ret |= __get_user(req->block_major, &user_req->block_major);
+	ret |= __get_user(req->block_minor, &user_req->block_minor);
+
+	return ret ? -EFAULT : 0;
+}
+
+static int set_raw32_request(struct raw_config_request *req,
+			     struct raw32_config_request __user * user_req)
+{
+	int ret;
+
+	if (!access_ok
+	    (VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
+		return -EFAULT;
+
+	ret = __put_user(req->raw_minor, &user_req->raw_minor);
+	ret |= __put_user(req->block_major, &user_req->block_major);
+	ret |= __put_user(req->block_minor, &user_req->block_minor);
+
+	return ret ? -EFAULT : 0;
+}
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned cmd,
+						unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+
+	switch (cmd) {
+	case RAW_SETBIND:
+	case RAW_GETBIND:{
+			struct raw_config_request req;
+			struct raw32_config_request __user *user_req =
+			    compat_ptr(arg);
+			mm_segment_t oldfs = get_fs();
+
+			if ((ret = get_raw32_request(&req, user_req)))
+				return ret;
+
+			set_fs(KERNEL_DS);
+			lock_kernel();
+			ret = raw_ctl_ioctl(file->f_dentry->d_inode, file,
+						cmd, (unsigned long) &req);
+			unlock_kernel();
+			set_fs(oldfs);
+
+			if ((!ret) && (cmd == RAW_GETBIND)) {
+				ret = set_raw32_request(&req, user_req);
+			}
+			break;
+		}
+	}
+	return ret;
+}
+#endif
+
 static ssize_t raw_file_write(struct file *file, const char __user *buf,
 				   size_t count, loff_t *ppos)
 {
@@ -269,6 +354,9 @@
 	.open	=	raw_open,
 	.release=	raw_release,
 	.ioctl	=	raw_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	raw_compat_ioctl,
+#endif
 	.readv	= 	generic_file_readv,
 	.writev	= 	generic_file_writev,
 	.owner	=	THIS_MODULE,
@@ -276,6 +364,9 @@
 
 static struct file_operations raw_ctl_fops = {
 	.ioctl	=	raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = raw_ctl_compat_ioctl,
+#endif
 	.open	=	raw_open,
 	.owner	=	THIS_MODULE,
 };
fs/compat_ioctl.c +0 -68

80 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -3
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -365,9 +365,6 @@
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
 COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK)
-/* Raw devices */
-COMPATIBLE_IOCTL(RAW_SETBIND)
-COMPATIBLE_IOCTL(RAW_GETBIND)
 /* Little a */
 COMPATIBLE_IOCTL(ATMSIGD_CTRL)
 COMPATIBLE_IOCTL(ATMARPD_CTRL)
include/linux/fs.h +2 -1
Index: linux-cg/include/linux/fs.h
===================================================================
@@ -1321,7 +1321,8 @@
 extern struct file_operations def_fifo_fops;
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
-extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
+extern long compat_blkdev_ioctl(struct inode *,struct file *,
+				unsigned, unsigned long);
 extern int blkdev_get(struct block_device *, mode_t, unsigned);
 extern int blkdev_put(struct block_device *);
 extern int bd_claim(struct block_device *, void *);
drivers/block/ioctl.c +4 -5
Index: linux-cg/drivers/block/ioctl.c
===================================================================
@@ -259,6 +259,7 @@
 
 	return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
 }
+EXPORT_SYMBOL_GPL(blkdev_ioctl);
 
 #ifdef CONFIG_COMPAT
 static int w_long(struct inode *inode, struct file *file,
@@ -695,11 +696,10 @@
 /* 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)
+long compat_blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg)
 {
-	struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+	struct block_device *bdev = inode->i_bdev;
 	struct gendisk *disk = bdev->bd_disk;
-	struct inode *inode = file->f_mapping->host;
 	int ret = -ENOIOCTLCMD;
 
 	switch (cmd) {
@@ -808,6 +808,5 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(compat_blkdev_ioctl);
 #endif
-
-EXPORT_SYMBOL_GPL(blkdev_ioctl);
fs/block_dev.c +9 -1
Index: linux-cg/fs/block_dev.c
===================================================================
@@ -782,6 +782,14 @@
 	return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+static long block_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	return compat_blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
+}
+#endif
+
 struct address_space_operations def_blk_aops = {
 	.readpage	= blkdev_readpage,
 	.writepage	= blkdev_writepage,
@@ -804,7 +812,7 @@
 	.fsync		= block_fsync,
 	.unlocked_ioctl	= block_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl	= compat_blkdev_ioctl,
+	.compat_ioctl	= block_compat_ioctl,
 #endif
 	.readv		= generic_file_readv,
 	.writev		= generic_file_write_nolock,

--

#48 lore raw

Re: [PATCH 18/25] raw: move ioctl32 code to raw.c

Quoted 4 lines · Arnd Bergmann

The two ioctl commands for the raw driver are not used anywhere outside of raw.c, so move the compat handler there as well.
...

Please leave this alone, the raw driver will be removed in 2.6.16.

cu
Adrian

Signature · 4 lines
       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed
author maintainer
#49 lore raw

Re: [PATCH 18/25] raw: move ioctl32 code to raw.c

Quoted 8 lines · Adrian Bunk
Quoted 4 lines · Arnd Bergmann

The two ioctl commands for the raw driver are not used anywhere outside of raw.c, so move the compat handler there as well.
...

Please leave this alone, the raw driver will be removed in 2.6.16.

Ok, good point.

	Arnd <><
author maintainer
#50 lore raw

PATCH 19/25 usbdevfs: move ioctl32 into devio.c

In reply to Arnd Bergmann

usbdevfs already has support for some compat ioctl code by handling it directly in its ioctl function and marking the numbers as compatible.

This patch moves over all remaining conversion handlers to the same file into a new compat_ioctl function. It should be further unified with the existing ioctl implementation in the future.

drivers/usb/core/devio.c +137 -2
Index: linux-cg/drivers/usb/core/devio.c
===================================================================
@@ -1392,7 +1392,7 @@
 }
 
 #ifdef CONFIG_COMPAT
-static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
+static int proc_ioctl_compat(struct dev_state *ps, unsigned long arg)
 {
 	struct usbdevfs_ioctl32 __user *uioc;
 	struct usbdevfs_ioctl ctrl;
@@ -1511,7 +1511,7 @@
 
 	case USBDEVFS_IOCTL32:
 		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
-		ret = proc_ioctl_compat(ps, p);
+		ret = proc_ioctl_compat(ps, arg);
 		break;
 #endif
 
@@ -1556,6 +1556,138 @@
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+/* FIXME: put the conversion handlers into usbdev_ioctl() */
+
+struct usbdevfs_ctrltransfer32 {
+	u8 bRequestType;
+	u8 bRequest;
+	u16 wValue;
+	u16 wIndex;
+	u16 wLength;
+	u32 timeout;		/* in milliseconds */
+	compat_caddr_t data;
+};
+
+#define USBDEVFS_CONTROL32           _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+
+static int do_usbdevfs_control(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_ctrltransfer32 __user *p32 = compat_ptr(arg);
+	struct usbdevfs_ctrltransfer __user *p;
+	__u32 udata;
+	p = compat_alloc_user_space(sizeof(*p));
+	if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t)))
+	    || get_user(udata, &p32->data)
+	    || put_user(compat_ptr(udata), &p->data))
+		return -EFAULT;
+	return usbdev_ioctl(inode, file, USBDEVFS_CONTROL, (unsigned long) p);
+}
+
+struct usbdevfs_bulktransfer32 {
+	compat_uint_t ep;
+	compat_uint_t len;
+	compat_uint_t timeout;	/* in milliseconds */
+	compat_caddr_t data;
+};
+
+#define USBDEVFS_BULK32              _IOWR('U', 2, struct usbdevfs_bulktransfer32)
+
+static int do_usbdevfs_bulk(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_bulktransfer32 __user *p32 = compat_ptr(arg);
+	struct usbdevfs_bulktransfer __user *p;
+	compat_uint_t n;
+	compat_caddr_t addr;
+
+	p = compat_alloc_user_space(sizeof(*p));
+
+	if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
+	    get_user(n, &p32->len) || put_user(n, &p->len) ||
+	    get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
+	    get_user(addr, &p32->data)
+	    || put_user(compat_ptr(addr), &p->data))
+		return -EFAULT;
+
+	return usbdev_ioctl(inode, file, USBDEVFS_BULK, (unsigned long) p);
+}
+
+struct usbdevfs_disconnectsignal32 {
+	compat_int_t signr;
+	compat_caddr_t context;
+};
+
+#define USBDEVFS_DISCSIGNAL32      _IOR('U', 14, struct usbdevfs_disconnectsignal32)
+
+static int do_usbdevfs_discsignal(struct inode *inode, struct file *file,
+					unsigned int cmd, unsigned long arg)
+{
+	struct usbdevfs_disconnectsignal kdis;
+	struct usbdevfs_disconnectsignal32 __user *udis;
+	mm_segment_t old_fs;
+	u32 uctx;
+	int err;
+
+	udis = compat_ptr(arg);
+
+	if (get_user(kdis.signr, &udis->signr) ||
+	    __get_user(uctx, &udis->context))
+		return -EFAULT;
+
+	kdis.context = compat_ptr(uctx);
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = usbdev_ioctl(inode, file, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
+	set_fs(old_fs);
+
+	return err;
+}
+
+static long
+usbdev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret = -ENOIOCTLCMD;
+
+	lock_kernel();
+	switch (cmd) {
+	case USBDEVFS_CONTROL32:
+		ret = do_usbdevfs_control(inode, file, cmd, arg);
+		break;
+	case USBDEVFS_BULK32:
+		ret = do_usbdevfs_bulk(inode, file, cmd, arg);
+		break;
+	case USBDEVFS_DISCSIGNAL32:
+		ret = do_usbdevfs_discsignal(inode, file, cmd, arg);
+		break;
+	case USBDEVFS_RESETEP:
+	case USBDEVFS_SETINTERFACE:
+	case USBDEVFS_SETCONFIGURATION:
+	case USBDEVFS_GETDRIVER:
+	case USBDEVFS_DISCARDURB:
+	case USBDEVFS_CLAIMINTERFACE:
+	case USBDEVFS_RELEASEINTERFACE:
+	case USBDEVFS_CONNECTINFO:
+	case USBDEVFS_HUB_PORTINFO:
+	case USBDEVFS_RESET:
+	case USBDEVFS_SUBMITURB32:
+	case USBDEVFS_REAPURB32:
+	case USBDEVFS_REAPURBNDELAY32:
+	case USBDEVFS_IOCTL32:
+	case USBDEVFS_CLEAR_HALT:
+		arg = (unsigned long) compat_ptr(arg);
+		ret = usbdev_ioctl(inode, file, cmd, arg);
+		break;
+	}
+	unlock_kernel();
+	return ret;
+}
+#endif
+
+
 /* No kernel lock - fine */
 static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
 {
@@ -1575,6 +1707,9 @@
 	.read =		usbdev_read,
 	.poll =		usbdev_poll,
 	.ioctl =	usbdev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = usbdev_compat_ioctl,
+#endif
 	.open =		usbdev_open,
 	.release =	usbdev_release,
 };
fs/compat_ioctl.c +0 -95

107 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -15
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -456,21 +456,6 @@
 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
 COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
-/* USB */
-COMPATIBLE_IOCTL(USBDEVFS_RESETEP)
-COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION)
-COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER)
-COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB)
-COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE)
-COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
-COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
-COMPATIBLE_IOCTL(USBDEVFS_RESET)
-COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32)
-COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
-COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
-COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
 /* NBD */
 ULONG_IOCTL(NBD_SET_SOCK)
 ULONG_IOCTL(NBD_SET_BLKSIZE)

--

author maintainer
#51 lore raw

PATCH 20/25 i2c: move ioctl32 code to i2c-dev.c

In reply to Arnd Bergmann

The conversion functions for i2c ioctl commands are all related to code in i2cdev_ioctl, so introduce move the conversion to a new i2cdev_compat_ioctl function in the same file.

These can probably be improved by not using
compat_alloc_user_space.

In order to support I2C_SREAD, it might be necessary to introduce a compat_algo_control method for i2c devices.

drivers/i2c/i2c-dev.c +141 -0
Index: linux-cg/drivers/i2c/i2c-dev.c
===================================================================
@@ -26,6 +26,8 @@
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <[email protected]> */
 
+#include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -358,6 +360,142 @@
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+struct i2c_msg32 {
+	u16 addr;
+	u16 flags;
+	u16 len;
+	compat_caddr_t buf;
+};
+
+struct i2c_rdwr_ioctl_data32 {
+	compat_caddr_t msgs; /* struct i2c_msg __user *msgs */
+	u32 nmsgs;
+};
+
+struct i2c_smbus_ioctl_data32 {
+	u8 read_write;
+	u8 command;
+	u32 size;
+	compat_caddr_t data; /* union i2c_smbus_data *data */
+};
+
+struct i2c_rdwr_aligned {
+	struct i2c_rdwr_ioctl_data cmd;
+	struct i2c_msg msgs[0];
+};
+
+static int do_i2c_w_long(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+
+	set_fs (KERNEL_DS);
+	err = i2cdev_ioctl(inode, file, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 __user *)compat_ptr(arg)))
+		return -EFAULT;
+	return err;
+}
+
+static int do_i2c_rdwr_ioctl(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct i2c_rdwr_ioctl_data32	__user *udata = compat_ptr(arg);
+	struct i2c_rdwr_aligned		__user *tdata;
+	struct i2c_msg			__user *tmsgs;
+	struct i2c_msg32		__user *umsgs;
+	compat_caddr_t			datap;
+	int				nmsgs, i;
+
+	if (get_user(nmsgs, &udata->nmsgs))
+		return -EFAULT;
+	if (nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+		return -EINVAL;
+
+	if (get_user(datap, &udata->msgs))
+		return -EFAULT;
+	umsgs = compat_ptr(datap);
+
+	tdata = compat_alloc_user_space(sizeof(*tdata) +
+				      nmsgs * sizeof(struct i2c_msg));
+	tmsgs = &tdata->msgs[0];
+
+	if (put_user(nmsgs, &tdata->cmd.nmsgs) ||
+	    put_user(tmsgs, &tdata->cmd.msgs))
+		return -EFAULT;
+
+	for (i = 0; i < nmsgs; i++) {
+		if (copy_in_user(&tmsgs[i].addr, &umsgs[i].addr, 3*sizeof(u16)))
+			return -EFAULT;
+		if (get_user(datap, &umsgs[i].buf) ||
+		    put_user(compat_ptr(datap), &tmsgs[i].buf))
+			return -EFAULT;
+	}
+	return i2cdev_ioctl(inode, file, cmd, (unsigned long)tdata);
+}
+
+static int do_i2c_smbus_ioctl(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct i2c_smbus_ioctl_data	__user *tdata;
+	struct i2c_smbus_ioctl_data32	__user *udata;
+	compat_caddr_t			datap;
+
+	tdata = compat_alloc_user_space(sizeof(*tdata));
+	if (tdata == NULL)
+		return -ENOMEM;
+	if (!access_ok(VERIFY_WRITE, tdata, sizeof(*tdata)))
+		return -EFAULT;
+
+	udata = compat_ptr(arg);
+	if (!access_ok(VERIFY_READ, udata, sizeof(*udata)))
+		return -EFAULT;
+
+	if (__copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
+		return -EFAULT;
+	if (__copy_in_user(&tdata->size, &udata->size, 2 * sizeof(u32)))
+		return -EFAULT;
+	if (__get_user(datap, &udata->data) ||
+	    __put_user(compat_ptr(datap), &tdata->data))
+		return -EFAULT;
+
+	return i2cdev_ioctl(inode, file, cmd, (unsigned long)tdata);
+}
+
+static long i2cdev_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int ret = -ENOIOCTLCMD;
+
+	lock_kernel();
+	switch (cmd) {
+	case I2C_FUNCS:
+		ret = do_i2c_w_long(inode, file, cmd, arg);
+		break;
+	case I2C_RDWR:
+		ret = do_i2c_rdwr_ioctl(inode, file, cmd, arg);
+		break;
+	case I2C_SMBUS:
+		ret = do_i2c_smbus_ioctl(inode, file, cmd, arg);
+		break;
+	case I2C_SLAVE:
+	case I2C_SLAVE_FORCE:
+	case I2C_TENBIT:
+	case I2C_PEC:
+	case I2C_RETRIES:
+	case I2C_TIMEOUT:
+		arg = (unsigned long) compat_ptr(arg);
+		ret = i2cdev_ioctl(inode, file, cmd, arg);
+	}
+	unlock_kernel();
+	return ret;
+}
+#endif
+
 static int i2cdev_open(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
@@ -404,6 +542,9 @@
 	.read		= i2cdev_read,
 	.write		= i2cdev_write,
 	.ioctl		= i2cdev_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= i2cdev_compat_ioctl,
+#endif
 	.open		= i2cdev_open,
 	.release	= i2cdev_release,
 };
fs/compat_ioctl.c +0 -95

107 lines not on this page · raw message

include/linux/compat_ioctl.h +0 -7
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -466,13 +466,6 @@
 COMPATIBLE_IOCTL(NBD_PRINT_DEBUG)
 ULONG_IOCTL(NBD_SET_SIZE_BLOCKS)
 COMPATIBLE_IOCTL(NBD_DISCONNECT)
-/* i2c */
-COMPATIBLE_IOCTL(I2C_SLAVE)
-COMPATIBLE_IOCTL(I2C_SLAVE_FORCE)
-COMPATIBLE_IOCTL(I2C_TENBIT)
-COMPATIBLE_IOCTL(I2C_PEC)
-COMPATIBLE_IOCTL(I2C_RETRIES)
-COMPATIBLE_IOCTL(I2C_TIMEOUT)
 /* hiddev */
 COMPATIBLE_IOCTL(HIDIOCGVERSION)
 COMPATIBLE_IOCTL(HIDIOCAPPLICATION)

--

author maintainer
#52 lore raw

PATCH 21/25 reiserfs: remove ioctl conversion code

In reply to Arnd Bergmann

An earlier patch in this series already adds a handler for this in reiserfs itself, so the code in compat_ioctl.c is no longer needed.

fs/compat_ioctl.c +0 -11
Index: linux-2.6.14-rc/fs/compat_ioctl.c
===================================================================
@@ -356,16 +356,6 @@
 #define HIDPGETCONNLIST	_IOR('H', 210, int)
 #define HIDPGETCONNINFO	_IOR('H', 211, int)
 
-#define REISERFS_IOC_UNPACK32               _IOW(0xCD,1,int)
-
-static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr)
-{
-        if (cmd == REISERFS_IOC_UNPACK32)
-                cmd = REISERFS_IOC_UNPACK;
-
-        return sys_ioctl(fd,cmd,ptr);
-}
-
 struct serial_struct32 {
         compat_int_t    type;
         compat_int_t    line;
@@ -435,7 +425,6 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
-HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
 /* Serial */
 HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
 HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)

--

author maintainer
#53 lore raw

PATCH 22/25 serial: move ioctl32 code to tty_io.c

In reply to Arnd Bergmann

All driver implementing TIOCGSERIAL are tty drivers, so the conversion handler can be part of tty_compat_ioctl.

In a perfect world, this would live in serial_core.c, but there are still a number of drivers that are not moved over to use that yet. If it were in serial_core, it could also live without the get_fs/set_fs hacks.

drivers/char/tty_io.c +78 -3
Index: linux-cg/drivers/char/tty_io.c
===================================================================
@@ -104,7 +104,6 @@
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/devfs_fs_kernel.h>
-
 #include <linux/kmod.h>
 
 #undef TTY_DEBUG_HANGUP
@@ -153,7 +152,7 @@
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
-long tty_compat_ioctl(struct file * file, unsigned int cmd, unsigned long arg);
+static long tty_compat_ioctl(struct file * file, unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_mem(struct tty_struct *tty, int idx);
 
@@ -2437,7 +2436,75 @@
 
 
 #ifdef CONFIG_COMPAT
-long tty_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#include <linux/serial.h>
+
+struct serial_struct32 {
+	compat_int_t type;
+	compat_int_t line;
+	compat_uint_t port;
+	compat_int_t irq;
+	compat_int_t flags;
+	compat_int_t xmit_fifo_size;
+	compat_int_t custom_divisor;
+	compat_int_t baud_base;
+	unsigned short close_delay;
+	char io_type;
+	char reserved_char[1];
+	compat_int_t hub6;
+	unsigned short closing_wait;	/* time to wait before closing */
+	unsigned short closing_wait2;	/* no longer used... */
+	compat_uint_t iomem_base;
+	unsigned short iomem_reg_shift;
+	unsigned int port_high;
+	/* compat_ulong_t  iomap_base FIXME */
+	compat_int_t reserved[1];
+};
+
+static int serial_struct_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	typedef struct serial_struct SS;
+	typedef struct serial_struct32 SS32;
+	struct serial_struct32 __user *ss32 = compat_ptr(arg);
+	int err;
+	struct serial_struct ss;
+	mm_segment_t oldseg = get_fs();
+	__u32 udata;
+
+	if (cmd == TIOCSSERIAL) {
+		if (!access_ok(VERIFY_READ, ss32, sizeof(SS32)))
+			return -EFAULT;
+		if (__copy_from_user
+		    (&ss, ss32, offsetof(SS32, iomem_base)))
+			return -EFAULT;
+		__get_user(udata, &ss32->iomem_base);
+		ss.iomem_base = compat_ptr(udata);
+		__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
+		__get_user(ss.port_high, &ss32->port_high);
+		ss.iomap_base = 0UL;
+	}
+	set_fs(KERNEL_DS);
+	lock_kernel();
+	err = tty_ioctl(inode, file, cmd, (unsigned long) (&ss));
+	unlock_kernel();
+	set_fs(oldseg);
+	if (cmd == TIOCGSERIAL && err >= 0) {
+		if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32)))
+			return -EFAULT;
+		if (__copy_to_user(ss32, &ss, offsetof(SS32, iomem_base)))
+			return -EFAULT;
+		__put_user((unsigned long) ss.iomem_base >> 32 ?
+			   0xffffffff : (unsigned) (unsigned long) ss.
+			   iomem_base, &ss32->iomem_base);
+		__put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
+		__put_user(ss.port_high, &ss32->port_high);
+
+	}
+	return err;
+}
+
+static long tty_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct tty_struct *tty;
@@ -2499,6 +2566,14 @@
 	/* enter the native code path for those numbers known
 	 * to be compatible */
 	switch (cmd) {
+	case TIOCGSERIAL:
+	case TIOCSSERIAL:
+		ret = serial_struct_ioctl(inode, file, cmd, arg);
+		break;
+#ifdef TIOCGLTC
+	case TIOCGLTC:
+	case TIOCSLTC:
+#endif
 	case TCFLSH:
 	case TCGETA:
 	case TCGETS:
fs/compat_ioctl.c +0 -69

80 lines not on this page · raw message

--

author maintainer
#54 lore raw

PATCH 23/25 cdrom: move ioctl32 code to drivers/cdrom/compat.c

In reply to Arnd Bergmann

All cdrom drivers use a subset of the same ioctl numbers, so the 32 bit conversion handlers can be moved to a common place.

This patch simply uses the global cdrom_compat_ioctl function as the .compat_ioctl block device operation for each of them.

Since I'm already touching pktcdvd, make that use its own ctl compat_ioctl function as well.

drivers/block/paride/pcd.c +1 -0
Index: linux-cg/drivers/block/paride/pcd.c
===================================================================
@@ -253,6 +253,7 @@
 	.open		= pcd_block_open,
 	.release	= pcd_block_release,
 	.ioctl		= pcd_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= pcd_block_media_changed,
 };
 
drivers/block/paride/pd.c +1 -0
Index: linux-cg/drivers/block/paride/pd.c
===================================================================
@@ -815,6 +815,7 @@
 	.open		= pd_open,
 	.release	= pd_release,
 	.ioctl		= pd_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= pd_check_media,
 	.revalidate_disk= pd_revalidate
 };
drivers/block/pktcdvd.c +17 -3
Index: linux-cg/drivers/block/pktcdvd.c
===================================================================
@@ -47,6 +47,7 @@
 
 #include <linux/pktcdvd.h>
 #include <linux/config.h>
+#include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -2465,6 +2466,7 @@
 	.open =			pkt_open,
 	.release =		pkt_close,
 	.ioctl =		pkt_ioctl,
+	.compat_ioctl =		cdrom_compat_ioctl,
 	.media_changed =	pkt_media_changed,
 };
 
@@ -2595,7 +2597,7 @@
 	ctrl_cmd->num_devices = MAX_WRITERS;
 }
 
-static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pkt_ctl_locked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
 	struct pkt_ctrl_command ctrl_cmd;
@@ -2636,10 +2638,22 @@
 	return ret;
 }
 
+static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	lock_kernel();
+	arg = (unsigned long) compat_ptr(arg);
+	ret = pkt_ctl_locked_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
 
 static struct file_operations pkt_ctl_fops = {
-	.ioctl	 = pkt_ctl_ioctl,
-	.owner	 = THIS_MODULE,
+	.unlocked_ioctl	= pkt_ctl_ioctl,
+	.compat_ioctl	= pkt_ctl_ioctl,
+	.owner		= THIS_MODULE,
 };
 
 static struct miscdevice pkt_misc = {
drivers/cdrom/Makefile +2 -0
Index: linux-cg/drivers/cdrom/Makefile
===================================================================
@@ -21,3 +21,5 @@
 obj-$(CONFIG_SJCD)		+= sjcd.o
 obj-$(CONFIG_CDU535)		+= sonycd535.o
 obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
+
+obj-y				+= compat.o
drivers/cdrom/aztcd.c +1 -0
Index: linux-cg/drivers/cdrom/aztcd.c
===================================================================
@@ -339,6 +339,7 @@
 	.open		= aztcd_open,
 	.release	= aztcd_release,
 	.ioctl		= aztcd_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= check_aztcd_media_change,
 };
 
drivers/cdrom/cdu31a.c +1 -0
Index: linux-cg/drivers/cdrom/cdu31a.c
===================================================================
@@ -2953,6 +2953,7 @@
 	.open		= scd_block_open,
 	.release	= scd_block_release,
 	.ioctl		= scd_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= scd_block_media_changed,
 };
 
drivers/cdrom/cm206.c +1 -0
Index: linux-cg/drivers/cdrom/cm206.c
===================================================================
@@ -1364,6 +1364,7 @@
 	.open		= cm206_block_open,
 	.release	= cm206_block_release,
 	.ioctl		= cm206_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= cm206_block_media_changed,
 };
 
drivers/cdrom/compat.c new file +163 -0

163 lines not on this page · raw message

drivers/cdrom/gscd.c +1 -0
Index: linux-cg/drivers/cdrom/gscd.c
===================================================================
@@ -155,6 +155,7 @@
 	.open		= gscd_open,
 	.release	= gscd_release,
 	.ioctl		= gscd_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= check_gscd_med_chg,
 };
 
drivers/cdrom/mcdx.c +1 -0
Index: linux-cg/drivers/cdrom/mcdx.c
===================================================================
@@ -243,6 +243,7 @@
 	.open		= mcdx_block_open,
 	.release	= mcdx_block_release,
 	.ioctl		= mcdx_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= mcdx_block_media_changed,
 };
 
drivers/cdrom/optcd.c +1 -0
Index: linux-cg/drivers/cdrom/optcd.c
===================================================================
@@ -1993,6 +1993,7 @@
 	.open		= opt_open,
 	.release	= opt_release,
 	.ioctl		= opt_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= opt_media_change,
 };
 
drivers/cdrom/sbpcd.c +1 -0
Index: linux-cg/drivers/cdrom/sbpcd.c
===================================================================
@@ -5385,6 +5385,7 @@
 	.open		= sbpcd_block_open,
 	.release	= sbpcd_block_release,
 	.ioctl		= sbpcd_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= sbpcd_block_media_changed,
 };
 /*==========================================================================*/
drivers/cdrom/sjcd.c +1 -0
Index: linux-cg/drivers/cdrom/sjcd.c
===================================================================
@@ -1646,6 +1646,7 @@
 	.open		= sjcd_open,
 	.release	= sjcd_release,
 	.ioctl		= sjcd_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= sjcd_disk_change,
 };
 
drivers/cdrom/sonycd535.c +2 -0
Index: linux-cg/drivers/cdrom/sonycd535.c
===================================================================
@@ -1,4 +1,5 @@
 /*
+	.compat_ioctl	= cdrom_compat_ioctl,
  * Sony CDU-535 interface device driver
  *
  * This is a modified version of the CDU-31A device driver (see below).
@@ -1433,6 +1434,7 @@
 	.open		= cdu_open,
 	.release	= cdu_release,
 	.ioctl		= cdu_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= cdu535_check_media_change,
 };
 
drivers/ide/ide-cd.c +1 -0
Index: linux-cg/drivers/ide/ide-cd.c
===================================================================
@@ -3421,6 +3421,7 @@
 	.open		= idecd_open,
 	.release	= idecd_release,
 	.ioctl		= idecd_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= idecd_media_changed,
 	.revalidate_disk= idecd_revalidate_disk
 };
drivers/ide/ide-floppy.c +1 -0
Index: linux-cg/drivers/ide/ide-floppy.c
===================================================================
@@ -2122,6 +2122,7 @@
 	.open		= idefloppy_open,
 	.release	= idefloppy_release,
 	.ioctl		= idefloppy_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= idefloppy_media_changed,
 	.revalidate_disk= idefloppy_revalidate_disk
 };
drivers/scsi/sr.c +1 -0
Index: linux-cg/drivers/scsi/sr.c
===================================================================
@@ -510,6 +510,7 @@
 	.open		= sr_block_open,
 	.release	= sr_block_release,
 	.ioctl		= sr_block_ioctl,
+	.compat_ioctl	= cdrom_compat_ioctl,
 	.media_changed	= sr_block_media_changed,
 	/* 
 	 * No compat_ioctl for now because sr_block_ioctl never
fs/compat_ioctl.c +0 -105

116 lines not on this page · raw message

include/linux/cdrom.h +2 -0
Index: linux-cg/include/linux/cdrom.h
===================================================================
@@ -991,6 +991,8 @@
 extern int cdrom_release(struct cdrom_device_info *cdi, struct file *fp);
 extern int cdrom_ioctl(struct file *file, struct cdrom_device_info *cdi,
 		struct inode *ip, unsigned int cmd, unsigned long arg);
+extern long cdrom_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg);
 extern int cdrom_media_changed(struct cdrom_device_info *);
 
 extern int register_cdrom(struct cdrom_device_info *cdi);
include/linux/compat_ioctl.h +0 -46

52 lines not on this page · raw message

--

author maintainer
#55 lore raw

PATCH 24/25 tape: move mtio ioctl32 code to driver/char/compat_mtio.c

In reply to Arnd Bergmann

There are currently seven drivers in linux that implement MTIO ioctl methods. This patch introduces a new file doing the conversion for compat_ioctl for all of them.

They then can all use the new compat_mtio_ioctl function as their compat_ioctl handler.

fs/compat_ioctl.c +0 -72
Index: linux-cg/fs/compat_ioctl.c
===================================================================
@@ -158,76 +158,6 @@
 }
 
 
-struct mtget32 {
-	compat_long_t	mt_type;
-	compat_long_t	mt_resid;
-	compat_long_t	mt_dsreg;
-	compat_long_t	mt_gstat;
-	compat_long_t	mt_erreg;
-	compat_daddr_t	mt_fileno;
-	compat_daddr_t	mt_blkno;
-};
-#define MTIOCGET32	_IOR('m', 2, struct mtget32)
-
-struct mtpos32 {
-	compat_long_t	mt_blkno;
-};
-#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
-
-static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	mm_segment_t old_fs = get_fs();
-	struct mtget get;
-	struct mtget32 __user *umget32;
-	struct mtpos pos;
-	struct mtpos32 __user *upos32;
-	unsigned long kcmd;
-	void *karg;
-	int err = 0;
-
-	switch(cmd) {
-	case MTIOCPOS32:
-		kcmd = MTIOCPOS;
-		karg = &pos;
-		break;
-	case MTIOCGET32:
-		kcmd = MTIOCGET;
-		karg = &get;
-		break;
-	default:
-		do {
-			static int count;
-			if (++count <= 20)
-				printk("mt_ioctl: Unknown cmd fd(%d) "
-				       "cmd(%08x) arg(%08x)\n",
-				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
-		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		return err;
-	switch (cmd) {
-	case MTIOCPOS32:
-		upos32 = compat_ptr(arg);
-		err = __put_user(pos.mt_blkno, &upos32->mt_blkno);
-		break;
-	case MTIOCGET32:
-		umget32 = compat_ptr(arg);
-		err = __put_user(get.mt_type, &umget32->mt_type);
-		err |= __put_user(get.mt_resid, &umget32->mt_resid);
-		err |= __put_user(get.mt_dsreg, &umget32->mt_dsreg);
-		err |= __put_user(get.mt_gstat, &umget32->mt_gstat);
-		err |= __put_user(get.mt_erreg, &umget32->mt_erreg);
-		err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
-		err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
-		break;
-	}
-	return err ? -EFAULT: 0;
-}
-
 static __attribute_used__ int 
 ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -257,7 +187,5 @@
 #endif
 
 #ifdef DECLARES
-HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 #undef DECLARES
 #endif
drivers/block/paride/pt.c +1 -0
Index: linux-cg/drivers/block/paride/pt.c
===================================================================
@@ -238,6 +238,7 @@
 	.read = pt_read,
 	.write = pt_write,
 	.ioctl = pt_ioctl,
+	.compat_ioctl = compat_mtio_ioctl,
 	.open = pt_open,
 	.release = pt_release,
 };
drivers/char/Makefile +1 -0
Index: linux-cg/drivers/char/Makefile
===================================================================
@@ -9,6 +9,7 @@
 
 obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
 
+obj-$(CONFIG_COMPAT)		+= compat_mtio.o
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
 obj-y				+= misc.o
drivers/char/compat_mtio.c new file +81 -0

81 lines not on this page · raw message

drivers/char/ftape/zftape/zftape-init.c +1 -0
Index: linux-cg/drivers/char/ftape/zftape/zftape-init.c
===================================================================
@@ -94,6 +94,7 @@
 	.read		= zft_read,
 	.write		= zft_write,
 	.ioctl		= zft_ioctl,
+	.compat_ioctl	= compat_mtio_ioctl,
 	.mmap		= zft_mmap,
 	.open		= zft_open,
 	.release	= zft_close,
drivers/char/viotape.c +1 -0
Index: linux-cg/drivers/char/viotape.c
===================================================================
@@ -881,6 +881,7 @@
 	read: viotap_read,
 	write: viotap_write,
 	ioctl: viotap_ioctl,
+	.compat_ioctl = compat_mtio_ioctl,
 	open: viotap_open,
 	release: viotap_release,
 };
drivers/ide/ide-tape.c +1 -0
Index: linux-cg/drivers/ide/ide-tape.c
===================================================================
@@ -4773,6 +4773,7 @@
 	.read		= idetape_chrdev_read,
 	.write		= idetape_chrdev_write,
 	.ioctl		= idetape_chrdev_ioctl,
+	.compat_ioctl	= compat_mtio_ioctl,
 	.open		= idetape_chrdev_open,
 	.release	= idetape_chrdev_release,
 };
drivers/s390/char/tape_char.c +1 -0
Index: linux-cg/drivers/s390/char/tape_char.c
===================================================================
@@ -44,6 +44,7 @@
 	.read = tapechar_read,
 	.write = tapechar_write,
 	.ioctl = tapechar_ioctl,
+	.compat_ioctl = compat_mtio_ioctl,
 	.open = tapechar_open,
 	.release = tapechar_release,
 };
drivers/scsi/osst.c +2 -0
Index: linux-cg/drivers/scsi/osst.c
===================================================================
@@ -5135,6 +5135,8 @@
 		ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
 
 	}
+	if (ret == -ENOIOCTLCMD)
+		ret = compat_mtio_ioctl(file, cmd_in, arg);
 	return ret;
 }
 #endif
drivers/scsi/st.c +2 -0
Index: linux-cg/drivers/scsi/st.c
===================================================================
@@ -3566,6 +3566,8 @@
 		ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
 
 	}
+	if (ret == -ENOIOCTLCMD)
+		ret = compat_mtio_ioctl(file, cmd, arg);
 	return ret;
 }
 #endif
include/linux/mtio.h +12 -0
Index: linux-cg/include/linux/mtio.h
===================================================================
@@ -348,4 +348,16 @@
 /* The offset for the arguments for the special HP changer load command. */
 #define MT_ST_HPLOADER_OFFSET 10000
 
+/* ioctl command conversion for 32 bit emulation */
+#ifdef __KERNEL__
+#include <linux/config.h>
+#ifdef CONFIG_COMPAT
+struct file;
+extern long compat_mtio_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg);
+#else
+#define compat_mtio_ioctl NULL
+#endif
+#endif
+
 #endif /* _LINUX_MTIO_H */
include/linux/compat_ioctl.h +0 -2
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -108,8 +108,6 @@
 COMPATIBLE_IOCTL(RTC_SET_TIME)
 COMPATIBLE_IOCTL(RTC_WKALM_SET)
 COMPATIBLE_IOCTL(RTC_WKALM_RD)
-/* Little m */
-COMPATIBLE_IOCTL(MTIOCTOP)
 /* SG stuff */
 COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
 COMPATIBLE_IOCTL(SG_GET_TIMEOUT)

--

author maintainer
#56 lore raw

PATCH 25/25 bluetooth: integrate ioctl32 handling

In reply to Arnd Bergmann

All bluetooth ioctl numbers are compatible for 32 bit, but some of them are not defined under include/linux, so we needed some hacks to make it work with compat_ioctl.

This patch moves the compat_ioctl code into the respective bluetooth device drivers for simplification.

drivers/bluetooth/hci_ldisc.c +22 -0
Index: linux-cg/drivers/bluetooth/hci_ldisc.c
===================================================================
@@ -507,6 +507,25 @@
 	return err;
 }
 
+#ifdef CONFIG_COMPAT
+static long hci_uart_tty_compat_ioctl(struct tty_struct *tty,
+		struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	switch (cmd) {
+	case HCIUARTSETPROTO:
+	case HCIUARTGETPROTO:
+		lock_kernel();
+		ret = hci_uart_tty_ioctl(tty, file, cmd, arg);
+		unlock_kernel();
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+#endif
+
 /*
  * We don't provide read/write/poll interface for user space.
  */
@@ -545,6 +564,9 @@
 	hci_uart_ldisc.read		= hci_uart_tty_read;
 	hci_uart_ldisc.write		= hci_uart_tty_write;
 	hci_uart_ldisc.ioctl		= hci_uart_tty_ioctl;
+#ifdef CONFIG_COMPAT
+	hci_uart_ldisc.compat_ioctl	= hci_uart_tty_compat_ioctl;
+#endif
 	hci_uart_ldisc.poll		= hci_uart_tty_poll;
 	hci_uart_ldisc.receive_room	= hci_uart_tty_room;
 	hci_uart_ldisc.receive_buf	= hci_uart_tty_receive;
fs/compat_ioctl.c +0 -19
Index: linux-cg/fs/compat_ioctl.c
===================================================================
@@ -164,25 +164,6 @@
 	return -EINVAL;
 }
 
-/* Bluetooth ioctls */
-#define HCIUARTSETPROTO	_IOW('U', 200, int)
-#define HCIUARTGETPROTO	_IOR('U', 201, int)
-
-#define BNEPCONNADD	_IOW('B', 200, int)
-#define BNEPCONNDEL	_IOW('B', 201, int)
-#define BNEPGETCONNLIST	_IOR('B', 210, int)
-#define BNEPGETCONNINFO	_IOR('B', 211, int)
-
-#define CMTPCONNADD	_IOW('C', 200, int)
-#define CMTPCONNDEL	_IOW('C', 201, int)
-#define CMTPGETCONNLIST	_IOR('C', 210, int)
-#define CMTPGETCONNINFO	_IOR('C', 211, int)
-
-#define HIDPCONNADD	_IOW('H', 200, int)
-#define HIDPCONNDEL	_IOW('H', 201, int)
-#define HIDPGETCONNLIST	_IOR('H', 210, int)
-#define HIDPGETCONNINFO	_IOR('H', 211, int)
-
 #undef CODE
 #endif
 
include/linux/compat_ioctl.h +0 -36
Index: linux-cg/include/linux/compat_ioctl.h
===================================================================
@@ -350,43 +350,7 @@
 COMPATIBLE_IOCTL(RNDZAPENTCNT)
 COMPATIBLE_IOCTL(RNDCLEARPOOL)
 /* Bluetooth */
-COMPATIBLE_IOCTL(HCIDEVUP)
-COMPATIBLE_IOCTL(HCIDEVDOWN)
-COMPATIBLE_IOCTL(HCIDEVRESET)
-COMPATIBLE_IOCTL(HCIDEVRESTAT)
-COMPATIBLE_IOCTL(HCIGETDEVLIST)
-COMPATIBLE_IOCTL(HCIGETDEVINFO)
-COMPATIBLE_IOCTL(HCIGETCONNLIST)
-COMPATIBLE_IOCTL(HCIGETCONNINFO)
-COMPATIBLE_IOCTL(HCISETRAW)
-COMPATIBLE_IOCTL(HCISETSCAN)
-COMPATIBLE_IOCTL(HCISETAUTH)
-COMPATIBLE_IOCTL(HCISETENCRYPT)
-COMPATIBLE_IOCTL(HCISETPTYPE)
-COMPATIBLE_IOCTL(HCISETLINKPOL)
-COMPATIBLE_IOCTL(HCISETLINKMODE)
-COMPATIBLE_IOCTL(HCISETACLMTU)
-COMPATIBLE_IOCTL(HCISETSCOMTU)
-COMPATIBLE_IOCTL(HCIINQUIRY)
-COMPATIBLE_IOCTL(HCIUARTSETPROTO)
-COMPATIBLE_IOCTL(HCIUARTGETPROTO)
-COMPATIBLE_IOCTL(RFCOMMCREATEDEV)
-COMPATIBLE_IOCTL(RFCOMMRELEASEDEV)
-COMPATIBLE_IOCTL(RFCOMMGETDEVLIST)
-COMPATIBLE_IOCTL(RFCOMMGETDEVINFO)
 COMPATIBLE_IOCTL(RFCOMMSTEALDLC)
-COMPATIBLE_IOCTL(BNEPCONNADD)
-COMPATIBLE_IOCTL(BNEPCONNDEL)
-COMPATIBLE_IOCTL(BNEPGETCONNLIST)
-COMPATIBLE_IOCTL(BNEPGETCONNINFO)
-COMPATIBLE_IOCTL(CMTPCONNADD)
-COMPATIBLE_IOCTL(CMTPCONNDEL)
-COMPATIBLE_IOCTL(CMTPGETCONNLIST)
-COMPATIBLE_IOCTL(CMTPGETCONNINFO)
-COMPATIBLE_IOCTL(HIDPCONNADD)
-COMPATIBLE_IOCTL(HIDPCONNDEL)
-COMPATIBLE_IOCTL(HIDPGETCONNLIST)
-COMPATIBLE_IOCTL(HIDPGETCONNINFO)
 /* CAPI */
 COMPATIBLE_IOCTL(CAPI_REGISTER)
 COMPATIBLE_IOCTL(CAPI_GET_MANUFACTURER)
net/bluetooth/bnep/sock.c +1 -0
Index: linux-cg/net/bluetooth/bnep/sock.c
===================================================================
@@ -151,6 +151,7 @@
 	.owner      = THIS_MODULE,
 	.release    = bnep_sock_release,
 	.ioctl      = bnep_sock_ioctl,
+	.compat_ioctl = bnep_sock_ioctl,
 	.bind       = sock_no_bind,
 	.getname    = sock_no_getname,
 	.sendmsg    = sock_no_sendmsg,
net/bluetooth/cmtp/sock.c +1 -0
Index: linux-cg/net/bluetooth/cmtp/sock.c
===================================================================
@@ -142,6 +142,7 @@
 	.owner		= THIS_MODULE,
 	.release	= cmtp_sock_release,
 	.ioctl		= cmtp_sock_ioctl,
+	.compat_ioctl	= cmtp_sock_ioctl,
 	.bind		= sock_no_bind,
 	.getname	= sock_no_getname,
 	.sendmsg	= sock_no_sendmsg,
net/bluetooth/hci_sock.c +1 -0
Index: linux-cg/net/bluetooth/hci_sock.c
===================================================================
@@ -584,6 +584,7 @@
 	.sendmsg	= hci_sock_sendmsg,
 	.recvmsg	= hci_sock_recvmsg,
 	.ioctl		= hci_sock_ioctl,
+	.compat_ioctl	= hci_sock_ioctl,
 	.poll		= datagram_poll,
 	.listen		= sock_no_listen,
 	.shutdown	= sock_no_shutdown,
net/bluetooth/hidp/sock.c +1 -0
Index: linux-cg/net/bluetooth/hidp/sock.c
===================================================================
@@ -148,6 +148,7 @@
 	.owner		= THIS_MODULE,
 	.release	= hidp_sock_release,
 	.ioctl		= hidp_sock_ioctl,
+	.compat_ioctl	= hidp_sock_ioctl,
 	.bind		= sock_no_bind,
 	.getname	= sock_no_getname,
 	.sendmsg	= sock_no_sendmsg,
net/bluetooth/rfcomm/sock.c +1 -0
Index: linux-cg/net/bluetooth/rfcomm/sock.c
===================================================================
@@ -986,6 +986,7 @@
 	.setsockopt	= rfcomm_sock_setsockopt,
 	.getsockopt	= rfcomm_sock_getsockopt,
 	.ioctl		= rfcomm_sock_ioctl,
+	.compat_ioctl	= rfcomm_sock_ioctl,
 	.poll		= bt_sock_poll,
 	.socketpair	= sock_no_socketpair,
 	.mmap		= sock_no_mmap

--