Index: include/asm-ia64/uaccess.h =================================================================== --- include/asm-ia64/uaccess.h (revision 12202) +++ include/asm-ia64/uaccess.h (working copy) @@ -240,6 +240,18 @@ __cu_len; \ }) +#define __copy_in_user(to, from, size) \ + __copy_user((to), (from), (size)) + +static inline unsigned long +copy_in_user(void *to, const void *from, unsigned long n) +{ + if(likely(access_ok(VERIFY_READ, from, n) && + access_ok(VERIFY_WRITE, to, n))) + n = __copy_user(to, from, n); + return n; +} + extern unsigned long __do_clear_user (void *, unsigned long); #define __clear_user(to,n) \ Index: include/asm-ia64/compat.h =================================================================== --- include/asm-ia64/compat.h (revision 12202) +++ include/asm-ia64/compat.h (working copy) @@ -133,7 +133,7 @@ compat_alloc_user_space (long len) { struct pt_regs *regs = ia64_task_regs(current); - return (void *) ((regs->r12 & -16) - len); + return (void *) (((regs->r12 & 0xffffffff) & -16) - len); } #endif /* _ASM_IA64_COMPAT_H */ Index: arch/ia64/ia32/ia32_ioctl.c =================================================================== --- arch/ia64/ia32/ia32_ioctl.c (revision 12202) +++ arch/ia64/ia32/ia32_ioctl.c (working copy) @@ -7,111 +7,13 @@ * David Mosberger-Tang */ -#include -#include -#include /* argh, msdos_fs.h isn't self-contained... */ #include /* argh, msdos_fs.h isn't self-contained... */ -#include - #include "ia32priv.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -/* Ugly hack. */ -#undef __KERNEL__ -#include -#define __KERNEL__ -#include - -#include -#include -#include -#include -#include -#include - -#include + +#define INCLUDES +#include "compat_ioctl.c" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include <../drivers/char/drm/drm.h> -#include <../drivers/char/drm/mga_drm.h> -#include <../drivers/char/drm/i810_drm.h> - #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) #define DO_IOCTL(fd, cmd, arg) ({ \ @@ -128,6 +30,9 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); +#define CODE +#include "compat_ioctl.c" + #define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct linux32_dirent[2]) #define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct linux32_dirent[2]) @@ -158,298 +63,6 @@ return ret; } -/* - * The transform code for the SG_IO ioctl was brazenly lifted from - * the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'. - * Thanks to Jakub Jelinek & Eddie C. Dost. - */ -typedef struct sg_io_hdr32 { - int interface_id; /* [i] 'S' for SCSI generic (required) */ - int dxfer_direction; /* [i] data transfer direction */ - char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - char mx_sb_len; /* [i] max length to write to sbp */ - short iovec_count; /* [i] 0 implies no scatter gather */ - int dxfer_len; /* [i] byte count of data transfer */ - int dxferp; /* [i], [*io] points to data transfer memory - or scatter gather list */ - int cmdp; /* [i], [*i] points to command to perform */ - int sbp; /* [i], [*o] points to sense_buffer memory */ - int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - int flags; /* [i] 0 -> default, see SG_FLAG... */ - int pack_id; /* [i->o] unused internally (normally) */ - int usr_ptr; /* [i->o] unused internally */ - char status; /* [o] scsi status */ - char masked_status; /* [o] shifted, masked scsi status */ - char msg_status; /* [o] messaging level data (optional) */ - char sb_len_wr; /* [o] byte count actually written to sbp */ - short host_status; /* [o] errors from host adapter */ - short driver_status; /* [o] errors from software driver */ - int resid; /* [o] dxfer_len - actual_transferred */ - int duration; /* [o] time taken by cmd (unit: millisec) */ - int info; /* [o] auxiliary information */ -} sg_io_hdr32_t; /* 64 bytes long (on IA32) */ - -static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32) -{ - struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); - sg_iovec_t *kiov; - int i; - - sgp->dxferp = kmalloc(sgp->iovec_count * - sizeof(sg_iovec_t), GFP_KERNEL); - if (!sgp->dxferp) - return -ENOMEM; - memset(sgp->dxferp, 0, - sgp->iovec_count * sizeof(sg_iovec_t)); - - kiov = (sg_iovec_t *) sgp->dxferp; - for (i = 0; i < sgp->iovec_count; i++) { - int iov_base32; - if (__get_user(iov_base32, &uiov->iov_base) || - __get_user(kiov->iov_len, &uiov->iov_len)) - return -EFAULT; - - kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); - if (!kiov->iov_base) - return -ENOMEM; - if (copy_from_user(kiov->iov_base, - (void *) P(iov_base32), - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32) -{ - struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - int iov_base32; - - if (__get_user(iov_base32, &uiov->iov_base)) - return -EFAULT; - - if (copy_to_user((void *) P(iov_base32), - kiov->iov_base, - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static void free_sg_iovec(sg_io_hdr_t *sgp) -{ - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - if (kiov->iov_base) { - kfree(kiov->iov_base); - kiov->iov_base = NULL; - } - kiov++; - } - kfree(sgp->dxferp); - sgp->dxferp = NULL; -} - -static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - sg_io_hdr32_t *sg_io32; - sg_io_hdr_t sg_io64; - int dxferp32, cmdp32, sbp32; - mm_segment_t old_fs; - int err = 0; - - sg_io32 = (sg_io_hdr32_t *)arg; - err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); - err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); - err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); - err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); - err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); - err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); - err |= __get_user(sg_io64.timeout, &sg_io32->timeout); - err |= __get_user(sg_io64.flags, &sg_io32->flags); - err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); - - sg_io64.dxferp = NULL; - sg_io64.cmdp = NULL; - sg_io64.sbp = NULL; - - err |= __get_user(cmdp32, &sg_io32->cmdp); - sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); - if (!sg_io64.cmdp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.cmdp, - (void *) P(cmdp32), - sg_io64.cmd_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(sbp32, &sg_io32->sbp); - sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); - if (!sg_io64.sbp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.sbp, - (void *) P(sbp32), - sg_io64.mx_sb_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(dxferp32, &sg_io32->dxferp); - if (sg_io64.iovec_count) { - int ret; - - if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { - err = ret; - goto out; - } - } else { - sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); - if (!sg_io64.dxferp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.dxferp, - (void *) P(dxferp32), - sg_io64.dxfer_len)) { - err = -EFAULT; - goto out; - } - } - - /* Unused internally, do not even bother to copy it over. */ - sg_io64.usr_ptr = NULL; - - if (err) - return -EFAULT; - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); - set_fs (old_fs); - - if (err < 0) - goto out; - - err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); - err |= __put_user(sg_io64.status, &sg_io32->status); - err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); - err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); - err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); - err |= __put_user(sg_io64.host_status, &sg_io32->host_status); - err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); - err |= __put_user(sg_io64.resid, &sg_io32->resid); - err |= __put_user(sg_io64.duration, &sg_io32->duration); - err |= __put_user(sg_io64.info, &sg_io32->info); - err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) - err |= copy_back_sg_iovec(&sg_io64, dxferp32); - else - err |= copy_to_user((void *)P(dxferp32), - sg_io64.dxferp, - sg_io64.dxfer_len); - } - if (err) - err = -EFAULT; - -out: - if (sg_io64.cmdp) - kfree(sg_io64.cmdp); - if (sg_io64.sbp) - kfree(sg_io64.sbp); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) { - free_sg_iovec(&sg_io64); - } else { - kfree(sg_io64.dxferp); - } - } - return err; -} - -static __inline__ void *alloc_user_space(long len) -{ - struct pt_regs *regs = ((struct pt_regs *)((unsigned long) current + - IA64_STK_OFFSET)) - 1; - return (void *)regs->r12 - len; -} - -struct ifmap32 { - u32 mem_start; - u32 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; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - char ifru_newname[IFNAMSIZ]; - compat_caddr_t ifru_data; - } ifr_ifru; -}; - -int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq *u_ifreq64; - struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; - char tmp_buf[IFNAMSIZ]; - void *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 = (void *) P(data32); - - u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); - - /* Don't check these user accesses, just let that get trapped - * in the ioctl handler instead. - */ - copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); - __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); - - return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); -} - typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) @@ -460,8 +73,9 @@ }; struct ioctl_trans ioctl_end[0]; IOCTL_TABLE_START -#include HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) -HANDLE_IOCTL(SG_IO,sg_ioctl_trans) +#define DECLARES +#include "compat_ioctl.c" +#include IOCTL_TABLE_END Index: arch/ia64/ia32/Makefile =================================================================== --- arch/ia64/ia32/Makefile (revision 12202) +++ arch/ia64/ia32/Makefile (working copy) @@ -4,3 +4,5 @@ obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o \ ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o + +CFLAGS_ia32_ioctl.o += -Ifs/