Skip to content

Commit ea2ce8f

Browse files
deepa-hubarndb
authored andcommitted
time: Fix get_timespec64() for y2038 safe compat interfaces
get/put_timespec64() interfaces will eventually be used for conversions between the new y2038 safe struct __kernel_timespec and struct timespec64. The new y2038 safe syscalls have a common entry for native and compat interfaces. On compat interfaces, the high order bits of nanoseconds should be zeroed out. This is because the application code or the libc do not guarantee zeroing of these. If used without zeroing, kernel might be at risk of using timespec values incorrectly. Note that clearing of bits is dependent on CONFIG_64BIT_TIME for now. This is until COMPAT_USE_64BIT_TIME has been handled correctly. x86 will be the first architecture that will use the CONFIG_64BIT_TIME. Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1 parent acf8870 commit ea2ce8f

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

include/linux/time.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
extern struct timezone sys_tz;
1111

1212
int get_timespec64(struct timespec64 *ts,
13-
const struct timespec __user *uts);
13+
const struct __kernel_timespec __user *uts);
1414
int put_timespec64(const struct timespec64 *ts,
15-
struct timespec __user *uts);
15+
struct __kernel_timespec __user *uts);
1616
int get_itimerspec64(struct itimerspec64 *it,
1717
const struct itimerspec __user *uit);
1818
int put_itimerspec64(const struct itimerspec64 *it,

kernel/time/time.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,29 +853,35 @@ struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
853853
}
854854

855855
int get_timespec64(struct timespec64 *ts,
856-
const struct timespec __user *uts)
856+
const struct __kernel_timespec __user *uts)
857857
{
858-
struct timespec kts;
858+
struct __kernel_timespec kts;
859859
int ret;
860860

861861
ret = copy_from_user(&kts, uts, sizeof(kts));
862862
if (ret)
863863
return -EFAULT;
864864

865865
ts->tv_sec = kts.tv_sec;
866+
867+
/* Zero out the padding for 32 bit systems or in compat mode */
868+
if (IS_ENABLED(CONFIG_64BIT_TIME) && (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall()))
869+
kts.tv_nsec &= 0xFFFFFFFFUL;
870+
866871
ts->tv_nsec = kts.tv_nsec;
867872

868873
return 0;
869874
}
870875
EXPORT_SYMBOL_GPL(get_timespec64);
871876

872877
int put_timespec64(const struct timespec64 *ts,
873-
struct timespec __user *uts)
878+
struct __kernel_timespec __user *uts)
874879
{
875-
struct timespec kts = {
880+
struct __kernel_timespec kts = {
876881
.tv_sec = ts->tv_sec,
877882
.tv_nsec = ts->tv_nsec
878883
};
884+
879885
return copy_to_user(uts, &kts, sizeof(kts)) ? -EFAULT : 0;
880886
}
881887
EXPORT_SYMBOL_GPL(put_timespec64);

0 commit comments

Comments
 (0)