2987 lines · 83.6 KB · C
RawDownload
/* * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com) * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be) * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs  * Copyright (C) 2003       Pavel Machek (pavel@suse.cz) * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. */ #include <linux/config.h>#include <linux/types.h>#include <linux/compat.h>#include <linux/kernel.h>#include <linux/capability.h>#include <linux/compiler.h>#include <linux/sched.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/ioctl.h>#include <linux/if.h>#include <linux/if_bridge.h>#include <linux/slab.h>#include <linux/hdreg.h>#include <linux/raid/md.h>#include <linux/kd.h>#include <linux/dirent.h>#include <linux/route.h>#include <linux/in6.h>#include <linux/ipv6_route.h>#include <linux/skbuff.h>#include <linux/netlink.h>#include <linux/vt.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/fd.h>#include <linux/ppp_defs.h>#include <linux/if_ppp.h>#include <linux/if_pppox.h>#include <linux/mtio.h>#include <linux/cdrom.h>#include <linux/loop.h>#include <linux/auto_fs.h>#include <linux/auto_fs4.h>#include <linux/devfs_fs.h>#include <linux/tty.h>#include <linux/vt_kern.h>#include <linux/fb.h>#include <linux/ext2_fs.h>#include <linux/ext3_jbd.h>#include <linux/ext3_fs.h>#include <linux/videodev.h>#include <linux/netdevice.h>#include <linux/raw.h>#include <linux/smb_fs.h>#include <linux/blkpg.h>#include <linux/blkdev.h>#include <linux/elevator.h>#include <linux/rtc.h>#include <linux/pci.h>#include <linux/module.h>#include <linux/serial.h>#include <linux/reiserfs_fs.h>#include <linux/if_tun.h>#include <linux/ctype.h>#include <linux/ioctl32.h>#include <linux/syscalls.h>#include <linux/ncp_fs.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>#include <linux/wireless.h>#include <linux/atalk.h>#include <linux/blktrace_api.h> #include <net/sock.h>          /* siocdevprivate_ioctl */#include <net/bluetooth/bluetooth.h>#include <net/bluetooth/hci.h>#include <net/bluetooth/rfcomm.h> #include <linux/capi.h> #include <scsi/scsi.h>#include <scsi/scsi_ioctl.h>#include <scsi/sg.h> #include <asm/uaccess.h>#include <linux/ethtool.h>#include <linux/mii.h>#include <linux/if_bonding.h>#include <linux/watchdog.h>#include <linux/dm-ioctl.h> #include <linux/soundcard.h>#include <linux/lp.h>#include <linux/ppdev.h> #include <linux/atm.h>#include <linux/atmarp.h>#include <linux/atmclip.h>#include <linux/atmdev.h>#include <linux/atmioc.h>#include <linux/atmlec.h>#include <linux/atmmpc.h>#include <linux/atmsvc.h>#include <linux/atm_tcp.h>#include <linux/sonet.h>#include <linux/atm_suni.h>#include <linux/mtd/mtd.h> #include <linux/usb.h>#include <linux/usbdevice_fs.h>#include <linux/nbd.h>#include <linux/random.h>#include <linux/filter.h>#include <linux/msdos_fs.h>#include <linux/pktcdvd.h> #include <linux/hiddev.h> #include <linux/dvb/audio.h>#include <linux/dvb/dmx.h>#include <linux/dvb/frontend.h>#include <linux/dvb/video.h>#include <linux/lp.h> /* 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 EXT3_IOC32_GETVERSION             _IOR('f', 3, int)#define EXT3_IOC32_SETVERSION             _IOW('f', 4, int)#define EXT3_IOC32_GETRSVSZ               _IOR('f', 5, int)#define EXT3_IOC32_SETRSVSZ               _IOW('f', 6, int)#define EXT3_IOC32_GROUP_EXTEND           _IOW('f', 7, unsigned int)#ifdef CONFIG_JBD_DEBUG#define EXT3_IOC32_WAIT_FOR_READONLY      _IOR('f', 99, int)#endif #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int) static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,			      unsigned long arg, struct file *f){	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));} static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg){	mm_segment_t old_fs = get_fs();	int err;	unsigned long val;		set_fs (KERNEL_DS);	err = sys_ioctl(fd, cmd, (unsigned long)&val);	set_fs (old_fs);	if (!err && put_user(val, (u32 __user *)compat_ptr(arg)))		return -EFAULT;	return err;} static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg){	mm_segment_t old_fs = get_fs();	u32 __user *argptr = compat_ptr(arg);	int err;	unsigned long val;		if(get_user(val, argptr))		return -EFAULT;	set_fs (KERNEL_DS);	err = sys_ioctl(fd, cmd, (unsigned long)&val);	set_fs (old_fs);	if (!err && put_user(val, argptr))		return -EFAULT;	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));} static int do_ext3_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 EXT3_IOC32_GETVERSION: cmd = EXT3_IOC_GETVERSION; break;	case EXT3_IOC32_SETVERSION: cmd = EXT3_IOC_SETVERSION; break;	case EXT3_IOC32_GETRSVSZ: cmd = EXT3_IOC_GETRSVSZ; break;	case EXT3_IOC32_SETRSVSZ: cmd = EXT3_IOC_SETRSVSZ; break;	case EXT3_IOC32_GROUP_EXTEND: cmd = EXT3_IOC_GROUP_EXTEND; break;#ifdef CONFIG_JBD_DEBUG	case EXT3_IOC32_WAIT_FOR_READONLY: cmd = EXT3_IOC_WAIT_FOR_READONLY; break;#endif	}	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));} struct compat_dmx_event {	dmx_event_t	event;	compat_time_t	timeStamp;	union	{		dmx_scrambling_status_t scrambling;	} u;}; static int do_dmx_get_event(unsigned int fd, unsigned int cmd, unsigned long arg){	struct dmx_event kevent;	mm_segment_t old_fs = get_fs();	int err; 	set_fs(KERNEL_DS);	err = sys_ioctl(fd, cmd, (unsigned long) &kevent);	set_fs(old_fs); 	if (!err) {		struct compat_dmx_event __user *up = compat_ptr(arg); 		err  = put_user(kevent.event, &up->event);		err |= put_user(kevent.timeStamp, &up->timeStamp);		err |= put_user(kevent.u.scrambling, &up->u.scrambling);		if (err)			err = -EFAULT;	} 	return err;} struct compat_video_event {	int32_t		type;	compat_time_t	timestamp;	union {	        video_size_t size;		unsigned int frame_rate;	} u;}; static int do_video_get_event(unsigned int fd, unsigned int cmd, unsigned long arg){	struct video_event kevent;	mm_segment_t old_fs = get_fs();	int err; 	set_fs(KERNEL_DS);	err = sys_ioctl(fd, cmd, (unsigned long) &kevent);	set_fs(old_fs); 	if (!err) {		struct compat_video_event __user *up = compat_ptr(arg); 		err  = put_user(kevent.type, &up->type);		err |= put_user(kevent.timestamp, &up->timestamp);		err |= put_user(kevent.u.size.w, &up->u.size.w);		err |= put_user(kevent.u.size.h, &up->u.size.h);		err |= put_user(kevent.u.size.aspect_ratio,				&up->u.size.aspect_ratio);		if (err)			err = -EFAULT;	} 	return err;} struct compat_video_still_picture {        compat_uptr_t iFrame;        int32_t size;}; static int do_video_stillpicture(unsigned int fd, unsigned int cmd, unsigned long arg){	struct compat_video_still_picture __user *up;	struct video_still_picture __user *up_native;	compat_uptr_t fp;	int32_t size;	int err; 	up = (struct compat_video_still_picture __user *) arg;	err  = get_user(fp, &up->iFrame);	err |= get_user(size, &up->size);	if (err)		return -EFAULT; 	up_native =		compat_alloc_user_space(sizeof(struct video_still_picture)); 	put_user(compat_ptr(fp), &up_native->iFrame);	put_user(size, &up_native->size); 	err = sys_ioctl(fd, cmd, (unsigned long) up_native); 	return err;} struct compat_video_spu_palette {	int length;	compat_uptr_t palette;}; static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned long arg){	struct compat_video_spu_palette __user *up;	struct video_spu_palette __user *up_native;	compat_uptr_t palp;	int length, err; 	up = (struct compat_video_spu_palette __user *) arg;	err  = get_user(palp, &up->palette);	err |= get_user(length, &up->length); 	up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));	put_user(compat_ptr(palp), &up_native->palette);	put_user(length, &up_native->length); 	err = sys_ioctl(fd, cmd, (unsigned long) up_native); 	return err;} #ifdef CONFIG_NETstatic 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 + sizeof (struct ifreq32) <= 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 {		ifc32.ifc_len = i;	}	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;

Lines 1–500 of 2987.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t