diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 187 |
1 files changed, 71 insertions, 116 deletions
diff --git a/fs/compat.c b/fs/compat.c index 5f9ec449c799..3b58c32be526 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1475,6 +1475,57 @@ out_ret: | |||
1475 | 1475 | ||
1476 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) | 1476 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) |
1477 | 1477 | ||
1478 | static int poll_select_copy_remaining(struct timespec *end_time, void __user *p, | ||
1479 | int timeval, int ret) | ||
1480 | { | ||
1481 | struct timespec ts; | ||
1482 | |||
1483 | if (!p) | ||
1484 | return ret; | ||
1485 | |||
1486 | if (current->personality & STICKY_TIMEOUTS) | ||
1487 | goto sticky; | ||
1488 | |||
1489 | /* No update for zero timeout */ | ||
1490 | if (!end_time->tv_sec && !end_time->tv_nsec) | ||
1491 | return ret; | ||
1492 | |||
1493 | ktime_get_ts(&ts); | ||
1494 | ts = timespec_sub(*end_time, ts); | ||
1495 | if (ts.tv_sec < 0) | ||
1496 | ts.tv_sec = ts.tv_nsec = 0; | ||
1497 | |||
1498 | if (timeval) { | ||
1499 | struct compat_timeval rtv; | ||
1500 | |||
1501 | rtv.tv_sec = ts.tv_sec; | ||
1502 | rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | ||
1503 | |||
1504 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | ||
1505 | return ret; | ||
1506 | } else { | ||
1507 | struct compat_timespec rts; | ||
1508 | |||
1509 | rts.tv_sec = ts.tv_sec; | ||
1510 | rts.tv_nsec = ts.tv_nsec; | ||
1511 | |||
1512 | if (!copy_to_user(p, &rts, sizeof(rts))) | ||
1513 | return ret; | ||
1514 | } | ||
1515 | /* | ||
1516 | * If an application puts its timeval in read-only memory, we | ||
1517 | * don't want the Linux-specific update to the timeval to | ||
1518 | * cause a fault after the select has completed | ||
1519 | * successfully. However, because we're not updating the | ||
1520 | * timeval, we can't restart the system call. | ||
1521 | */ | ||
1522 | |||
1523 | sticky: | ||
1524 | if (ret == -ERESTARTNOHAND) | ||
1525 | ret = -EINTR; | ||
1526 | return ret; | ||
1527 | } | ||
1528 | |||
1478 | /* | 1529 | /* |
1479 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to | 1530 | * Ooo, nasty. We need here to frob 32-bit unsigned longs to |
1480 | * 64-bit unsigned longs. | 1531 | * 64-bit unsigned longs. |
@@ -1556,7 +1607,8 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1556 | ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) | 1607 | ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) |
1557 | 1608 | ||
1558 | int compat_core_sys_select(int n, compat_ulong_t __user *inp, | 1609 | int compat_core_sys_select(int n, compat_ulong_t __user *inp, |
1559 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) | 1610 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
1611 | struct timespec *end_time) | ||
1560 | { | 1612 | { |
1561 | fd_set_bits fds; | 1613 | fd_set_bits fds; |
1562 | void *bits; | 1614 | void *bits; |
@@ -1603,7 +1655,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1603 | zero_fd_set(n, fds.res_out); | 1655 | zero_fd_set(n, fds.res_out); |
1604 | zero_fd_set(n, fds.res_ex); | 1656 | zero_fd_set(n, fds.res_ex); |
1605 | 1657 | ||
1606 | ret = do_select(n, &fds, timeout); | 1658 | ret = do_select(n, &fds, end_time); |
1607 | 1659 | ||
1608 | if (ret < 0) | 1660 | if (ret < 0) |
1609 | goto out; | 1661 | goto out; |
@@ -1629,7 +1681,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
1629 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1681 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
1630 | struct compat_timeval __user *tvp) | 1682 | struct compat_timeval __user *tvp) |
1631 | { | 1683 | { |
1632 | s64 timeout = -1; | 1684 | struct timespec end_time, *to = NULL; |
1633 | struct compat_timeval tv; | 1685 | struct compat_timeval tv; |
1634 | int ret; | 1686 | int ret; |
1635 | 1687 | ||
@@ -1637,43 +1689,14 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
1637 | if (copy_from_user(&tv, tvp, sizeof(tv))) | 1689 | if (copy_from_user(&tv, tvp, sizeof(tv))) |
1638 | return -EFAULT; | 1690 | return -EFAULT; |
1639 | 1691 | ||
1640 | if (tv.tv_sec < 0 || tv.tv_usec < 0) | 1692 | to = &end_time; |
1693 | if (poll_select_set_timeout(to, tv.tv_sec, | ||
1694 | tv.tv_usec * NSEC_PER_USEC)) | ||
1641 | return -EINVAL; | 1695 | 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 | } | 1696 | } |
1651 | 1697 | ||
1652 | ret = compat_core_sys_select(n, inp, outp, exp, &timeout); | 1698 | ret = compat_core_sys_select(n, inp, outp, exp, to); |
1653 | 1699 | 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))) { | ||
1664 | sticky: | ||
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 | 1700 | ||
1678 | return ret; | 1701 | return ret; |
1679 | } | 1702 | } |
@@ -1686,15 +1709,16 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1686 | { | 1709 | { |
1687 | compat_sigset_t ss32; | 1710 | compat_sigset_t ss32; |
1688 | sigset_t ksigmask, sigsaved; | 1711 | sigset_t ksigmask, sigsaved; |
1689 | s64 timeout = MAX_SCHEDULE_TIMEOUT; | ||
1690 | struct compat_timespec ts; | 1712 | struct compat_timespec ts; |
1713 | struct timespec end_time, *to = NULL; | ||
1691 | int ret; | 1714 | int ret; |
1692 | 1715 | ||
1693 | if (tsp) { | 1716 | if (tsp) { |
1694 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1717 | if (copy_from_user(&ts, tsp, sizeof(ts))) |
1695 | return -EFAULT; | 1718 | return -EFAULT; |
1696 | 1719 | ||
1697 | if (ts.tv_sec < 0 || ts.tv_nsec < 0) | 1720 | to = &end_time; |
1721 | if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) | ||
1698 | return -EINVAL; | 1722 | return -EINVAL; |
1699 | } | 1723 | } |
1700 | 1724 | ||
@@ -1709,51 +1733,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1709 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1733 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
1710 | } | 1734 | } |
1711 | 1735 | ||
1712 | do { | 1736 | ret = compat_core_sys_select(n, inp, outp, exp, to); |
1713 | if (tsp) { | 1737 | 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))) { | ||
1744 | sticky: | ||
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 | 1738 | ||
1758 | if (ret == -ERESTARTNOHAND) { | 1739 | if (ret == -ERESTARTNOHAND) { |
1759 | /* | 1740 | /* |
@@ -1798,18 +1779,16 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | |||
1798 | compat_sigset_t ss32; | 1779 | compat_sigset_t ss32; |
1799 | sigset_t ksigmask, sigsaved; | 1780 | sigset_t ksigmask, sigsaved; |
1800 | struct compat_timespec ts; | 1781 | struct compat_timespec ts; |
1801 | s64 timeout = -1; | 1782 | struct timespec end_time, *to = NULL; |
1802 | int ret; | 1783 | int ret; |
1803 | 1784 | ||
1804 | if (tsp) { | 1785 | if (tsp) { |
1805 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1786 | if (copy_from_user(&ts, tsp, sizeof(ts))) |
1806 | return -EFAULT; | 1787 | return -EFAULT; |
1807 | 1788 | ||
1808 | /* We assume that ts.tv_sec is always lower than | 1789 | to = &end_time; |
1809 | the number of seconds that can be expressed in | 1790 | if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) |
1810 | an s64. Otherwise the compiler bitches at us */ | 1791 | return -EINVAL; |
1811 | timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ); | ||
1812 | timeout += ts.tv_sec * HZ; | ||
1813 | } | 1792 | } |
1814 | 1793 | ||
1815 | if (sigmask) { | 1794 | if (sigmask) { |
@@ -1823,7 +1802,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | |||
1823 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1802 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
1824 | } | 1803 | } |
1825 | 1804 | ||
1826 | ret = do_sys_poll(ufds, nfds, &timeout); | 1805 | ret = do_sys_poll(ufds, nfds, to); |
1827 | 1806 | ||
1828 | /* We can restart this syscall, usually */ | 1807 | /* We can restart this syscall, usually */ |
1829 | if (ret == -EINTR) { | 1808 | if (ret == -EINTR) { |
@@ -1841,31 +1820,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | |||
1841 | } else if (sigmask) | 1820 | } else if (sigmask) |
1842 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); | 1821 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); |
1843 | 1822 | ||
1844 | if (tsp && timeout >= 0) { | 1823 | 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))) { | ||
1856 | sticky: | ||
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 | 1824 | ||
1870 | return ret; | 1825 | return ret; |
1871 | } | 1826 | } |