1628 lines · 45.2 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@ucw.cz) * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. */ #include <linux/joystick.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/ioctl.h>#include <linux/if.h>#include <linux/if_bridge.h>#include <linux/raid/md_u.h>#include <linux/kd.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/falloc.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/ppp_defs.h>#include <linux/ppp-ioctl.h>#include <linux/if_pppox.h>#include <linux/mtio.h>#include <linux/auto_fs.h>#include <linux/auto_fs4.h>#include <linux/tty.h>#include <linux/vt_kern.h>#include <linux/fb.h>#include <linux/videodev2.h>#include <linux/netdevice.h>#include <linux/raw.h>#include <linux/blkdev.h>#include <linux/elevator.h>#include <linux/rtc.h>#include <linux/pci.h>#include <linux/serial.h>#include <linux/if_tun.h>#include <linux/ctype.h>#include <linux/syscalls.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>#include <linux/atalk.h>#include <linux/gfp.h> #include <net/bluetooth/bluetooth.h>#include <net/bluetooth/hci.h>#include <net/bluetooth/rfcomm.h> #include <linux/capi.h>#include <linux/gigaset_dev.h> #ifdef CONFIG_BLOCK#include <linux/loop.h>#include <linux/cdrom.h>#include <linux/fd.h>#include <scsi/scsi.h>#include <scsi/scsi_ioctl.h>#include <scsi/sg.h>#endif #include <asm/uaccess.h>#include <linux/ethtool.h>#include <linux/mii.h>#include <linux/if_bonding.h>#include <linux/watchdog.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/usb.h>#include <linux/usbdevice_fs.h>#include <linux/nbd.h>#include <linux/random.h>#include <linux/filter.h> #include <linux/hiddev.h> #define __DVB_CORE__#include <linux/dvb/audio.h>#include <linux/dvb/dmx.h>#include <linux/dvb/frontend.h>#include <linux/dvb/video.h> #include <linux/sort.h> #ifdef CONFIG_SPARC#include <asm/fbio.h>#endif static int w_long(unsigned int fd, unsigned int cmd,		compat_ulong_t __user *argp){	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, argp))		return -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,		struct compat_video_event __user *up){	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) {		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,	struct compat_video_still_picture __user *up){	struct video_still_picture __user *up_native;	compat_uptr_t fp;	int32_t size;	int err; 	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)); 	err =  put_user(compat_ptr(fp), &up_native->iFrame);	err |= put_user(size, &up_native->size);	if (err)		return -EFAULT; 	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,		struct compat_video_spu_palette __user *up){	struct video_spu_palette __user *up_native;	compat_uptr_t palp;	int length, err; 	err  = get_user(palp, &up->palette);	err |= get_user(length, &up->length); 	up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));	err  = put_user(compat_ptr(palp), &up_native->palette);	err |= put_user(length, &up_native->length);	if (err)		return -EFAULT; 	err = sys_ioctl(fd, cmd, (unsigned long) up_native); 	return err;} #ifdef CONFIG_BLOCKtypedef 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(unsigned int fd, unsigned int cmd,			sg_io_hdr32_t __user *sgio32){	sg_io_hdr_t __user *sgio;	u16 iovec_count;	u32 data;	void __user *dxferp;	int err;	int interface_id; 	if (get_user(interface_id, &sgio32->interface_id))		return -EFAULT;	if (interface_id != 'S')		return sys_ioctl(fd, cmd, (unsigned long)sgio32); 	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; 	err = sys_ioctl(fd, cmd, (unsigned long) sgio); 	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;} struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */	char req_state;	char orphan;	char sg_io_owned;	char problem;	int pack_id;	compat_uptr_t usr_ptr;	unsigned int duration;	int unused;}; static int sg_grt_trans(unsigned int fd, unsigned int cmd, struct			compat_sg_req_info __user *o){	int err, i;	sg_req_info_t __user *r;	r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE);	err = sys_ioctl(fd,cmd,(unsigned long)r);	if (err < 0)		return err;	for (i = 0; i < SG_MAX_QUEUE; i++) {		void __user *ptr;		int d; 		if (copy_in_user(o + i, r + i, offsetof(sg_req_info_t, usr_ptr)) ||		    get_user(ptr, &r[i].usr_ptr) ||		    get_user(d, &r[i].duration) ||		    put_user((u32)(unsigned long)(ptr), &o[i].usr_ptr) ||		    put_user(d, &o[i].duration))			return -EFAULT;	}	return err;}#endif /* CONFIG_BLOCK */ 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,			struct sock_fprog32 __user *u_fprog32){	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,		struct ppp_idle32 __user *idle32){	struct ppp_idle __user *idle;	__kernel_time_t xmit, recv;	int err; 	idle = compat_alloc_user_space(sizeof(*idle)); 	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,	struct ppp_option_data32 __user *odata32){	struct ppp_option_data __user *odata;	__u32 data;	void __user *datap; 	odata = compat_alloc_user_space(sizeof(*odata)); 	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);} #ifdef CONFIG_BLOCKstruct mtget32 {	compat_long_t	mt_type;	compat_long_t	mt_resid;

Lines 1–500 of 1628.

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