diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/fs/compat.c b/fs/compat.c index 18b21b4c9e3a..5333c7d7427f 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -73,17 +73,17 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __ | |||
73 | return do_utimes(AT_FDCWD, filename, t ? tv : NULL); | 73 | return do_utimes(AT_FDCWD, filename, t ? tv : NULL); |
74 | } | 74 | } |
75 | 75 | ||
76 | asmlinkage long compat_sys_futimesat(int dfd, char __user *filename, struct compat_timeval __user *t) | 76 | asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) |
77 | { | 77 | { |
78 | struct timeval tv[2]; | 78 | struct timeval tv[2]; |
79 | 79 | ||
80 | if (t) { | 80 | if (t) { |
81 | if (get_user(tv[0].tv_sec, &t[0].tv_sec) || | 81 | if (get_user(tv[0].tv_sec, &t[0].tv_sec) || |
82 | get_user(tv[0].tv_usec, &t[0].tv_usec) || | 82 | get_user(tv[0].tv_usec, &t[0].tv_usec) || |
83 | get_user(tv[1].tv_sec, &t[1].tv_sec) || | 83 | get_user(tv[1].tv_sec, &t[1].tv_sec) || |
84 | get_user(tv[1].tv_usec, &t[1].tv_usec)) | 84 | get_user(tv[1].tv_usec, &t[1].tv_usec)) |
85 | return -EFAULT; | 85 | return -EFAULT; |
86 | } | 86 | } |
87 | return do_utimes(dfd, filename, t ? tv : NULL); | 87 | return do_utimes(dfd, filename, t ? tv : NULL); |
88 | } | 88 | } |
89 | 89 | ||
@@ -114,7 +114,7 @@ asmlinkage long compat_sys_newlstat(char __user * filename, | |||
114 | return error; | 114 | return error; |
115 | } | 115 | } |
116 | 116 | ||
117 | asmlinkage long compat_sys_newfstatat(int dfd, char __user *filename, | 117 | asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, |
118 | struct compat_stat __user *statbuf, int flag) | 118 | struct compat_stat __user *statbuf, int flag) |
119 | { | 119 | { |
120 | struct kstat stat; | 120 | struct kstat stat; |
@@ -1326,7 +1326,7 @@ compat_sys_open(const char __user *filename, int flags, int mode) | |||
1326 | * O_LARGEFILE flag. | 1326 | * O_LARGEFILE flag. |
1327 | */ | 1327 | */ |
1328 | asmlinkage long | 1328 | asmlinkage long |
1329 | compat_sys_openat(int dfd, const char __user *filename, int flags, int mode) | 1329 | compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode) |
1330 | { | 1330 | { |
1331 | return do_sys_open(dfd, filename, flags, mode); | 1331 | return do_sys_open(dfd, filename, flags, mode); |
1332 | } | 1332 | } |
@@ -1743,7 +1743,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
1743 | if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS) | 1743 | if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS) |
1744 | timeout = -1; /* infinite */ | 1744 | timeout = -1; /* infinite */ |
1745 | else { | 1745 | else { |
1746 | timeout = ROUND_UP(tv.tv_sec, 1000000/HZ); | 1746 | timeout = ROUND_UP(tv.tv_usec, 1000000/HZ); |
1747 | timeout += tv.tv_sec * HZ; | 1747 | timeout += tv.tv_sec * HZ; |
1748 | } | 1748 | } |
1749 | } | 1749 | } |
@@ -1751,11 +1751,15 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
1751 | ret = compat_core_sys_select(n, inp, outp, exp, &timeout); | 1751 | ret = compat_core_sys_select(n, inp, outp, exp, &timeout); |
1752 | 1752 | ||
1753 | if (tvp) { | 1753 | if (tvp) { |
1754 | struct compat_timeval rtv; | ||
1755 | |||
1754 | if (current->personality & STICKY_TIMEOUTS) | 1756 | if (current->personality & STICKY_TIMEOUTS) |
1755 | goto sticky; | 1757 | goto sticky; |
1756 | tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)); | 1758 | rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)); |
1757 | tv.tv_sec = timeout; | 1759 | rtv.tv_sec = timeout; |
1758 | if (copy_to_user(tvp, &tv, sizeof(tv))) { | 1760 | if (compat_timeval_compare(&rtv, &tv) >= 0) |
1761 | rtv = tv; | ||
1762 | if (copy_to_user(tvp, &rtv, sizeof(rtv))) { | ||
1759 | sticky: | 1763 | sticky: |
1760 | /* | 1764 | /* |
1761 | * If an application puts its timeval in read-only | 1765 | * If an application puts its timeval in read-only |
@@ -1781,7 +1785,7 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1781 | { | 1785 | { |
1782 | compat_sigset_t ss32; | 1786 | compat_sigset_t ss32; |
1783 | sigset_t ksigmask, sigsaved; | 1787 | sigset_t ksigmask, sigsaved; |
1784 | long timeout = MAX_SCHEDULE_TIMEOUT; | 1788 | s64 timeout = MAX_SCHEDULE_TIMEOUT; |
1785 | struct compat_timespec ts; | 1789 | struct compat_timespec ts; |
1786 | int ret; | 1790 | int ret; |
1787 | 1791 | ||
@@ -1822,13 +1826,17 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1822 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); | 1826 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); |
1823 | 1827 | ||
1824 | if (tsp && !(current->personality & STICKY_TIMEOUTS)) { | 1828 | if (tsp && !(current->personality & STICKY_TIMEOUTS)) { |
1825 | ts.tv_sec += timeout / HZ; | 1829 | struct compat_timespec rts; |
1826 | ts.tv_nsec += (timeout % HZ) * (1000000000/HZ); | 1830 | |
1827 | if (ts.tv_nsec >= 1000000000) { | 1831 | rts.tv_sec = timeout / HZ; |
1828 | ts.tv_sec++; | 1832 | rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); |
1829 | ts.tv_nsec -= 1000000000; | 1833 | if (rts.tv_nsec >= NSEC_PER_SEC) { |
1834 | rts.tv_sec++; | ||
1835 | rts.tv_nsec -= NSEC_PER_SEC; | ||
1830 | } | 1836 | } |
1831 | (void)copy_to_user(tsp, &ts, sizeof(ts)); | 1837 | if (compat_timespec_compare(&rts, &ts) >= 0) |
1838 | rts = ts; | ||
1839 | copy_to_user(tsp, &rts, sizeof(rts)); | ||
1832 | } | 1840 | } |
1833 | 1841 | ||
1834 | if (ret == -ERESTARTNOHAND) { | 1842 | if (ret == -ERESTARTNOHAND) { |
@@ -1884,7 +1892,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | |||
1884 | /* We assume that ts.tv_sec is always lower than | 1892 | /* We assume that ts.tv_sec is always lower than |
1885 | the number of seconds that can be expressed in | 1893 | the number of seconds that can be expressed in |
1886 | an s64. Otherwise the compiler bitches at us */ | 1894 | an s64. Otherwise the compiler bitches at us */ |
1887 | timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ); | 1895 | timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ); |
1888 | timeout += ts.tv_sec * HZ; | 1896 | timeout += ts.tv_sec * HZ; |
1889 | } | 1897 | } |
1890 | 1898 | ||
@@ -1918,12 +1926,17 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, | |||
1918 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); | 1926 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); |
1919 | 1927 | ||
1920 | if (tsp && timeout >= 0) { | 1928 | if (tsp && timeout >= 0) { |
1929 | struct compat_timespec rts; | ||
1930 | |||
1921 | if (current->personality & STICKY_TIMEOUTS) | 1931 | if (current->personality & STICKY_TIMEOUTS) |
1922 | goto sticky; | 1932 | goto sticky; |
1923 | /* Yes, we know it's actually an s64, but it's also positive. */ | 1933 | /* Yes, we know it's actually an s64, but it's also positive. */ |
1924 | ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000; | 1934 | rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * |
1925 | ts.tv_sec = timeout; | 1935 | 1000; |
1926 | if (copy_to_user(tsp, &ts, sizeof(ts))) { | 1936 | rts.tv_sec = timeout; |
1937 | if (compat_timespec_compare(&rts, &ts) >= 0) | ||
1938 | rts = ts; | ||
1939 | if (copy_to_user(tsp, &rts, sizeof(rts))) { | ||
1927 | sticky: | 1940 | sticky: |
1928 | /* | 1941 | /* |
1929 | * If an application puts its timeval in read-only | 1942 | * If an application puts its timeval in read-only |