X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcompat_ioctl.c;h=a14dc212e301721a2ed24eb09a08cfa934fffefe;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=2edf63444ccbdf9570cfb7e6054cff56a68c7377;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 2edf63444..a14dc212e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -69,6 +69,7 @@ #include #include #include +#include #include /* siocdevprivate_ioctl */ #include @@ -95,6 +96,7 @@ #include #include #include +#include #include #include @@ -115,6 +117,7 @@ #include #include #include +#include #include @@ -642,8 +645,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); } @@ -681,6 +687,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: @@ -2340,7 +2351,9 @@ put_dirent32 (struct dirent *d, struct compat_dirent __user *d32) __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); + if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen)) + return -EFAULT; + return ret; } @@ -2483,7 +2496,8 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) if (cmd == TIOCSSERIAL) { if (verify_area(VERIFY_READ, ss32, sizeof(SS32))) return -EFAULT; - __copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)); + if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base))) + return -EFAULT; __get_user(udata, &ss32->iomem_base); ss.iomem_base = compat_ptr(udata); __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); @@ -2496,7 +2510,8 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) if (cmd == TIOCGSERIAL && err >= 0) { if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32))) return -EFAULT; - __copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)); + if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base))) + return -EFAULT; __put_user((unsigned long)ss.iomem_base >> 32 ? 0xffffffff : (unsigned)(unsigned long)ss.iomem_base, &ss32->iomem_base); @@ -2838,48 +2853,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 __user *tdata; - struct i2c_rdwr_ioctl_data32 __user *udata; + 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 = 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)) + + if (get_user(datap, &udata->msgs)) return -EFAULT; umsgs = compat_ptr(datap); - if (verify_area(VERIFY_READ, umsgs, sizeof(struct i2c_msg) * nmsgs)) - return -EFAULT; - 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); @@ -3184,6 +3193,13 @@ HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) + +/* ioctls used by appletalk ddp.c */ +HANDLE_IOCTL(SIOCATALKDIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCDIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSARP, dev_ifsioc) +HANDLE_IOCTL(SIOCDARP, dev_ifsioc) + HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)