aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c210
1 files changed, 80 insertions, 130 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 5f9ec449c79..e5f49f53850 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -869,7 +869,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
869 buf.dirent = dirent; 869 buf.dirent = dirent;
870 870
871 error = vfs_readdir(file, compat_fillonedir, &buf); 871 error = vfs_readdir(file, compat_fillonedir, &buf);
872 if (error >= 0) 872 if (buf.result)
873 error = buf.result; 873 error = buf.result;
874 874
875 fput(file); 875 fput(file);
@@ -956,9 +956,8 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
956 buf.error = 0; 956 buf.error = 0;
957 957
958 error = vfs_readdir(file, compat_filldir, &buf); 958 error = vfs_readdir(file, compat_filldir, &buf);
959 if (error < 0) 959 if (error >= 0)
960 goto out_putf; 960 error = buf.error;
961 error = buf.error;
962 lastdirent = buf.previous; 961 lastdirent = buf.previous;
963 if (lastdirent) { 962 if (lastdirent) {
964 if (put_user(file->f_pos, &lastdirent->d_off)) 963 if (put_user(file->f_pos, &lastdirent->d_off))
@@ -966,8 +965,6 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
966 else 965 else
967 error = count - buf.count; 966 error = count - buf.count;
968 } 967 }
969
970out_putf:
971 fput(file); 968 fput(file);
972out: 969out:
973 return error; 970 return error;
@@ -1047,19 +1044,16 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
1047 buf.error = 0; 1044 buf.error = 0;
1048 1045
1049 error = vfs_readdir(file, compat_filldir64, &buf); 1046 error = vfs_readdir(file, compat_filldir64, &buf);
1050 if (error < 0) 1047 if (error >= 0)
1051 goto out_putf; 1048 error = buf.error;
1052 error = buf.error;
1053 lastdirent = buf.previous; 1049 lastdirent = buf.previous;
1054 if (lastdirent) { 1050 if (lastdirent) {
1055 typeof(lastdirent->d_off) d_off = file->f_pos; 1051 typeof(lastdirent->d_off) d_off = file->f_pos;
1056 error = -EFAULT;
1057 if (__put_user_unaligned(d_off, &lastdirent->d_off)) 1052 if (__put_user_unaligned(d_off, &lastdirent->d_off))
1058 goto out_putf; 1053 error = -EFAULT;
1059 error = count - buf.count; 1054 else
1055 error = count - buf.count;
1060 } 1056 }
1061
1062out_putf:
1063 fput(file); 1057 fput(file);
1064out: 1058out:
1065 return error; 1059 return error;
@@ -1475,6 +1469,57 @@ out_ret:
1475 1469
1476#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1470#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1477 1471
1472static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1473 int timeval, int ret)
1474{
1475 struct timespec ts;
1476
1477 if (!p)
1478 return ret;
1479
1480 if (current->personality & STICKY_TIMEOUTS)
1481 goto sticky;
1482
1483 /* No update for zero timeout */
1484 if (!end_time->tv_sec && !end_time->tv_nsec)
1485 return ret;
1486
1487 ktime_get_ts(&ts);
1488 ts = timespec_sub(*end_time, ts);
1489 if (ts.tv_sec < 0)
1490 ts.tv_sec = ts.tv_nsec = 0;
1491
1492 if (timeval) {
1493 struct compat_timeval rtv;
1494
1495 rtv.tv_sec = ts.tv_sec;
1496 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1497
1498 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1499 return ret;
1500 } else {
1501 struct compat_timespec rts;
1502
1503 rts.tv_sec = ts.tv_sec;
1504 rts.tv_nsec = ts.tv_nsec;
1505
1506 if (!copy_to_user(p, &rts, sizeof(rts)))
1507 return ret;
1508 }
1509 /*
1510 * If an application puts its timeval in read-only memory, we
1511 * don't want the Linux-specific update to the timeval to
1512 * cause a fault after the select has completed
1513 * successfully. However, because we're not updating the
1514 * timeval, we can't restart the system call.
1515 */
1516
1517sticky:
1518 if (ret == -ERESTARTNOHAND)
1519 ret = -EINTR;
1520 return ret;
1521}
1522
1478/* 1523/*
1479 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1524 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1480 * 64-bit unsigned longs. 1525 * 64-bit unsigned longs.
@@ -1556,7 +1601,8 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1556 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1601 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1557 1602
1558int compat_core_sys_select(int n, compat_ulong_t __user *inp, 1603int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1559 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) 1604 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1605 struct timespec *end_time)
1560{ 1606{
1561 fd_set_bits fds; 1607 fd_set_bits fds;
1562 void *bits; 1608 void *bits;
@@ -1603,7 +1649,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1603 zero_fd_set(n, fds.res_out); 1649 zero_fd_set(n, fds.res_out);
1604 zero_fd_set(n, fds.res_ex); 1650 zero_fd_set(n, fds.res_ex);
1605 1651
1606 ret = do_select(n, &fds, timeout); 1652 ret = do_select(n, &fds, end_time);
1607 1653
1608 if (ret < 0) 1654 if (ret < 0)
1609 goto out; 1655 goto out;
@@ -1629,7 +1675,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1629 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1675 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1630 struct compat_timeval __user *tvp) 1676 struct compat_timeval __user *tvp)
1631{ 1677{
1632 s64 timeout = -1; 1678 struct timespec end_time, *to = NULL;
1633 struct compat_timeval tv; 1679 struct compat_timeval tv;
1634 int ret; 1680 int ret;
1635 1681
@@ -1637,43 +1683,15 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1637 if (copy_from_user(&tv, tvp, sizeof(tv))) 1683 if (copy_from_user(&tv, tvp, sizeof(tv)))
1638 return -EFAULT; 1684 return -EFAULT;
1639 1685
1640 if (tv.tv_sec < 0 || tv.tv_usec < 0) 1686 to = &end_time;
1687 if (poll_select_set_timeout(to,
1688 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1689 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1641 return -EINVAL; 1690 return -EINVAL;
1642
1643 /* Cast to u64 to make GCC stop complaining */
1644 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
1645 timeout = -1; /* infinite */
1646 else {
1647 timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ);
1648 timeout += tv.tv_sec * HZ;
1649 }
1650 } 1691 }
1651 1692
1652 ret = compat_core_sys_select(n, inp, outp, exp, &timeout); 1693 ret = compat_core_sys_select(n, inp, outp, exp, to);
1653 1694 ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1654 if (tvp) {
1655 struct compat_timeval rtv;
1656
1657 if (current->personality & STICKY_TIMEOUTS)
1658 goto sticky;
1659 rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
1660 rtv.tv_sec = timeout;
1661 if (compat_timeval_compare(&rtv, &tv) >= 0)
1662 rtv = tv;
1663 if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
1664sticky:
1665 /*
1666 * If an application puts its timeval in read-only
1667 * memory, we don't want the Linux-specific update to
1668 * the timeval to cause a fault after the select has
1669 * completed successfully. However, because we're not
1670 * updating the timeval, we can't restart the system
1671 * call.
1672 */
1673 if (ret == -ERESTARTNOHAND)
1674 ret = -EINTR;
1675 }
1676 }
1677 1695
1678 return ret; 1696 return ret;
1679} 1697}
@@ -1686,15 +1704,16 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1686{ 1704{
1687 compat_sigset_t ss32; 1705 compat_sigset_t ss32;
1688 sigset_t ksigmask, sigsaved; 1706 sigset_t ksigmask, sigsaved;
1689 s64 timeout = MAX_SCHEDULE_TIMEOUT;
1690 struct compat_timespec ts; 1707 struct compat_timespec ts;
1708 struct timespec end_time, *to = NULL;
1691 int ret; 1709 int ret;
1692 1710
1693 if (tsp) { 1711 if (tsp) {
1694 if (copy_from_user(&ts, tsp, sizeof(ts))) 1712 if (copy_from_user(&ts, tsp, sizeof(ts)))
1695 return -EFAULT; 1713 return -EFAULT;
1696 1714
1697 if (ts.tv_sec < 0 || ts.tv_nsec < 0) 1715 to = &end_time;
1716 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1698 return -EINVAL; 1717 return -EINVAL;
1699 } 1718 }
1700 1719
@@ -1709,51 +1728,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1709 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1728 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1710 } 1729 }
1711 1730
1712 do { 1731 ret = compat_core_sys_select(n, inp, outp, exp, to);
1713 if (tsp) { 1732 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1714 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
1715 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1716 timeout += ts.tv_sec * (unsigned long)HZ;
1717 ts.tv_sec = 0;
1718 ts.tv_nsec = 0;
1719 } else {
1720 ts.tv_sec -= MAX_SELECT_SECONDS;
1721 timeout = MAX_SELECT_SECONDS * HZ;
1722 }
1723 }
1724
1725 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1726
1727 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
1728
1729 if (tsp) {
1730 struct compat_timespec rts;
1731
1732 if (current->personality & STICKY_TIMEOUTS)
1733 goto sticky;
1734
1735 rts.tv_sec = timeout / HZ;
1736 rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
1737 if (rts.tv_nsec >= NSEC_PER_SEC) {
1738 rts.tv_sec++;
1739 rts.tv_nsec -= NSEC_PER_SEC;
1740 }
1741 if (compat_timespec_compare(&rts, &ts) >= 0)
1742 rts = ts;
1743 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1744sticky:
1745 /*
1746 * If an application puts its timeval in read-only
1747 * memory, we don't want the Linux-specific update to
1748 * the timeval to cause a fault after the select has
1749 * completed successfully. However, because we're not
1750 * updating the timeval, we can't restart the system
1751 * call.
1752 */
1753 if (ret == -ERESTARTNOHAND)
1754 ret = -EINTR;
1755 }
1756 }
1757 1733
1758 if (ret == -ERESTARTNOHAND) { 1734 if (ret == -ERESTARTNOHAND) {
1759 /* 1735 /*
@@ -1798,18 +1774,16 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1798 compat_sigset_t ss32; 1774 compat_sigset_t ss32;
1799 sigset_t ksigmask, sigsaved; 1775 sigset_t ksigmask, sigsaved;
1800 struct compat_timespec ts; 1776 struct compat_timespec ts;
1801 s64 timeout = -1; 1777 struct timespec end_time, *to = NULL;
1802 int ret; 1778 int ret;
1803 1779
1804 if (tsp) { 1780 if (tsp) {
1805 if (copy_from_user(&ts, tsp, sizeof(ts))) 1781 if (copy_from_user(&ts, tsp, sizeof(ts)))
1806 return -EFAULT; 1782 return -EFAULT;
1807 1783
1808 /* We assume that ts.tv_sec is always lower than 1784 to = &end_time;
1809 the number of seconds that can be expressed in 1785 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1810 an s64. Otherwise the compiler bitches at us */ 1786 return -EINVAL;
1811 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1812 timeout += ts.tv_sec * HZ;
1813 } 1787 }
1814 1788
1815 if (sigmask) { 1789 if (sigmask) {
@@ -1823,7 +1797,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1823 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1797 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1824 } 1798 }
1825 1799
1826 ret = do_sys_poll(ufds, nfds, &timeout); 1800 ret = do_sys_poll(ufds, nfds, to);
1827 1801
1828 /* We can restart this syscall, usually */ 1802 /* We can restart this syscall, usually */
1829 if (ret == -EINTR) { 1803 if (ret == -EINTR) {
@@ -1841,31 +1815,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1841 } else if (sigmask) 1815 } else if (sigmask)
1842 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1816 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1843 1817
1844 if (tsp && timeout >= 0) { 1818 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1845 struct compat_timespec rts;
1846
1847 if (current->personality & STICKY_TIMEOUTS)
1848 goto sticky;
1849 /* Yes, we know it's actually an s64, but it's also positive. */
1850 rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
1851 1000;
1852 rts.tv_sec = timeout;
1853 if (compat_timespec_compare(&rts, &ts) >= 0)
1854 rts = ts;
1855 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1856sticky:
1857 /*
1858 * If an application puts its timeval in read-only
1859 * memory, we don't want the Linux-specific update to
1860 * the timeval to cause a fault after the select has
1861 * completed successfully. However, because we're not
1862 * updating the timeval, we can't restart the system
1863 * call.
1864 */
1865 if (ret == -ERESTARTNOHAND && timeout >= 0)
1866 ret = -EINTR;
1867 }
1868 }
1869 1819
1870 return ret; 1820 return ret;
1871} 1821}