aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
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 /fs/compat.c
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>
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c35
1 files changed, 19 insertions, 16 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: