aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-12-06 23:36:36 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:33 -0500
commit7116e994b47f3988389be4ceee67dac64b56e0d0 (patch)
treef6b722a14cba117898456c3a9edbe7538310db2f
parent841d5fb7c75260f76ae682648b28a3dca724940d (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.c35
-rw-r--r--fs/compat_ioctl.c33
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
1632static 1634static
1633void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1635int 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;
1733out: 1736out:
1734 kfree(bits); 1737 kfree(bits);
1735out_nofds: 1738out_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}