diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2006-11-04 22:42:39 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2006-11-04 22:42:39 -0500 |
commit | 752c58a471c108d64da1676b2925dfbd83eb177e (patch) | |
tree | fbffa0d7c54cd812950dffc16d642c9d449f4faf /fs/compat.c | |
parent | e52b29c2a637f6854d71a45646d7283d984a6dad (diff) | |
parent | 10b1fbdb0a0ca91847a534ad26d0bc250c25b74f (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/compat.c')
-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, } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); - if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) { + if (tsp) { struct compat_timespec rts; + if (current->personality & STICKY_TIMEOUTS) + goto sticky; + rts.tv_sec = timeout / HZ; rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); if (rts.tv_nsec >= NSEC_PER_SEC) { @@ -1846,8 +1849,19 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, } if (compat_timespec_compare(&rts, &ts) >= 0) rts = ts; - if (copy_to_user(tsp, &rts, sizeof(rts))) - ret = -EFAULT; + if (copy_to_user(tsp, &rts, sizeof(rts))) { +sticky: + /* + * If an application puts its timeval in read-only + * memory, we don't want the Linux-specific update to + * the timeval to cause a fault after the select has + * completed successfully. However, because we're not + * updating the timeval, we can't restart the system + * call. + */ + if (ret == -ERESTARTNOHAND) + ret = -EINTR; + } } if (ret == -ERESTARTNOHAND) { |