diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-04-17 11:23:35 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-12-07 16:19:07 -0500 |
commit | bec2f7cbb73eadf5e1cc7d54ecb0980ede244257 (patch) | |
tree | 24d06866d036f57bed35f0828f42d9fa63256eb2 /kernel/futex.c | |
parent | 04e7712f4460585e5eed5b853fd8b82a9943958f (diff) |
y2038: futex: Add support for __kernel_timespec
This prepares sys_futex for y2038 safe calling: the native
syscall is changed to receive a __kernel_timespec argument, which
will be switched to 64-bit time_t in the future. All the internal
time handling gets changed to timespec64, and the compat_sys_futex
entry point is moved under the CONFIG_COMPAT_32BIT_TIME check
to provide compatibility for existing 32-bit architectures.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 5cc7c3b098e9..b305beaab739 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -3558,10 +3558,10 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | |||
3558 | 3558 | ||
3559 | 3559 | ||
3560 | SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | 3560 | SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, |
3561 | struct timespec __user *, utime, u32 __user *, uaddr2, | 3561 | struct __kernel_timespec __user *, utime, u32 __user *, uaddr2, |
3562 | u32, val3) | 3562 | u32, val3) |
3563 | { | 3563 | { |
3564 | struct timespec ts; | 3564 | struct timespec64 ts; |
3565 | ktime_t t, *tp = NULL; | 3565 | ktime_t t, *tp = NULL; |
3566 | u32 val2 = 0; | 3566 | u32 val2 = 0; |
3567 | int cmd = op & FUTEX_CMD_MASK; | 3567 | int cmd = op & FUTEX_CMD_MASK; |
@@ -3571,12 +3571,12 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | |||
3571 | cmd == FUTEX_WAIT_REQUEUE_PI)) { | 3571 | cmd == FUTEX_WAIT_REQUEUE_PI)) { |
3572 | if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG)))) | 3572 | if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG)))) |
3573 | return -EFAULT; | 3573 | return -EFAULT; |
3574 | if (copy_from_user(&ts, utime, sizeof(ts)) != 0) | 3574 | if (get_timespec64(&ts, utime)) |
3575 | return -EFAULT; | 3575 | return -EFAULT; |
3576 | if (!timespec_valid(&ts)) | 3576 | if (!timespec64_valid(&ts)) |
3577 | return -EINVAL; | 3577 | return -EINVAL; |
3578 | 3578 | ||
3579 | t = timespec_to_ktime(ts); | 3579 | t = timespec64_to_ktime(ts); |
3580 | if (cmd == FUTEX_WAIT) | 3580 | if (cmd == FUTEX_WAIT) |
3581 | t = ktime_add_safe(ktime_get(), t); | 3581 | t = ktime_add_safe(ktime_get(), t); |
3582 | tp = &t; | 3582 | tp = &t; |
@@ -3747,12 +3747,14 @@ err_unlock: | |||
3747 | 3747 | ||
3748 | return ret; | 3748 | return ret; |
3749 | } | 3749 | } |
3750 | #endif /* CONFIG_COMPAT */ | ||
3750 | 3751 | ||
3752 | #ifdef CONFIG_COMPAT_32BIT_TIME | ||
3751 | COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | 3753 | COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, |
3752 | struct old_timespec32 __user *, utime, u32 __user *, uaddr2, | 3754 | struct old_timespec32 __user *, utime, u32 __user *, uaddr2, |
3753 | u32, val3) | 3755 | u32, val3) |
3754 | { | 3756 | { |
3755 | struct timespec ts; | 3757 | struct timespec64 ts; |
3756 | ktime_t t, *tp = NULL; | 3758 | ktime_t t, *tp = NULL; |
3757 | int val2 = 0; | 3759 | int val2 = 0; |
3758 | int cmd = op & FUTEX_CMD_MASK; | 3760 | int cmd = op & FUTEX_CMD_MASK; |
@@ -3760,12 +3762,12 @@ COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | |||
3760 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || | 3762 | if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || |
3761 | cmd == FUTEX_WAIT_BITSET || | 3763 | cmd == FUTEX_WAIT_BITSET || |
3762 | cmd == FUTEX_WAIT_REQUEUE_PI)) { | 3764 | cmd == FUTEX_WAIT_REQUEUE_PI)) { |
3763 | if (compat_get_timespec(&ts, utime)) | 3765 | if (get_old_timespec32(&ts, utime)) |
3764 | return -EFAULT; | 3766 | return -EFAULT; |
3765 | if (!timespec_valid(&ts)) | 3767 | if (!timespec64_valid(&ts)) |
3766 | return -EINVAL; | 3768 | return -EINVAL; |
3767 | 3769 | ||
3768 | t = timespec_to_ktime(ts); | 3770 | t = timespec64_to_ktime(ts); |
3769 | if (cmd == FUTEX_WAIT) | 3771 | if (cmd == FUTEX_WAIT) |
3770 | t = ktime_add_safe(ktime_get(), t); | 3772 | t = ktime_add_safe(ktime_get(), t); |
3771 | tp = &t; | 3773 | tp = &t; |
@@ -3776,7 +3778,7 @@ COMPAT_SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, | |||
3776 | 3778 | ||
3777 | return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); | 3779 | return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); |
3778 | } | 3780 | } |
3779 | #endif /* CONFIG_COMPAT */ | 3781 | #endif /* CONFIG_COMPAT_32BIT_TIME */ |
3780 | 3782 | ||
3781 | static void __init futex_detect_cmpxchg(void) | 3783 | static void __init futex_detect_cmpxchg(void) |
3782 | { | 3784 | { |