diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2006-12-06 23:36:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:33 -0500 |
commit | 7116e994b47f3988389be4ceee67dac64b56e0d0 (patch) | |
tree | f6b722a14cba117898456c3a9edbe7538310db2f | |
parent | 841d5fb7c75260f76ae682648b28a3dca724940d (diff) |
[PATCH] compat: fix uaccess handling
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/compat.c | 35 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 33 |
2 files changed, 39 insertions, 29 deletions
diff --git a/fs/compat.c b/fs/compat.c index 7aef5412f49c..a7e3f162fb15 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1144,7 +1144,9 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
1144 | lastdirent = buf.previous; | 1144 | lastdirent = buf.previous; |
1145 | if (lastdirent) { | 1145 | if (lastdirent) { |
1146 | typeof(lastdirent->d_off) d_off = file->f_pos; | 1146 | typeof(lastdirent->d_off) d_off = file->f_pos; |
1147 | __put_user_unaligned(d_off, &lastdirent->d_off); | 1147 | error = -EFAULT; |
1148 | if (__put_user_unaligned(d_off, &lastdirent->d_off)) | ||
1149 | goto out_putf; | ||
1148 | error = count - buf.count; | 1150 | error = count - buf.count; |
1149 | } | 1151 | } |
1150 | 1152 | ||
@@ -1611,14 +1613,14 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1611 | nr &= ~1UL; | 1613 | nr &= ~1UL; |
1612 | while (nr) { | 1614 | while (nr) { |
1613 | unsigned long h, l; | 1615 | unsigned long h, l; |
1614 | __get_user(l, ufdset); | 1616 | if (__get_user(l, ufdset) || __get_user(h, ufdset+1)) |
1615 | __get_user(h, ufdset+1); | 1617 | return -EFAULT; |
1616 | ufdset += 2; | 1618 | ufdset += 2; |
1617 | *fdset++ = h << 32 | l; | 1619 | *fdset++ = h << 32 | l; |
1618 | nr -= 2; | 1620 | nr -= 2; |
1619 | } | 1621 | } |
1620 | if (odd) | 1622 | if (odd && __get_user(*fdset, ufdset)) |
1621 | __get_user(*fdset, ufdset); | 1623 | return -EFAULT; |
1622 | } else { | 1624 | } else { |
1623 | /* Tricky, must clear full unsigned long in the | 1625 | /* Tricky, must clear full unsigned long in the |
1624 | * kernel fdset at the end, this makes sure that | 1626 | * kernel fdset at the end, this makes sure that |
@@ -1630,14 +1632,14 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1630 | } | 1632 | } |
1631 | 1633 | ||
1632 | static | 1634 | static |
1633 | void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | 1635 | int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, |
1634 | unsigned long *fdset) | 1636 | unsigned long *fdset) |
1635 | { | 1637 | { |
1636 | unsigned long odd; | 1638 | unsigned long odd; |
1637 | nr = ROUND_UP(nr, __COMPAT_NFDBITS); | 1639 | nr = ROUND_UP(nr, __COMPAT_NFDBITS); |
1638 | 1640 | ||
1639 | if (!ufdset) | 1641 | if (!ufdset) |
1640 | return; | 1642 | return 0; |
1641 | 1643 | ||
1642 | odd = nr & 1UL; | 1644 | odd = nr & 1UL; |
1643 | nr &= ~1UL; | 1645 | nr &= ~1UL; |
@@ -1645,13 +1647,14 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1645 | unsigned long h, l; | 1647 | unsigned long h, l; |
1646 | l = *fdset++; | 1648 | l = *fdset++; |
1647 | h = l >> 32; | 1649 | h = l >> 32; |
1648 | __put_user(l, ufdset); | 1650 | if (__put_user(l, ufdset) || __put_user(h, ufdset+1)) |
1649 | __put_user(h, ufdset+1); | 1651 | return -EFAULT; |
1650 | ufdset += 2; | 1652 | ufdset += 2; |
1651 | nr -= 2; | 1653 | nr -= 2; |
1652 | } | 1654 | } |
1653 | if (odd) | 1655 | if (odd && __put_user(*fdset, ufdset)) |
1654 | __put_user(*fdset, ufdset); | 1656 | return -EFAULT; |
1657 | return 0; | ||
1655 | } | 1658 | } |
1656 | 1659 | ||
1657 | 1660 | ||
@@ -1726,10 +1729,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1726 | ret = 0; | 1729 | ret = 0; |
1727 | } | 1730 | } |
1728 | 1731 | ||
1729 | compat_set_fd_set(n, inp, fds.res_in); | 1732 | if (compat_set_fd_set(n, inp, fds.res_in) || |
1730 | compat_set_fd_set(n, outp, fds.res_out); | 1733 | compat_set_fd_set(n, outp, fds.res_out) || |
1731 | compat_set_fd_set(n, exp, fds.res_ex); | 1734 | compat_set_fd_set(n, exp, fds.res_ex)) |
1732 | 1735 | ret = -EFAULT; | |
1733 | out: | 1736 | out: |
1734 | kfree(bits); | 1737 | kfree(bits); |
1735 | out_nofds: | 1738 | out_nofds: |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a91f2628c981..6e3177685556 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -211,8 +211,10 @@ static int do_video_stillpicture(unsigned int fd, unsigned int cmd, unsigned lon | |||
211 | up_native = | 211 | up_native = |
212 | compat_alloc_user_space(sizeof(struct video_still_picture)); | 212 | compat_alloc_user_space(sizeof(struct video_still_picture)); |
213 | 213 | ||
214 | put_user(compat_ptr(fp), &up_native->iFrame); | 214 | err = put_user(compat_ptr(fp), &up_native->iFrame); |
215 | put_user(size, &up_native->size); | 215 | err |= put_user(size, &up_native->size); |
216 | if (err) | ||
217 | return -EFAULT; | ||
216 | 218 | ||
217 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); | 219 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); |
218 | 220 | ||
@@ -236,8 +238,10 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, unsigned | |||
236 | err |= get_user(length, &up->length); | 238 | err |= get_user(length, &up->length); |
237 | 239 | ||
238 | up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); | 240 | up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); |
239 | put_user(compat_ptr(palp), &up_native->palette); | 241 | err = put_user(compat_ptr(palp), &up_native->palette); |
240 | put_user(length, &up_native->length); | 242 | err |= put_user(length, &up_native->length); |
243 | if (err) | ||
244 | return -EFAULT; | ||
241 | 245 | ||
242 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); | 246 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); |
243 | 247 | ||
@@ -2043,16 +2047,19 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) | |||
2043 | struct serial_struct ss; | 2047 | struct serial_struct ss; |
2044 | mm_segment_t oldseg = get_fs(); | 2048 | mm_segment_t oldseg = get_fs(); |
2045 | __u32 udata; | 2049 | __u32 udata; |
2050 | unsigned int base; | ||
2046 | 2051 | ||
2047 | if (cmd == TIOCSSERIAL) { | 2052 | if (cmd == TIOCSSERIAL) { |
2048 | if (!access_ok(VERIFY_READ, ss32, sizeof(SS32))) | 2053 | if (!access_ok(VERIFY_READ, ss32, sizeof(SS32))) |
2049 | return -EFAULT; | 2054 | return -EFAULT; |
2050 | if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base))) | 2055 | if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base))) |
2051 | return -EFAULT; | 2056 | return -EFAULT; |
2052 | __get_user(udata, &ss32->iomem_base); | 2057 | if (__get_user(udata, &ss32->iomem_base)) |
2058 | return -EFAULT; | ||
2053 | ss.iomem_base = compat_ptr(udata); | 2059 | ss.iomem_base = compat_ptr(udata); |
2054 | __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); | 2060 | if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || |
2055 | __get_user(ss.port_high, &ss32->port_high); | 2061 | __get_user(ss.port_high, &ss32->port_high)) |
2062 | return -EFAULT; | ||
2056 | ss.iomap_base = 0UL; | 2063 | ss.iomap_base = 0UL; |
2057 | } | 2064 | } |
2058 | set_fs(KERNEL_DS); | 2065 | set_fs(KERNEL_DS); |
@@ -2063,12 +2070,12 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg) | |||
2063 | return -EFAULT; | 2070 | return -EFAULT; |
2064 | if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base))) | 2071 | if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base))) |
2065 | return -EFAULT; | 2072 | return -EFAULT; |
2066 | __put_user((unsigned long)ss.iomem_base >> 32 ? | 2073 | base = (unsigned long)ss.iomem_base >> 32 ? |
2067 | 0xffffffff : (unsigned)(unsigned long)ss.iomem_base, | 2074 | 0xffffffff : (unsigned)(unsigned long)ss.iomem_base; |
2068 | &ss32->iomem_base); | 2075 | if (__put_user(base, &ss32->iomem_base) || |
2069 | __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift); | 2076 | __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || |
2070 | __put_user(ss.port_high, &ss32->port_high); | 2077 | __put_user(ss.port_high, &ss32->port_high)) |
2071 | 2078 | return -EFAULT; | |
2072 | } | 2079 | } |
2073 | return err; | 2080 | return err; |
2074 | } | 2081 | } |