Skip to content

Commit 5e0fb1b

Browse files
committed
y2038: time: avoid timespec usage in settimeofday()
The compat_get_timeval() and timeval_valid() interfaces are deprecated and getting removed along with the definition of struct timeval itself. Change the two implementations of the settimeofday() system call to open-code these helpers and completely avoid references to timeval. The timeval_valid() call is not needed any more here, only a check to avoid overflowing tv_nsec during the multiplication, as there is another range check in do_sys_settimeofday64(). Tested-by: [email protected] Signed-off-by: Arnd Bergmann <[email protected]>
1 parent bde9e96 commit 5e0fb1b

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

include/linux/syscalls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct g
734734
/* kernel/time.c */
735735
asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv,
736736
struct timezone __user *tz);
737-
asmlinkage long sys_settimeofday(struct timeval __user *tv,
737+
asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv,
738738
struct timezone __user *tz);
739739
asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p);
740740
asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p);

kernel/time/time.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,22 +196,21 @@ int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz
196196
return 0;
197197
}
198198

199-
SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
199+
SYSCALL_DEFINE2(settimeofday, struct __kernel_old_timeval __user *, tv,
200200
struct timezone __user *, tz)
201201
{
202202
struct timespec64 new_ts;
203-
struct timeval user_tv;
204203
struct timezone new_tz;
205204

206205
if (tv) {
207-
if (copy_from_user(&user_tv, tv, sizeof(*tv)))
206+
if (get_user(new_ts.tv_sec, &tv->tv_sec) ||
207+
get_user(new_ts.tv_nsec, &tv->tv_usec))
208208
return -EFAULT;
209209

210-
if (!timeval_valid(&user_tv))
210+
if (new_ts.tv_nsec > USEC_PER_SEC || new_ts.tv_nsec < 0)
211211
return -EINVAL;
212212

213-
new_ts.tv_sec = user_tv.tv_sec;
214-
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
213+
new_ts.tv_nsec *= NSEC_PER_USEC;
215214
}
216215
if (tz) {
217216
if (copy_from_user(&new_tz, tz, sizeof(*tz)))
@@ -245,18 +244,17 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, struct old_timeval32 __user *, tv,
245244
struct timezone __user *, tz)
246245
{
247246
struct timespec64 new_ts;
248-
struct timeval user_tv;
249247
struct timezone new_tz;
250248

251249
if (tv) {
252-
if (compat_get_timeval(&user_tv, tv))
250+
if (get_user(new_ts.tv_sec, &tv->tv_sec) ||
251+
get_user(new_ts.tv_nsec, &tv->tv_usec))
253252
return -EFAULT;
254253

255-
if (!timeval_valid(&user_tv))
254+
if (new_ts.tv_nsec > USEC_PER_SEC || new_ts.tv_nsec < 0)
256255
return -EINVAL;
257256

258-
new_ts.tv_sec = user_tv.tv_sec;
259-
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
257+
new_ts.tv_nsec *= NSEC_PER_USEC;
260258
}
261259
if (tz) {
262260
if (copy_from_user(&new_tz, tz, sizeof(*tz)))

0 commit comments

Comments
 (0)