diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2006-11-03 01:06:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-03 15:27:55 -0500 |
commit | 87c2b7c045a44f6c1c7af23e64f2b286e6f7130a (patch) | |
tree | 42c59705e0b04b8cd4770556f59f65228b62feaa /fs | |
parent | 7870db4c7fa1b03fec133c4f4e67fdaa04c5ac15 (diff) |
[PATCH] sys_pselect7 vs compat_sys_pselect7 uaccess error handling
758333458aa719bfc26ec16eafd4ad3a9e96014d fixes the not checked copy_to_user
return value of compat_sys_pselect7. I ran into this too because of an old
source tree, but my fix would look quite a bit different to Andi's fix.
The reason is that the compat function IMHO should behave the very same as
the non-compat function if possible. Since sys_pselect7 does not return
-EFAULT in this specific case, change the compat code so it behaves like
sys_pselect7.
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/compat.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/compat.c b/fs/compat.c index 50624d4a70c6..8d0a0018a7d2 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1835,9 +1835,12 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1835 | 1835 | ||
1836 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); | 1836 | } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); |
1837 | 1837 | ||
1838 | if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) { | 1838 | if (tsp) { |
1839 | struct compat_timespec rts; | 1839 | struct compat_timespec rts; |
1840 | 1840 | ||
1841 | if (current->personality & STICKY_TIMEOUTS) | ||
1842 | goto sticky; | ||
1843 | |||
1841 | rts.tv_sec = timeout / HZ; | 1844 | rts.tv_sec = timeout / HZ; |
1842 | rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); | 1845 | rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); |
1843 | if (rts.tv_nsec >= NSEC_PER_SEC) { | 1846 | if (rts.tv_nsec >= NSEC_PER_SEC) { |
@@ -1846,8 +1849,19 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, | |||
1846 | } | 1849 | } |
1847 | if (compat_timespec_compare(&rts, &ts) >= 0) | 1850 | if (compat_timespec_compare(&rts, &ts) >= 0) |
1848 | rts = ts; | 1851 | rts = ts; |
1849 | if (copy_to_user(tsp, &rts, sizeof(rts))) | 1852 | if (copy_to_user(tsp, &rts, sizeof(rts))) { |
1850 | ret = -EFAULT; | 1853 | sticky: |
1854 | /* | ||
1855 | * If an application puts its timeval in read-only | ||
1856 | * memory, we don't want the Linux-specific update to | ||
1857 | * the timeval to cause a fault after the select has | ||
1858 | * completed successfully. However, because we're not | ||
1859 | * updating the timeval, we can't restart the system | ||
1860 | * call. | ||
1861 | */ | ||
1862 | if (ret == -ERESTARTNOHAND) | ||
1863 | ret = -EINTR; | ||
1864 | } | ||
1851 | } | 1865 | } |
1852 | 1866 | ||
1853 | if (ret == -ERESTARTNOHAND) { | 1867 | if (ret == -ERESTARTNOHAND) { |