X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcompat_ioctl.c;h=c81c958b3e1d00c4ad22909b43d1d084961aadd3;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=56ef9138e9cc1f5729d479fe2ccb7c04c92b1e6f;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 56ef9138e..c81c958b3 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -10,16 +10,17 @@ * ioctls. */ -#ifdef INCLUDES -#include #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -39,14 +40,11 @@ #include #include #include -#include #include #include -#include #include #include #include -#include #include #include #include @@ -58,15 +56,15 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include +#include +#include #include /* siocdevprivate_ioctl */ #include @@ -74,15 +72,12 @@ #include #include +#include #include -/* Ugly hack. */ -#undef __KERNEL__ #include -#define __KERNEL__ #include -#include #include #include #include @@ -90,9 +85,9 @@ #include #include -#include #include #include +#include #include #include @@ -112,18 +107,21 @@ #include #include #include -#include +#include -#undef INCLUDES -#endif +#include -#ifdef CODE +#include +#include +#include +#include +#include -/* 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 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) { @@ -134,7 +132,7 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); - if (!err && put_user(val, (u32 *)compat_ptr(arg))) + if (!err && put_user(val, (u32 __user *)compat_ptr(arg))) return -EFAULT; return err; } @@ -142,7 +140,7 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); - u32 *argptr = compat_ptr(arg); + u32 __user *argptr = compat_ptr(arg); int err; unsigned long val; @@ -156,262 +154,104 @@ static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) 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 video_tuner32 { - compat_int_t tuner; - char name[32]; - compat_ulong_t rangelow, rangehigh; - u32 flags; /* It is really u32 in videodev.h */ - u16 mode, signal; +struct compat_video_event { + int32_t type; + compat_time_t timestamp; + union { + video_size_t size; + unsigned int frame_rate; + } u; }; -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) +static int do_video_get_event(unsigned int fd, unsigned int cmd, unsigned long arg) { - int i; + struct video_event kevent; + mm_segment_t old_fs = get_fs(); + int err; - if(get_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __get_user(kp->name[i], &up->name[i]); - __get_user(kp->rangelow, &up->rangelow); - __get_user(kp->rangehigh, &up->rangehigh); - __get_user(kp->flags, &up->flags); - __get_user(kp->mode, &up->mode); - __get_user(kp->signal, &up->signal); - return 0; -} + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long) &kevent); + set_fs(old_fs); -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) -{ - int i; + 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; + } - if(put_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __put_user(kp->name[i], &up->name[i]); - __put_user(kp->rangelow, &up->rangelow); - __put_user(kp->rangehigh, &up->rangehigh); - __put_user(kp->flags, &up->flags); - __put_user(kp->mode, &up->mode); - __put_user(kp->signal, &up->signal); - return 0; + return err; } -struct video_buffer32 { - compat_caddr_t base; - compat_int_t height, width, depth, bytesperline; +struct compat_video_still_picture { + compat_uptr_t iFrame; + int32_t size; }; -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) -{ - u32 tmp; - - if(get_user(tmp, &up->base)) - return -EFAULT; - kp->base = compat_ptr(tmp); - __get_user(kp->height, &up->height); - __get_user(kp->width, &up->width); - __get_user(kp->depth, &up->depth); - __get_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) +static int do_video_stillpicture(unsigned int fd, unsigned int cmd, unsigned long arg) { - u32 tmp = (u32)((unsigned long)kp->base); + struct compat_video_still_picture __user *up; + struct video_still_picture __user *up_native; + compat_uptr_t fp; + int32_t size; + int err; - if(put_user(tmp, &up->base)) + up = (struct compat_video_still_picture __user *) arg; + err = get_user(fp, &up->iFrame); + err |= get_user(size, &up->size); + if (err) return -EFAULT; - __put_user(kp->height, &up->height); - __put_user(kp->width, &up->width); - __put_user(kp->depth, &up->depth); - __put_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -struct video_clip32 { - s32 x, y, width, height; /* Its really s32 in videodev.h */ - compat_caddr_t next; -}; - -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - compat_caddr_t clips; - compat_int_t clipcount; -}; - -static void free_kvideo_clips(struct video_window *kp) -{ - struct video_clip *cp; - - cp = kp->clips; - if(cp != NULL) - kfree(cp); -} -static int get_video_window32(struct video_window *kp, struct video_window32 *up) -{ - struct video_clip32 *ucp; - struct video_clip *kcp; - int nclips, err, i; - u32 tmp; + up_native = + compat_alloc_user_space(sizeof(struct video_still_picture)); - if(get_user(kp->x, &up->x)) + err = put_user(compat_ptr(fp), &up_native->iFrame); + err |= put_user(size, &up_native->size); + if (err) return -EFAULT; - __get_user(kp->y, &up->y); - __get_user(kp->width, &up->width); - __get_user(kp->height, &up->height); - __get_user(kp->chromakey, &up->chromakey); - __get_user(kp->flags, &up->flags); - __get_user(kp->clipcount, &up->clipcount); - __get_user(tmp, &up->clips); - ucp = compat_ptr(tmp); - kp->clips = NULL; - - nclips = kp->clipcount; - if(nclips == 0) - return 0; - - if(ucp == 0) - return -EINVAL; - - /* Peculiar interface... */ - if(nclips < 0) - nclips = VIDEO_CLIPMAP_SIZE; - - kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); - err = -ENOMEM; - if(kcp == NULL) - goto cleanup_and_err; - - kp->clips = kcp; - for(i = 0; i < nclips; i++) { - __get_user(kcp[i].x, &ucp[i].x); - __get_user(kcp[i].y, &ucp[i].y); - __get_user(kcp[i].width, &ucp[i].width); - __get_user(kcp[i].height, &ucp[i].height); - kcp[nclips].next = NULL; - } - return 0; + err = sys_ioctl(fd, cmd, (unsigned long) up_native); -cleanup_and_err: - free_kvideo_clips(kp); return err; } -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 *up) -{ - if(put_user(kp->x, &up->x)) - return -EFAULT; - __put_user(kp->y, &up->y); - __put_user(kp->width, &up->width); - __put_user(kp->height, &up->height); - __put_user(kp->chromakey, &up->chromakey); - __put_user(kp->flags, &up->flags); - __put_user(kp->clipcount, &up->clipcount); - return 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) +struct compat_video_spu_palette { + int length; + compat_uptr_t palette; +}; -static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned long arg) { - union { - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - unsigned long vx; - } karg; - mm_segment_t old_fs = get_fs(); - void *up = compat_ptr(arg); - int err = 0; - - /* First, convert the command. */ - switch(cmd) { - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - }; - - switch(cmd) { - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - break; - - case VIDIOCSWIN: - err = get_video_window32(&karg.vw, up); - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 *)up); - break; - }; - if(err) - goto out; + struct compat_video_spu_palette __user *up; + struct video_spu_palette __user *up_native; + compat_uptr_t palp; + int length, err; - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if(cmd == VIDIOCSWIN) - free_kvideo_clips(&karg.vw); - - if(err == 0) { - switch(cmd) { - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; + up = (struct compat_video_spu_palette __user *) arg; + err = get_user(palp, &up->palette); + err |= get_user(length, &up->length); - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; + 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; - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; + err = sys_ioctl(fd, cmd, (unsigned long) up_native); - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 *)up); - break; - }; - } -out: return err; } +#ifdef CONFIG_NET static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct compat_timeval *up = compat_ptr(arg); + struct compat_timeval __user *up = compat_ptr(arg); struct timeval ktv; mm_segment_t old_fs = get_fs(); int err; @@ -463,7 +303,6 @@ struct ifconf32 { compat_caddr_t ifcbuf; }; -#ifdef CONFIG_NET static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) { struct net_device *dev; @@ -483,89 +322,82 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32)); return (err ? -EFAULT : 0); } -#endif static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifconf32 ifc32; struct ifconf ifc; - struct ifreq32 *ifr32; - struct ifreq *ifr; - mm_segment_t old_fs; + 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) { + if (ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; - ifc.ifc_buf = NULL; + ifc.ifc_req = NULL; + uifc = compat_alloc_user_space(sizeof(struct ifconf)); } else { - ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * + size_t len =((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * sizeof (struct ifreq); - /* should the size be limited? -arnd */ - ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); - if (!ifc.ifc_buf) - return -ENOMEM; + 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; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { - if (copy_from_user(ifr, ifr32, sizeof (struct ifreq32))) { - kfree (ifc.ifc_buf); + 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++; - ifr32++; } - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); - set_fs (old_fs); - if (!err) { - 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)) { - int k = copy_to_user(ifr32, ifr, sizeof (struct ifreq32)); - ifr32++; - ifr++; - if (k) { - err = -EFAULT; - break; - } - - } - if (!err) { - 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))) - err = -EFAULT; - } + + 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(ifc.ifc_buf != NULL) - kfree (ifc.ifc_buf); - return err; + 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 *ifr; - struct ifreq32 *ifr32; + struct ifreq __user *ifr; + struct ifreq32 __user *ifr32; u32 data; - void *datap; + void __user *datap; ifr = compat_alloc_user_space(sizeof(*ifr)); ifr32 = compat_ptr(arg); @@ -586,12 +418,12 @@ static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq kifr; - struct ifreq *uifr; - struct ifreq32 *ifr32 = compat_ptr(arg); + struct ifreq __user *uifr; + struct ifreq32 __user *ifr32 = compat_ptr(arg); mm_segment_t old_fs; int err; u32 data; - void *datap; + void __user *datap; switch (cmd) { case SIOCBONDENSLAVE: @@ -628,10 +460,10 @@ static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ifreq *u_ifreq64; - struct ifreq32 *u_ifreq32 = compat_ptr(arg); + struct ifreq __user *u_ifreq64; + struct ifreq32 __user *u_ifreq32 = compat_ptr(arg); char tmp_buf[IFNAMSIZ]; - void *data64; + void __user *data64; u32 data32; if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), @@ -646,8 +478,11 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) /* 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); + 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); } @@ -655,8 +490,8 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; - struct ifreq32 *uifr32; - struct ifmap32 *uifmap32; + struct ifreq32 __user *uifr32; + struct ifmap32 __user *uifmap32; mm_segment_t old_fs; int err; @@ -685,6 +520,11 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) 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: @@ -760,7 +600,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) struct socket *mysock = sockfd_lookup(fd, &ret); if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */ - struct in6_rtmsg32 *ur6 = compat_ptr(arg); + 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)); @@ -773,7 +613,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) r = (void *) &r6; } else { /* ipv4 */ - struct rtentry32 *ur4 = compat_ptr(arg); + 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)); @@ -786,24 +626,29 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ret |= copy_from_user (devname, compat_ptr(rtdev), 15); r4.rt_dev = devname; devname[15] = 0; } else - r4.rt_dev = 0; + r4.rt_dev = NULL; r = (void *) &r4; } - if (ret) - return -EFAULT; + 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 +#ifdef CONFIG_BLOCK struct hd_geometry32 { unsigned char heads; unsigned char sectors; @@ -815,7 +660,7 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct hd_geometry geo; - struct hd_geometry32 *ugeo; + struct hd_geometry32 __user *ugeo; int err; set_fs (KERNEL_DS); @@ -829,159 +674,11 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT : 0; } -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 do_cmap_ptr(__u16 **ptr64, __u32 *ptr32) -{ - __u32 data; - void *datap; - - if (get_user(data, ptr32)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, ptr64)) - return -EFAULT; - return 0; -} - -static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct fb_cmap *cmap; - struct fb_cmap32 *cmap32; - 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 (do_cmap_ptr(&cmap->red, &cmap32->red) || - do_cmap_ptr(&cmap->green, &cmap32->green) || - do_cmap_ptr(&cmap->blue, &cmap32->blue) || - do_cmap_ptr(&cmap->transp, &cmap32->transp)) - return -EFAULT; - - err = sys_ioctl(fd, 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 *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(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - struct fb_fix_screeninfo fix; - struct fb_fix_screeninfo32 *fix32; - int err; - - fix32 = compat_ptr(arg); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long) &fix); - set_fs(old_fs); - - if (!err) - err = do_fscreeninfo_to_user(&fix, fix32); - - return err; -} - -static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch (cmd) { - case FBIOGET_FSCREENINFO: - err = fb_get_fscreeninfo(fd,cmd, arg); - break; - - case FBIOGETCMAP: - case FBIOPUTCMAP: - err = fb_getput_cmap(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("%s: Unknown fb ioctl cmd fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } while(0); - err = -ENOSYS; - break; - }; - - return err; -} - static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); unsigned long kval; - unsigned int *uvp; + unsigned int __user *uvp; int error; set_fs(KERNEL_DS); @@ -1028,10 +725,10 @@ typedef struct sg_iovec32 { compat_uint_t iov_len; } sg_iovec32_t; -static int sg_build_iovec(sg_io_hdr_t *sgio, void *dxferp, u16 iovec_count) +static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count) { - sg_iovec_t *iov = (sg_iovec_t *) (sgio + 1); - sg_iovec32_t *iov32 = dxferp; + 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++) { @@ -1044,17 +741,18 @@ static int sg_build_iovec(sg_io_hdr_t *sgio, void *dxferp, u16 iovec_count) return -EFAULT; } - sgio->dxferp = iov; /* FIXME: dereferencing user pointer? */ + if (put_user(iov, &sgio->dxferp)) + return -EFAULT; return 0; } static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { - sg_io_hdr_t *sgio; - sg_io_hdr32_t *sgio32; + sg_io_hdr_t __user *sgio; + sg_io_hdr32_t __user *sgio32; u16 iovec_count; u32 data; - void *dxferp; + void __user *dxferp; int err; sgio32 = compat_ptr(arg); @@ -1062,12 +760,9 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return -EFAULT; { - void *new, *top; - - top = compat_alloc_user_space(0); - new = compat_alloc_user_space(sizeof(sg_io_hdr_t) + - (iovec_count * - sizeof(sg_iovec_t))); + 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; @@ -1094,7 +789,8 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) } { - unsigned char *cmdp, *sbp; + unsigned char __user *cmdp; + unsigned char __user *sbp; if (get_user(data, &sgio32->cmdp)) return -EFAULT; @@ -1127,7 +823,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err = sys_ioctl(fd, cmd, (unsigned long) sgio); if (err >= 0) { - void *datap; + void __user *datap; if (copy_in_user(&sgio32->pack_id, &sgio->pack_id, sizeof(int)) || @@ -1144,6 +840,41 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) 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, unsigned long arg) +{ + int err, i; + sg_req_info_t __user *r; + struct compat_sg_req_info __user *o = (void __user *)arg; + 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; @@ -1154,9 +885,9 @@ struct sock_fprog32 { static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct sock_fprog32 *u_fprog32 = compat_ptr(arg); - struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); - void *fptr64; + 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; @@ -1193,8 +924,8 @@ struct ppp_idle32 { static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ppp_idle *idle; - struct ppp_idle32 *idle32; + struct ppp_idle __user *idle; + struct ppp_idle32 __user *idle32; __kernel_time_t xmit, recv; int err; @@ -1215,10 +946,10 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg) static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ppp_option_data *odata; - struct ppp_option_data32 *odata32; + struct ppp_option_data __user *odata; + struct ppp_option_data32 __user *odata32; __u32 data; - void *datap; + void __user *datap; odata = compat_alloc_user_space(sizeof(*odata)); odata32 = compat_ptr(arg); @@ -1266,6 +997,7 @@ static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) } +#ifdef CONFIG_BLOCK struct mtget32 { compat_long_t mt_type; compat_long_t mt_resid; @@ -1282,39 +1014,13 @@ struct mtpos32 { }; #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) -struct mtconfiginfo32 { - compat_long_t mt_type; - compat_long_t ifc_type; - unsigned short irqnr; - unsigned short dmanr; - unsigned short port; - compat_ulong_t debug; - compat_uint_t have_dens:1; - compat_uint_t have_bsf:1; - compat_uint_t have_fsr:1; - compat_uint_t have_bsr:1; - compat_uint_t have_eod:1; - compat_uint_t have_seek:1; - compat_uint_t have_tell:1; - compat_uint_t have_ras1:1; - compat_uint_t have_ras2:1; - compat_uint_t have_ras3:1; - compat_uint_t have_qfa:1; - compat_uint_t pad1:5; - char reserved[10]; -}; -#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) -#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) - static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); - struct mtconfiginfo info; - struct mtconfiginfo32 *uinfo32; struct mtget get; - struct mtget32 *umget32; + struct mtget32 __user *umget32; struct mtpos pos; - struct mtpos32 *upos32; + struct mtpos32 __user *upos32; unsigned long kcmd; void *karg; int err = 0; @@ -1328,27 +1034,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) kcmd = MTIOCGET; karg = &get; break; - case MTIOCGETCONFIG32: - kcmd = MTIOCGETCONFIG; - karg = &info; - break; - case MTIOCSETCONFIG32: - kcmd = MTIOCSETCONFIG; - karg = &info; - uinfo32 = compat_ptr(arg); - err = __get_user(info.mt_type, &uinfo32->mt_type); - err |= __get_user(info.ifc_type, &uinfo32->ifc_type); - err |= __get_user(info.irqnr, &uinfo32->irqnr); - err |= __get_user(info.dmanr, &uinfo32->dmanr); - err |= __get_user(info.port, &uinfo32->port); - err |= __get_user(info.debug, &uinfo32->debug); - err |= __copy_from_user((char *)&info.debug - + sizeof(info.debug), - (char *)&uinfo32->debug - + sizeof(uinfo32->debug), sizeof(__u32)); - if (err) - return -EFAULT; - break; default: do { static int count; @@ -1379,20 +1064,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __put_user(get.mt_fileno, &umget32->mt_fileno); err |= __put_user(get.mt_blkno, &umget32->mt_blkno); break; - case MTIOCGETCONFIG32: - uinfo32 = compat_ptr(arg); - err = __put_user(info.mt_type, &uinfo32->mt_type); - err |= __put_user(info.ifc_type, &uinfo32->ifc_type); - err |= __put_user(info.irqnr, &uinfo32->irqnr); - err |= __put_user(info.dmanr, &uinfo32->dmanr); - err |= __put_user(info.port, &uinfo32->port); - err |= __put_user(info.debug, &uinfo32->debug); - err |= __copy_to_user((char *)&uinfo32->debug - + sizeof(uinfo32->debug), - (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); - break; - case MTIOCSETCONFIG32: - break; } return err ? -EFAULT: 0; } @@ -1418,10 +1089,10 @@ struct cdrom_generic_command32 { static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct cdrom_read_audio *cdread_audio; - struct cdrom_read_audio32 *cdread_audio32; + struct cdrom_read_audio __user *cdread_audio; + struct cdrom_read_audio32 __user *cdread_audio32; __u32 data; - void *datap; + void __user *datap; cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); cdread_audio32 = compat_ptr(arg); @@ -1441,24 +1112,11 @@ static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long return sys_ioctl(fd, cmd, (unsigned long) cdread_audio); } -static int __cgc_do_ptr(void **ptr64, __u32 *ptr32) -{ - u32 data; - void *datap; - - if (get_user(data, ptr32)) - return -EFAULT; - datap = compat_ptr(data); - if (put_user(datap, ptr64)) - return -EFAULT; - - return 0; -} - static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct cdrom_generic_command *cgc; - struct cdrom_generic_command32 *cgc32; + struct cdrom_generic_command __user *cgc; + struct cdrom_generic_command32 __user *cgc32; + u32 data; unsigned char dir; int itmp; @@ -1466,25 +1124,20 @@ static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned cgc32 = compat_ptr(arg); if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || - __cgc_do_ptr((void **) &cgc->buffer, &cgc32->buffer) || + get_user(data, &cgc32->buffer) || + put_user(compat_ptr(data), &cgc->buffer) || copy_in_user(&cgc->buflen, &cgc32->buflen, (sizeof(unsigned int) + sizeof(int))) || - __cgc_do_ptr((void **) &cgc->sense, &cgc32->sense)) - return -EFAULT; - - if (get_user(dir, &cgc32->data_direction) || - put_user(dir, &cgc->data_direction)) - return -EFAULT; - - if (get_user(itmp, &cgc32->quiet) || - put_user(itmp, &cgc->quiet)) - return -EFAULT; - - if (get_user(itmp, &cgc32->timeout) || - put_user(itmp, &cgc->timeout)) - return -EFAULT; - - if (__cgc_do_ptr(&cgc->reserved[0], &cgc32->reserved[0])) + get_user(data, &cgc32->sense) || + put_user(compat_ptr(data), &cgc->sense) || + get_user(dir, &cgc32->data_direction) || + put_user(dir, &cgc->data_direction) || + get_user(itmp, &cgc32->quiet) || + put_user(itmp, &cgc->quiet) || + get_user(itmp, &cgc32->timeout) || + put_user(itmp, &cgc->timeout) || + get_user(data, &cgc32->reserved[0]) || + put_user(compat_ptr(data), &cgc->reserved[0])) return -EFAULT; return sys_ioctl(fd, cmd, (unsigned long) cgc); @@ -1517,80 +1170,14 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar return err; } - -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 int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct loop_info l; - struct loop_info32 *ul; - int err = -EINVAL; - - ul = compat_ptr(arg); - 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 = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - } - break; - case LOOP_GET_STATUS: - set_fs (KERNEL_DS); - err = sys_ioctl (fd, 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; - default: { - static int count; - if (++count <= 20) - printk("%s: Unknown loop ioctl cmd, fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } - } - return err; -} - -extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); +#endif /* CONFIG_BLOCK */ #ifdef CONFIG_VT static int vt_check(struct file *file) { struct tty_struct *tty; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; if (file->f_op->ioctl != tty_ioctl) return -EINVAL; @@ -1619,19 +1206,14 @@ struct consolefontdesc32 { static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) { - struct consolefontdesc cfdarg; + struct consolefontdesc32 __user *user_cfd = compat_ptr(arg); struct console_font_op op; - struct consolefontdesc32 *user_cfd = compat_ptr(arg); + compat_caddr_t data; int i, perm; perm = vt_check(file); if (perm < 0) return perm; - if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) - return -EFAULT; - - cfdarg.chardata = compat_ptr(((struct consolefontdesc32 *)&cfdarg)->chardata); - switch (cmd) { case PIO_FONTX: if (!perm) @@ -1639,26 +1221,30 @@ static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, op.op = KD_FONT_OP_SET; op.flags = 0; op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - return con_font_op(fg_console, &op); + if (get_user(op.height, &user_cfd->charheight) || + get_user(op.charcount, &user_cfd->charcount) || + get_user(data, &user_cfd->chardata)) + return -EFAULT; + op.data = compat_ptr(data); + return con_font_op(vc_cons[fg_console].d, &op); case GIO_FONTX: - if (!cfdarg.chardata) - return 0; op.op = KD_FONT_OP_GET; op.flags = 0; op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - i = con_font_op(fg_console, &op); + if (get_user(op.height, &user_cfd->charheight) || + get_user(op.charcount, &user_cfd->charcount) || + get_user(data, &user_cfd->chardata)) + return -EFAULT; + if (!data) + return 0; + op.data = compat_ptr(data); + i = con_font_op(vc_cons[fg_console].d, &op); if (i) return i; - cfdarg.charheight = op.height; - cfdarg.charcount = op.charcount; - ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata; - if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32))) + if (put_user(op.height, &user_cfd->charheight) || + put_user(op.charcount, &user_cfd->charcount) || + put_user((compat_caddr_t)(unsigned long)op.data, + &user_cfd->chardata)) return -EFAULT; return 0; } @@ -1676,23 +1262,24 @@ struct console_font_op32 { static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) { struct console_font_op op; - struct console_font_op32 *fontop = compat_ptr(arg); + struct console_font_op32 __user *fontop = compat_ptr(arg); int perm = vt_check(file), i; - struct vt_struct *vt; + struct vc_data *vc; if (perm < 0) return perm; - if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32))) + if (copy_from_user(&op, fontop, sizeof(struct console_font_op32))) return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; op.data = compat_ptr(((struct console_font_op32 *)&op)->data); op.flags |= KD_FONT_FLAG_OLD; - vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; - i = con_font_op(vt->vc_num, &op); - if (i) return i; + vc = ((struct tty_struct *)file->private_data)->driver_data; + i = con_font_op(vc, &op); + if (i) + return i; ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; - if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32))) + if (copy_to_user(fontop, &op, sizeof(struct console_font_op32))) return -EFAULT; return 0; } @@ -1705,7 +1292,7 @@ struct unimapdesc32 { static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) { struct unimapdesc32 tmp; - struct unimapdesc32 *user_ud = compat_ptr(arg); + struct unimapdesc32 __user *user_ud = compat_ptr(arg); int perm = vt_check(file); if (perm < 0) return perm; @@ -1714,9 +1301,9 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, switch (cmd) { case PIO_UNIMAP: if (!perm) return -EPERM; - return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries)); + return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); case GIO_UNIMAP: - return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); + return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); } return 0; } @@ -1736,7 +1323,7 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a set_fs(old_fs); if (err >= 0) - err = put_user(kuid, (compat_uid_t *)compat_ptr(arg)); + err = put_user(kuid, (compat_uid_t __user *)compat_ptr(arg)); return err; } @@ -1793,15 +1380,14 @@ static struct { { ATM_QUERYLOOP32, ATM_QUERYLOOP } }; -#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) - +#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map) static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct atm_iobuf *iobuf; - struct atm_iobuf32 *iobuf32; + struct atm_iobuf __user *iobuf; + struct atm_iobuf32 __user *iobuf32; u32 data; - void *datap; + void __user *datap; int len, err; iobuf = compat_alloc_user_space(sizeof(*iobuf)); @@ -1828,10 +1414,10 @@ static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct atmif_sioc *sioc; - struct atmif_sioc32 *sioc32; + struct atmif_sioc __user *sioc; + struct atmif_sioc32 __user *sioc32; u32 data; - void *datap; + void __user *datap; int err; sioc = compat_alloc_user_space(sizeof(*sioc)); @@ -1906,11 +1492,13 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) return -EINVAL; } -static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) +static __attribute_used__ int +ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) { return -EINVAL; } +#ifdef CONFIG_BLOCK static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) { /* The mkswap binary hard codes it to Intel value :-((( */ @@ -1926,46 +1514,33 @@ struct blkpg_ioctl_arg32 { static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct blkpg_ioctl_arg a; - struct blkpg_ioctl_arg32 *ua32; - struct blkpg_partition p; - struct blkpg_partition *up32; + 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; - mm_segment_t old_fs = get_fs(); - ua32 = compat_ptr(arg); - err = get_user(a.op, &ua32->op); - err |= __get_user(a.flags, &ua32->flags); - err |= __get_user(a.datalen, &ua32->datalen); - err |= __get_user(udata, &ua32->data); - up32 = compat_ptr(udata); + 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; - switch (a.op) { - case BLKPG_ADD_PARTITION: - case BLKPG_DEL_PARTITION: - if (a.datalen < sizeof(struct blkpg_partition)) - return -EINVAL; - if (copy_from_user(&p, up32, sizeof(struct blkpg_partition))) - return -EFAULT; - a.data = &p; - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&a); - set_fs (old_fs); - break; - default: - return -EINVAL; - } - return err; + return sys_ioctl(fd, cmd, (unsigned long)a); } +#endif static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); } +#ifdef CONFIG_BLOCK /* Fix sizeof(sizeof()) breakage */ #define BLKBSZGET_32 _IOR(0x12,112,int) #define BLKBSZSET_32 _IOW(0x12,113,int) @@ -1986,6 +1561,7 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd, { return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg)); } +#endif /* Bluetooth ioctls */ #define HCIUARTSETPROTO _IOW('U', 200, int) @@ -2001,6 +1577,12 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd, #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) + +#ifdef CONFIG_BLOCK struct floppy_struct32 { compat_uint_t size; compat_uint_t sect; @@ -2104,7 +1686,7 @@ static struct { { FDWERRORGET32, FDWERRORGET } }; -#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0])) +#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -2127,7 +1709,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FDGETPRM32: { compat_uptr_t name; - struct floppy_struct32 *uf; + struct floppy_struct32 __user *uf; struct floppy_struct *f; uf = compat_ptr(arg); @@ -2156,7 +1738,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FDSETDRVPRM32: case FDGETDRVPRM32: { - struct floppy_drive_params32 *uf; + struct floppy_drive_params32 __user *uf; struct floppy_drive_params *f; uf = compat_ptr(arg); @@ -2218,22 +1800,23 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FDGETPRM32: { struct floppy_struct *f = karg; + struct floppy_struct32 __user *uf = compat_ptr(arg); - err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size); - err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect); - err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head); - err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track); - err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); - err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap); - err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate); - err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); - err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __put_user((u64)f->name, (compat_caddr_t*)&((struct floppy_struct32 *)arg)->name); + 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 *uf; + struct floppy_drive_params32 __user *uf; struct floppy_drive_params *f = karg; uf = compat_ptr(arg); @@ -2261,7 +1844,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: { - struct floppy_drive_struct32 *uf; + struct floppy_drive_struct32 __user *uf; struct floppy_drive_struct *f = karg; uf = compat_ptr(arg); @@ -2284,7 +1867,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) } case FDGETFDCSTAT32: { - struct floppy_fdc_state32 *uf; + struct floppy_fdc_state32 __user *uf; struct floppy_fdc_state *f = karg; uf = compat_ptr(arg); @@ -2294,7 +1877,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) 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 *)&uf->address + sizeof(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)); @@ -2302,7 +1885,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) } case FDWERRORGET32: { - struct floppy_write_errors32 *uf; + struct floppy_write_errors32 __user *uf; struct floppy_write_errors *f = karg; uf = compat_ptr(arg); @@ -2320,9 +1903,11 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) if (err) err = -EFAULT; -out: if (karg) kfree(karg); +out: + kfree(karg); return err; } +#endif struct mtd_oob_buf32 { u_int32_t start; @@ -2335,10 +1920,10 @@ struct mtd_oob_buf32 { static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct mtd_oob_buf *buf = compat_alloc_user_space(sizeof(*buf)); - struct mtd_oob_buf32 *buf32 = compat_ptr(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 *datap; + char __user *datap; unsigned int real_cmd; int err; @@ -2364,61 +1949,7 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) return err; } -#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 *d32) -{ - int ret; - - if ((ret = verify_area(VERIFY_WRITE, d32, - sizeof(struct compat_dirent)))) - return ret; - - __put_user(d->d_ino, &d32->d_ino); - __put_user(d->d_off, &d32->d_off); - __put_user(d->d_reclen, &d32->d_reclen); - __copy_to_user(d32->d_name, d->d_name, d->d_reclen); - return ret; -} - -static int vfat_ioctl32(unsigned fd, unsigned cmd, unsigned long 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], (struct compat_dirent *)compat_ptr(arg)); - ret |= put_dirent32(&d[1], ((struct compat_dirent *)compat_ptr(arg)) + 1); - } - return ret; -} - -#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); -} - +#ifdef CONFIG_BLOCK struct raw32_config_request { compat_int_t raw_minor; @@ -2426,42 +1957,32 @@ struct raw32_config_request __u64 block_minor; } __attribute__((packed)); -static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req) +static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req) { - __u32 lo_maj, hi_maj, lo_min, hi_min; int ret; - if ((ret = verify_area(VERIFY_READ, user_req, - sizeof(struct raw32_config_request)))) - return ret; - - __get_user(req->raw_minor, &user_req->raw_minor); - __get_user(lo_maj, (__u32*)&user_req->block_major); - __get_user(hi_maj, ((__u32*)(&user_req->block_major) + 1)); - __get_user(lo_min, (__u32*)&user_req->block_minor); - __get_user(hi_min, ((__u32*)(&user_req->block_minor) + 1)); + if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request))) + return -EFAULT; - req->block_major = lo_maj | (((__u64)hi_maj) << 32); - req->block_minor = lo_min | (((__u64)hi_min) << 32); + 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; + return ret ? -EFAULT : 0; } -static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req) +static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req) { int ret; - if ((ret = verify_area(VERIFY_WRITE, user_req, - sizeof(struct raw32_config_request)))) - return ret; + if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request))) + return -EFAULT; - __put_user(req->raw_minor, &user_req->raw_minor); - __put_user((__u32)(req->block_major), (__u32*)&user_req->block_major); - __put_user((__u32)(req->block_major >> 32), ((__u32*)(&user_req->block_major) + 1)); - __put_user((__u32)(req->block_minor), (__u32*)&user_req->block_minor); - __put_user((__u32)(req->block_minor >> 32), ((__u32*)(&user_req->block_minor) + 1)); + 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; + return ret ? -EFAULT : 0; } static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) @@ -2472,7 +1993,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) case RAW_SETBIND: case RAW_GETBIND: { struct raw_config_request req; - struct raw32_config_request *user_req = compat_ptr(arg); + struct raw32_config_request __user *user_req = compat_ptr(arg); mm_segment_t oldfs = get_fs(); if ((ret = get_raw32_request(&req, user_req))) @@ -2493,6 +2014,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) } return ret; } +#endif /* CONFIG_BLOCK */ struct serial_struct32 { compat_int_t type; @@ -2520,35 +2042,40 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) { typedef struct serial_struct SS; typedef struct serial_struct32 SS32; - struct serial_struct32 *ss32 = compat_ptr(arg); + struct serial_struct32 __user *ss32 = compat_ptr(arg); int err; struct serial_struct ss; mm_segment_t oldseg = get_fs(); __u32 udata; + unsigned int base; if (cmd == TIOCSSERIAL) { - if (verify_area(VERIFY_READ, ss32, sizeof(SS32))) + if (!access_ok(VERIFY_READ, ss32, sizeof(SS32))) return -EFAULT; - __copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)); - __get_user(udata, &ss32->iomem_base); + if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base))) + return -EFAULT; + if (__get_user(udata, &ss32->iomem_base)) + return -EFAULT; ss.iomem_base = compat_ptr(udata); - __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); - __get_user(ss.port_high, &ss32->port_high); + if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || + __get_user(ss.port_high, &ss32->port_high)) + return -EFAULT; ss.iomap_base = 0UL; } set_fs(KERNEL_DS); err = sys_ioctl(fd,cmd,(unsigned long)(&ss)); set_fs(oldseg); if (cmd == TIOCGSERIAL && err >= 0) { - if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32))) + if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32))) return -EFAULT; - __copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)); - __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); - + if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base))) + return -EFAULT; + base = (unsigned long)ss.iomem_base >> 32 ? + 0xffffffff : (unsigned)(unsigned long)ss.iomem_base; + if (__put_user(base, &ss32->iomem_base) || + __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || + __put_user(ss.port_high, &ss32->port_high)) + return -EFAULT; } return err; } @@ -2567,53 +2094,15 @@ struct usbdevfs_ctrltransfer32 { static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct usbdevfs_ctrltransfer kctrl; - struct usbdevfs_ctrltransfer32 *uctrl; - mm_segment_t old_fs; + struct usbdevfs_ctrltransfer32 __user *p32 = compat_ptr(arg); + struct usbdevfs_ctrltransfer __user *p; __u32 udata; - void *uptr, *kptr; - int err; - - uctrl = compat_ptr(arg); - - if (copy_from_user(&kctrl, uctrl, - (sizeof(struct usbdevfs_ctrltransfer32) - - sizeof(compat_caddr_t)))) - return -EFAULT; - - if (get_user(udata, &uctrl->data)) - return -EFAULT; - uptr = compat_ptr(udata); - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kctrl.wLength > PAGE_SIZE) - return -EINVAL; - - kptr = (void *)__get_free_page(GFP_KERNEL); - - if ((kctrl.bRequestType & USB_DIR_IN) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kctrl.wLength)) - goto out; - } - - kctrl.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); - set_fs(old_fs); - - if (err >= 0 && - ((kctrl.bRequestType & USB_DIR_IN) != 0)) { - if (copy_to_user(uptr, kptr, kctrl.wLength)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; + 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 sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)p); } @@ -2628,278 +2117,27 @@ struct usbdevfs_bulktransfer32 { static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct usbdevfs_bulktransfer kbulk; - struct usbdevfs_bulktransfer32 *ubulk; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - int err; + struct usbdevfs_bulktransfer32 __user *p32 = compat_ptr(arg); + struct usbdevfs_bulktransfer __user *p; + compat_uint_t n; + compat_caddr_t addr; - ubulk = compat_ptr(arg); + p = compat_alloc_user_space(sizeof(*p)); - if (get_user(kbulk.ep, &ubulk->ep) || - get_user(kbulk.len, &ubulk->len) || - get_user(kbulk.timeout, &ubulk->timeout) || - get_user(udata, &ubulk->data)) + 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; - uptr = compat_ptr(udata); - - /* In usbdevice_fs, it limits the control buffer to a page, - * for simplicity so do we. - */ - if (!uptr || kbulk.len > PAGE_SIZE) - return -EINVAL; - - kptr = (void *) __get_free_page(GFP_KERNEL); - - if ((kbulk.ep & 0x80) == 0) { - err = -EFAULT; - if (copy_from_user(kptr, uptr, kbulk.len)) - goto out; - } - - kbulk.data = kptr; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); - set_fs(old_fs); - - if (err >= 0 && - ((kbulk.ep & 0x80) != 0)) { - if (copy_to_user(uptr, kptr, kbulk.len)) - err = -EFAULT; - } - -out: - free_page((unsigned long) kptr); - return err; -} - -/* This needs more work before we can enable it. Unfortunately - * because of the fancy asynchronous way URB status/error is written - * back to userspace, we'll need to fiddle with USB devio internals - * and/or reimplement entirely the frontend of it ourselves. -DaveM - * - * The issue is: - * - * When an URB is submitted via usbdevicefs it is put onto an - * asynchronous queue. When the URB completes, it may be reaped - * via another ioctl. During this reaping the status is written - * back to userspace along with the length of the transfer. - * - * We must translate into 64-bit kernel types so we pass in a kernel - * space copy of the usbdevfs_urb structure. This would mean that we - * must do something to deal with the async entry reaping. First we - * have to deal somehow with this transitory memory we've allocated. - * This is problematic since there are many call sites from which the - * async entries can be destroyed (and thus when we'd need to free up - * this kernel memory). One of which is the close() op of usbdevicefs. - * To handle that we'd need to make our own file_operations struct which - * overrides usbdevicefs's release op with our own which runs usbdevicefs's - * real release op then frees up the kernel memory. - * - * But how to keep track of these kernel buffers? We'd need to either - * keep track of them in some table _or_ know about usbdevicefs internals - * (ie. the exact layout of its file private, which is actually defined - * in linux/usbdevice_fs.h, the layout of the async queues are private to - * devio.c) - * - * There is one possible other solution I considered, also involving knowledge - * of usbdevicefs internals: - * - * After an URB is submitted, we "fix up" the address back to the user - * space one. This would work if the status/length fields written back - * by the async URB completion lines up perfectly in the 32-bit type with - * the 64-bit kernel type. Unfortunately, it does not because the iso - * frame descriptors, at the end of the struct, can be written back. - * - * I think we'll just need to simply duplicate the devio URB engine here. - */ -#if 0 -struct usbdevfs_urb32 { - unsigned char type; - unsigned char endpoint; - compat_int_t status; - compat_uint_t flags; - compat_caddr_t buffer; - compat_int_t buffer_length; - compat_int_t actual_length; - compat_int_t start_frame; - compat_int_t number_of_packets; - compat_int_t error_count; - compat_uint_t signr; - compat_caddr_t usercontext; /* unused */ - struct usbdevfs_iso_packet_desc iso_frame_desc[0]; -}; - -#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) - -static int get_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (get_user(kurb->type, &uurb->type) || - __get_user(kurb->endpoint, &uurb->endpoint) || - __get_user(kurb->status, &uurb->status) || - __get_user(kurb->flags, &uurb->flags) || - __get_user(kurb->buffer_length, &uurb->buffer_length) || - __get_user(kurb->actual_length, &uurb->actual_length) || - __get_user(kurb->start_frame, &uurb->start_frame) || - __get_user(kurb->number_of_packets, &uurb->number_of_packets) || - __get_user(kurb->error_count, &uurb->error_count) || - __get_user(kurb->signr, &uurb->signr)) - return -EFAULT; - - kurb->usercontext = 0; /* unused currently */ - - return 0; + return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p); } -/* Just put back the values which usbdevfs actually changes. */ -static int put_urb32(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - if (put_user(kurb->status, &uurb->status) || - __put_user(kurb->actual_length, &uurb->actual_length) || - __put_user(kurb->error_count, &uurb->error_count)) - return -EFAULT; - - if (kurb->number_of_packets != 0) { - int i; - for (i = 0; i < kurb->number_of_packets; i++) { - if (__put_user(kurb->iso_frame_desc[i].actual_length, - &uurb->iso_frame_desc[i].actual_length) || - __put_user(kurb->iso_frame_desc[i].status, - &uurb->iso_frame_desc[i].status)) - return -EFAULT; - } - } - - return 0; -} - -static int get_urb32_isoframes(struct usbdevfs_urb *kurb, - struct usbdevfs_urb32 *uurb) -{ - unsigned int totlen; - int i; - - if (kurb->type != USBDEVFS_URB_TYPE_ISO) { - kurb->number_of_packets = 0; - return 0; - } - - if (kurb->number_of_packets < 1 || - kurb->number_of_packets > 128) - return -EINVAL; - - if (copy_from_user(&kurb->iso_frame_desc[0], - &uurb->iso_frame_desc[0], - sizeof(struct usbdevfs_iso_packet_desc) * - kurb->number_of_packets)) - return -EFAULT; - - totlen = 0; - for (i = 0; i < kurb->number_of_packets; i++) { - unsigned int this_len; - - this_len = kurb->iso_frame_desc[i].length; - if (this_len > 1023) - return -EINVAL; - - totlen += this_len; - } - - if (totlen > 32768) - return -EINVAL; - - kurb->buffer_length = totlen; - - return 0; -} - -static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct usbdevfs_urb *kurb; - struct usbdevfs_urb32 *uurb; - mm_segment_t old_fs; - __u32 udata; - void *uptr, *kptr; - unsigned int buflen; - int err; - - uurb = compat_ptr(arg); - - err = -ENOMEM; - kurb = kmalloc(sizeof(struct usbdevfs_urb) + - (sizeof(struct usbdevfs_iso_packet_desc) * 128), - GFP_KERNEL); - if (!kurb) - goto out; - - err = -EFAULT; - if (get_urb32(kurb, uurb)) - goto out; - - err = get_urb32_isoframes(kurb, uurb); - if (err) - goto out; - - err = -EFAULT; - if (__get_user(udata, &uurb->buffer)) - goto out; - uptr = compat_ptr(udata); - - buflen = kurb->buffer_length; - err = verify_area(VERIFY_WRITE, uptr, buflen); - if (err) - goto out; - - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); - set_fs(old_fs); - - if (err >= 0) { - /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ - if (put_urb32(kurb, uurb)) { - err = -EFAULT; - } - } - -out: - kfree(kurb); - return err; -} -#endif - -#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) -#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) - -static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - void *kptr; - int err; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, - (cmd == USBDEVFS_REAPURB32 ? - USBDEVFS_REAPURB : - USBDEVFS_REAPURBNDELAY), - (unsigned long) &kptr); - set_fs(old_fs); - - if (err >= 0 && - put_user((u32)(u64)kptr, (u32 *)compat_ptr(arg))) - err = -EFAULT; - - return err; -} +/* + * USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY + * are handled in usbdevfs core. -Christopher Li + */ struct usbdevfs_disconnectsignal32 { compat_int_t signr; @@ -2911,7 +2149,7 @@ struct usbdevfs_disconnectsignal32 { static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) { struct usbdevfs_disconnectsignal kdis; - struct usbdevfs_disconnectsignal32 *udis; + struct usbdevfs_disconnectsignal32 __user *udis; mm_segment_t old_fs; u32 uctx; int err; @@ -2955,48 +2193,42 @@ struct i2c_smbus_ioctl_data32 { 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_rdwr_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct i2c_rdwr_ioctl_data *tdata; - struct i2c_rdwr_ioctl_data32 *udata; - struct i2c_msg *tmsgs; - struct i2c_msg32 *umsgs; + 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; - tdata = compat_alloc_user_space(sizeof(*tdata)); - if (tdata == NULL) - return -ENOMEM; - if (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata))) - return -EFAULT; - - udata = (struct i2c_rdwr_ioctl_data32 *)compat_ptr(arg); - if (verify_area(VERIFY_READ, udata, sizeof(*udata))) - return -EFAULT; - if (__get_user(nmsgs, &udata->nmsgs) || __put_user(nmsgs, &tdata->nmsgs)) + 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 = (struct i2c_msg32 *)compat_ptr(datap); - if (verify_area(VERIFY_READ, umsgs, sizeof(struct i2c_msg) * nmsgs)) + + if (get_user(datap, &udata->msgs)) return -EFAULT; + umsgs = compat_ptr(datap); - tmsgs = compat_alloc_user_space(sizeof(struct i2c_msg) * nmsgs); - if (tmsgs == NULL) - return -ENOMEM; - if (verify_area(VERIFY_WRITE, tmsgs, sizeof(struct i2c_msg) * nmsgs)) + 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; - if (__put_user(tmsgs, &tdata->msgs)) - return -ENOMEM; + for (i = 0; i < nmsgs; i++) { - if (__copy_in_user(&tmsgs[i].addr, - &umsgs[i].addr, - 3 * sizeof(u16))) + 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)) + if (get_user(datap, &umsgs[i].buf) || + put_user(compat_ptr(datap), &tmsgs[i].buf)) return -EFAULT; } return sys_ioctl(fd, cmd, (unsigned long)tdata); @@ -3004,18 +2236,18 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct i2c_smbus_ioctl_data *tdata; - struct i2c_smbus_ioctl_data32 *udata; + 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 (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata))) + if (!access_ok(VERIFY_WRITE, tdata, sizeof(*tdata))) return -EFAULT; - udata = (struct i2c_smbus_ioctl_data32 *)compat_ptr(arg); - if (verify_area(VERIFY_READ, udata, sizeof(*udata))) + 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))) @@ -3037,21 +2269,22 @@ struct compat_iw_point { static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct iwreq *iwr, *iwr_u; - struct iw_point *iwp; - struct compat_iw_point *iwp_u; + 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 = (struct iwreq *) compat_ptr(arg); - iwp_u = (struct compat_iw_point *) &iwr_u->u.data; + 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 (verify_area(VERIFY_WRITE, iwr, sizeof(*iwr))) + if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr))) return -EFAULT; if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0], @@ -3072,29 +2305,87 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar return sys_ioctl(fd, cmd, (unsigned long) iwr); } -/* Emulate old style bridge ioctls */ -static int do_bridge_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +/* 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; - unsigned long *argbuf = compat_alloc_user_space(3 * sizeof(unsigned long)); - int i; - for (i = 0; i < 3; i++) { - if (get_user(tmp, i + ((u32 *)arg)) || - put_user(tmp, i + argbuf)) - return -EFAULT; + + if (get_user(tmp, (u32 __user *) arg)) + return -EFAULT; + if (tmp == BRCTL_GET_VERSION) + return BRCTL_VERSION + 1; + return -EINVAL; +} + +#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) +#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) +#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) +#define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) + +static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) +{ + mm_segment_t oldfs = get_fs(); + compat_ulong_t val32; + unsigned long kval; + int ret; + + switch (cmd) { + case RTC_IRQP_READ32: + case RTC_EPOCH_READ32: + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ? + RTC_IRQP_READ : RTC_EPOCH_READ, + (unsigned long)&kval); + set_fs(oldfs); + if (ret) + return ret; + val32 = kval; + return put_user(val32, (unsigned int __user *)arg); + case RTC_IRQP_SET32: + return sys_ioctl(fd, RTC_IRQP_SET, arg); + case RTC_EPOCH_SET32: + return sys_ioctl(fd, RTC_EPOCH_SET, arg); + default: + /* unreached */ + return -ENOIOCTLCMD; } - return sys_ioctl(fd, cmd, (unsigned long)argbuf); } -#undef CODE -#endif +static int +lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct compat_timeval __user *tc = (struct compat_timeval __user *)arg; + struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval)); + struct timeval ts; + if (get_user(ts.tv_sec, &tc->tv_sec) || + get_user(ts.tv_usec, &tc->tv_usec) || + put_user(ts.tv_sec, &tn->tv_sec) || + put_user(ts.tv_usec, &tn->tv_usec)) + return -EFAULT; + return sys_ioctl(fd, cmd, (unsigned long)tn); +} -#ifdef DECLARES +#define HANDLE_IOCTL(cmd,handler) \ + { (cmd), (ioctl_trans_handler_t)(handler) }, + +/* pointer to compatible structure or no argument */ +#define COMPATIBLE_IOCTL(cmd) \ + { (cmd), do_ioctl32_pointer }, + +/* argument is an unsigned long integer, not a pointer */ +#define ULONG_IOCTL(cmd) \ + { (cmd), (ioctl_trans_handler_t)sys_ioctl }, + + +struct ioctl_trans ioctl_start[] = { +#include HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) #ifdef CONFIG_NET HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) -#endif HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) @@ -3113,6 +2404,14 @@ HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFHWBROADCAST, 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) @@ -3133,26 +2432,31 @@ 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 +#ifdef CONFIG_BLOCK HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) HANDLE_IOCTL(BLKRAGET, w_long) HANDLE_IOCTL(BLKGETSIZE, w_long) HANDLE_IOCTL(0x1260, broken_blkgetsize) HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) -HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_WCACHE, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_ACOUSTIC, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_ADDRESS, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_BUSSTATE, hdio_ioctl_trans) HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) @@ -3163,18 +2467,18 @@ HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) HANDLE_IOCTL(SG_IO,sg_ioctl_trans) +HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) +#endif 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) +#ifdef CONFIG_BLOCK HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans) HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) -HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) -HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) +#endif #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) #ifdef CONFIG_VT @@ -3184,18 +2488,6 @@ HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) #endif -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) -HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFREQ32, do_video_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) @@ -3225,26 +2517,36 @@ HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) /* block stuff */ +#ifdef CONFIG_BLOCK HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) -/* 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) HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) +#endif /* Serial */ HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) +#ifdef TIOCGLTC +COMPATIBLE_IOCTL(TIOCGLTC) +COMPATIBLE_IOCTL(TIOCSLTC) +#endif +#ifdef TIOCSTART +/* + * For these two we have defintions in ioctls.h and/or termios.h on + * some architectures but no actual implemention. Some applications + * like bash call them if they are defined in the headers, so we provide + * entries here to avoid syslog message spew. + */ +COMPATIBLE_IOCTL(TIOCSTART) +COMPATIBLE_IOCTL(TIOCSTOP) +#endif /* Usbdevfs */ HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ -HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) -HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) +COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) /* i2c */ HANDLE_IOCTL(I2C_FUNCS, w_long) HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) @@ -3263,8 +2565,31 @@ 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, do_bridge_ioctl) -HANDLE_IOCTL(SIOCGIFBR, do_bridge_ioctl) +HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) +HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) +HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) +HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl) +HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl) +HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl) + +/* dvb */ +HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event) +HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture) +HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette) + +/* parport */ +COMPATIBLE_IOCTL(LPTIME) +COMPATIBLE_IOCTL(LPCHAR) +COMPATIBLE_IOCTL(LPABORTOPEN) +COMPATIBLE_IOCTL(LPCAREFUL) +COMPATIBLE_IOCTL(LPWAIT) +COMPATIBLE_IOCTL(LPSETIRQ) +COMPATIBLE_IOCTL(LPGETSTATUS) +COMPATIBLE_IOCTL(LPGETSTATUS) +COMPATIBLE_IOCTL(LPRESET) +/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/ +COMPATIBLE_IOCTL(LPGETFLAGS) +HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) +}; -#undef DECLARES -#endif +int ioctl_table_size = ARRAY_SIZE(ioctl_start);