Skip to content

Commit bd40a17

Browse files
committed
y2038: itimer: change implementation to timespec64
There is no 64-bit version of getitimer/setitimer since that is not actually needed. However, the implementation is built around the deprecated 'struct timeval' type. Change the code to use timespec64 internally to reduce the dependencies on timeval and associated helper functions. Minor adjustments in the code are needed to make the native and compat version work the same way, and to keep the range check working after the conversion. Signed-off-by: Arnd Bergmann <[email protected]>
1 parent ddbc7d0 commit bd40a17

File tree

2 files changed

+104
-70
lines changed

2 files changed

+104
-70
lines changed

include/trace/events/timer.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ DEFINE_EVENT(hrtimer_class, hrtimer_cancel,
303303
*/
304304
TRACE_EVENT(itimer_state,
305305

306-
TP_PROTO(int which, const struct itimerval *const value,
306+
TP_PROTO(int which, const struct itimerspec64 *const value,
307307
unsigned long long expires),
308308

309309
TP_ARGS(which, value, expires),
@@ -312,24 +312,24 @@ TRACE_EVENT(itimer_state,
312312
__field( int, which )
313313
__field( unsigned long long, expires )
314314
__field( long, value_sec )
315-
__field( long, value_usec )
315+
__field( long, value_nsec )
316316
__field( long, interval_sec )
317-
__field( long, interval_usec )
317+
__field( long, interval_nsec )
318318
),
319319

320320
TP_fast_assign(
321321
__entry->which = which;
322322
__entry->expires = expires;
323323
__entry->value_sec = value->it_value.tv_sec;
324-
__entry->value_usec = value->it_value.tv_usec;
324+
__entry->value_nsec = value->it_value.tv_nsec;
325325
__entry->interval_sec = value->it_interval.tv_sec;
326-
__entry->interval_usec = value->it_interval.tv_usec;
326+
__entry->interval_nsec = value->it_interval.tv_nsec;
327327
),
328328

329-
TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld",
329+
TP_printk("which=%d expires=%llu it_value=%ld.%06ld it_interval=%ld.%06ld",
330330
__entry->which, __entry->expires,
331-
__entry->value_sec, __entry->value_usec,
332-
__entry->interval_sec, __entry->interval_usec)
331+
__entry->value_sec, __entry->value_nsec / NSEC_PER_USEC,
332+
__entry->interval_sec, __entry->interval_nsec / NSEC_PER_USEC)
333333
);
334334

335335
/**

kernel/time/itimer.c

Lines changed: 96 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* Returns the delta between the expiry time and now, which can be
2727
* less than zero or 1usec for an pending expired timer
2828
*/
29-
static struct timeval itimer_get_remtime(struct hrtimer *timer)
29+
static struct timespec64 itimer_get_remtime(struct hrtimer *timer)
3030
{
3131
ktime_t rem = __hrtimer_get_remaining(timer, true);
3232

@@ -41,11 +41,11 @@ static struct timeval itimer_get_remtime(struct hrtimer *timer)
4141
} else
4242
rem = 0;
4343

44-
return ktime_to_timeval(rem);
44+
return ktime_to_timespec64(rem);
4545
}
4646

4747
static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
48-
struct itimerval *const value)
48+
struct itimerspec64 *const value)
4949
{
5050
u64 val, interval;
5151
struct cpu_itimer *it = &tsk->signal->it[clock_id];
@@ -69,11 +69,11 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
6969

7070
spin_unlock_irq(&tsk->sighand->siglock);
7171

72-
value->it_value = ns_to_timeval(val);
73-
value->it_interval = ns_to_timeval(interval);
72+
value->it_value = ns_to_timespec64(val);
73+
value->it_interval = ns_to_timespec64(interval);
7474
}
7575

76-
static int do_getitimer(int which, struct itimerval *value)
76+
static int do_getitimer(int which, struct itimerspec64 *value)
7777
{
7878
struct task_struct *tsk = current;
7979

@@ -82,7 +82,7 @@ static int do_getitimer(int which, struct itimerval *value)
8282
spin_lock_irq(&tsk->sighand->siglock);
8383
value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
8484
value->it_interval =
85-
ktime_to_timeval(tsk->signal->it_real_incr);
85+
ktime_to_timespec64(tsk->signal->it_real_incr);
8686
spin_unlock_irq(&tsk->sighand->siglock);
8787
break;
8888
case ITIMER_VIRTUAL:
@@ -97,17 +97,26 @@ static int do_getitimer(int which, struct itimerval *value)
9797
return 0;
9898
}
9999

100+
static int put_itimerval(struct itimerval __user *o,
101+
const struct itimerspec64 *i)
102+
{
103+
struct itimerval v;
104+
105+
v.it_interval.tv_sec = i->it_interval.tv_sec;
106+
v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;
107+
v.it_value.tv_sec = i->it_value.tv_sec;
108+
v.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;
109+
return copy_to_user(o, &v, sizeof(struct itimerval)) ? -EFAULT : 0;
110+
}
111+
112+
100113
SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value)
101114
{
102-
int error = -EFAULT;
103-
struct itimerval get_buffer;
115+
struct itimerspec64 get_buffer;
116+
int error = do_getitimer(which, &get_buffer);
104117

105-
if (value) {
106-
error = do_getitimer(which, &get_buffer);
107-
if (!error &&
108-
copy_to_user(value, &get_buffer, sizeof(get_buffer)))
109-
error = -EFAULT;
110-
}
118+
if (!error && put_itimerval(value, &get_buffer))
119+
error = -EFAULT;
111120
return error;
112121
}
113122

@@ -117,24 +126,25 @@ struct old_itimerval32 {
117126
struct old_timeval32 it_value;
118127
};
119128

120-
static int put_old_itimerval32(struct old_itimerval32 __user *o, const struct itimerval *i)
129+
static int put_old_itimerval32(struct old_itimerval32 __user *o,
130+
const struct itimerspec64 *i)
121131
{
122132
struct old_itimerval32 v32;
123133

124134
v32.it_interval.tv_sec = i->it_interval.tv_sec;
125-
v32.it_interval.tv_usec = i->it_interval.tv_usec;
135+
v32.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC;
126136
v32.it_value.tv_sec = i->it_value.tv_sec;
127-
v32.it_value.tv_usec = i->it_value.tv_usec;
137+
v32.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC;
128138
return copy_to_user(o, &v32, sizeof(struct old_itimerval32)) ? -EFAULT : 0;
129139
}
130140

131141
COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
132-
struct old_itimerval32 __user *, it)
142+
struct old_itimerval32 __user *, value)
133143
{
134-
struct itimerval kit;
135-
int error = do_getitimer(which, &kit);
144+
struct itimerspec64 get_buffer;
145+
int error = do_getitimer(which, &get_buffer);
136146

137-
if (!error && put_old_itimerval32(it, &kit))
147+
if (!error && put_old_itimerval32(value, &get_buffer))
138148
error = -EFAULT;
139149
return error;
140150
}
@@ -156,8 +166,8 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
156166
}
157167

158168
static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
159-
const struct itimerval *const value,
160-
struct itimerval *const ovalue)
169+
const struct itimerspec64 *const value,
170+
struct itimerspec64 *const ovalue)
161171
{
162172
u64 oval, nval, ointerval, ninterval;
163173
struct cpu_itimer *it = &tsk->signal->it[clock_id];
@@ -166,8 +176,8 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
166176
* Use the to_ktime conversion because that clamps the maximum
167177
* value to KTIME_MAX and avoid multiplication overflows.
168178
*/
169-
nval = ktime_to_ns(timeval_to_ktime(value->it_value));
170-
ninterval = ktime_to_ns(timeval_to_ktime(value->it_interval));
179+
nval = timespec64_to_ns(&value->it_value);
180+
ninterval = timespec64_to_ns(&value->it_interval);
171181

172182
spin_lock_irq(&tsk->sighand->siglock);
173183

@@ -186,8 +196,8 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
186196
spin_unlock_irq(&tsk->sighand->siglock);
187197

188198
if (ovalue) {
189-
ovalue->it_value = ns_to_timeval(oval);
190-
ovalue->it_interval = ns_to_timeval(ointerval);
199+
ovalue->it_value = ns_to_timespec64(oval);
200+
ovalue->it_interval = ns_to_timespec64(ointerval);
191201
}
192202
}
193203

@@ -197,19 +207,13 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
197207
#define timeval_valid(t) \
198208
(((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
199209

200-
static int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
210+
static int do_setitimer(int which, struct itimerspec64 *value,
211+
struct itimerspec64 *ovalue)
201212
{
202213
struct task_struct *tsk = current;
203214
struct hrtimer *timer;
204215
ktime_t expires;
205216

206-
/*
207-
* Validate the timevals in value.
208-
*/
209-
if (!timeval_valid(&value->it_value) ||
210-
!timeval_valid(&value->it_interval))
211-
return -EINVAL;
212-
213217
switch (which) {
214218
case ITIMER_REAL:
215219
again:
@@ -218,18 +222,18 @@ static int do_setitimer(int which, struct itimerval *value, struct itimerval *ov
218222
if (ovalue) {
219223
ovalue->it_value = itimer_get_remtime(timer);
220224
ovalue->it_interval
221-
= ktime_to_timeval(tsk->signal->it_real_incr);
225+
= ktime_to_timespec64(tsk->signal->it_real_incr);
222226
}
223227
/* We are sharing ->siglock with it_real_fn() */
224228
if (hrtimer_try_to_cancel(timer) < 0) {
225229
spin_unlock_irq(&tsk->sighand->siglock);
226230
hrtimer_cancel_wait_running(timer);
227231
goto again;
228232
}
229-
expires = timeval_to_ktime(value->it_value);
233+
expires = timespec64_to_ktime(value->it_value);
230234
if (expires != 0) {
231235
tsk->signal->it_real_incr =
232-
timeval_to_ktime(value->it_interval);
236+
timespec64_to_ktime(value->it_interval);
233237
hrtimer_start(timer, expires, HRTIMER_MODE_REL);
234238
} else
235239
tsk->signal->it_real_incr = 0;
@@ -252,7 +256,7 @@ static int do_setitimer(int which, struct itimerval *value, struct itimerval *ov
252256
#ifdef CONFIG_SECURITY_SELINUX
253257
void clear_itimer(void)
254258
{
255-
struct itimerval v = {};
259+
struct itimerspec64 v = {};
256260
int i;
257261

258262
for (i = 0; i < 3; i++)
@@ -276,24 +280,24 @@ void clear_itimer(void)
276280
*/
277281
static unsigned int alarm_setitimer(unsigned int seconds)
278282
{
279-
struct itimerval it_new, it_old;
283+
struct itimerspec64 it_new, it_old;
280284

281285
#if BITS_PER_LONG < 64
282286
if (seconds > INT_MAX)
283287
seconds = INT_MAX;
284288
#endif
285289
it_new.it_value.tv_sec = seconds;
286-
it_new.it_value.tv_usec = 0;
287-
it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
290+
it_new.it_value.tv_nsec = 0;
291+
it_new.it_interval.tv_sec = it_new.it_interval.tv_nsec = 0;
288292

289293
do_setitimer(ITIMER_REAL, &it_new, &it_old);
290294

291295
/*
292296
* We can't return 0 if we have an alarm pending ... And we'd
293297
* better return too much than too little anyway
294298
*/
295-
if ((!it_old.it_value.tv_sec && it_old.it_value.tv_usec) ||
296-
it_old.it_value.tv_usec >= 500000)
299+
if ((!it_old.it_value.tv_sec && it_old.it_value.tv_nsec) ||
300+
it_old.it_value.tv_nsec >= 500000)
297301
it_old.it_value.tv_sec++;
298302

299303
return it_old.it_value.tv_sec;
@@ -310,15 +314,35 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds)
310314

311315
#endif
312316

317+
static int get_itimerval(struct itimerspec64 *o, const struct itimerval __user *i)
318+
{
319+
struct itimerval v;
320+
321+
if (copy_from_user(&v, i, sizeof(struct itimerval)))
322+
return -EFAULT;
323+
324+
/* Validate the timevals in value. */
325+
if (!timeval_valid(&v.it_value) ||
326+
!timeval_valid(&v.it_interval))
327+
return -EINVAL;
328+
329+
o->it_interval.tv_sec = v.it_interval.tv_sec;
330+
o->it_interval.tv_nsec = v.it_interval.tv_usec * NSEC_PER_USEC;
331+
o->it_value.tv_sec = v.it_value.tv_sec;
332+
o->it_value.tv_nsec = v.it_value.tv_usec * NSEC_PER_USEC;
333+
return 0;
334+
}
335+
313336
SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
314337
struct itimerval __user *, ovalue)
315338
{
316-
struct itimerval set_buffer, get_buffer;
339+
struct itimerspec64 set_buffer, get_buffer;
317340
int error;
318341

319342
if (value) {
320-
if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
321-
return -EFAULT;
343+
error = get_itimerval(&set_buffer, value);
344+
if (error)
345+
return error;
322346
} else {
323347
memset(&set_buffer, 0, sizeof(set_buffer));
324348
printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
@@ -330,43 +354,53 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
330354
if (error || !ovalue)
331355
return error;
332356

333-
if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
357+
if (put_itimerval(ovalue, &get_buffer))
334358
return -EFAULT;
335359
return 0;
336360
}
337361

338362
#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)
339-
static int get_old_itimerval32(struct itimerval *o, const struct old_itimerval32 __user *i)
363+
static int get_old_itimerval32(struct itimerspec64 *o, const struct old_itimerval32 __user *i)
340364
{
341365
struct old_itimerval32 v32;
342366

343367
if (copy_from_user(&v32, i, sizeof(struct old_itimerval32)))
344368
return -EFAULT;
369+
370+
/* Validate the timevals in value. */
371+
if (!timeval_valid(&v32.it_value) ||
372+
!timeval_valid(&v32.it_interval))
373+
return -EINVAL;
374+
345375
o->it_interval.tv_sec = v32.it_interval.tv_sec;
346-
o->it_interval.tv_usec = v32.it_interval.tv_usec;
376+
o->it_interval.tv_nsec = v32.it_interval.tv_usec * NSEC_PER_USEC;
347377
o->it_value.tv_sec = v32.it_value.tv_sec;
348-
o->it_value.tv_usec = v32.it_value.tv_usec;
378+
o->it_value.tv_nsec = v32.it_value.tv_usec * NSEC_PER_USEC;
349379
return 0;
350380
}
351381

352382
COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
353-
struct old_itimerval32 __user *, in,
354-
struct old_itimerval32 __user *, out)
383+
struct old_itimerval32 __user *, value,
384+
struct old_itimerval32 __user *, ovalue)
355385
{
356-
struct itimerval kin, kout;
386+
struct itimerspec64 set_buffer, get_buffer;
357387
int error;
358388

359-
if (in) {
360-
if (get_old_itimerval32(&kin, in))
361-
return -EFAULT;
389+
if (value) {
390+
error = get_old_itimerval32(&set_buffer, value);
391+
if (error)
392+
return error;
362393
} else {
363-
memset(&kin, 0, sizeof(kin));
394+
memset(&set_buffer, 0, sizeof(set_buffer));
395+
printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
396+
" Misfeature support will be removed\n",
397+
current->comm);
364398
}
365399

366-
error = do_setitimer(which, &kin, out ? &kout : NULL);
367-
if (error || !out)
400+
error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
401+
if (error || !ovalue)
368402
return error;
369-
if (put_old_itimerval32(out, &kout))
403+
if (put_old_itimerval32(ovalue, &get_buffer))
370404
return -EFAULT;
371405
return 0;
372406
}

0 commit comments

Comments
 (0)