time/alarmtimer: Add bounds checking for the timer interval and expiration
PATCH 1/1 time/alarmtimer: Add bounds checking for the timer interval and expiration
Running the syzkaller timer_hang_poc.c
(https://groups.google.com/forum/#!topic/syzkaller/355tWdc8oHY) causes a kernel hang by passing in a time that results in the timer being started with an expiration that exceeds KTIME_MAX.
Check for overflow values of expiration (exp) and interval.
Also cleanup the code. Set and check the values, and then modify the timer.
--- kernel/time/alarmtimer.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
kernel/time/alarmtimer.c +13 -7
@@ -643,7 +643,7 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,struct itimerspec64 *new_setting, struct itimerspec64 *old_setting) { - ktime_t exp; + ktime_t exp, interval;if (!rtcdev)return -ENOTSUPP ;
@@ -654,12 +654,6 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,if (old_setting)alarm_timer_get (timr, old_setting); -/* If the timer was already set, cancel it */ -if (alarm_try_to_cancel (&timr->it.alarm.alarmtimer) <0 ) -return TIMER_RETRY ; - -/* start the timer */ - timr->it.alarm.interval =timespec64_to_ktime (new_setting->it_interval); exp =timespec64_to_ktime (new_setting->it_value);/* Convert (if necessary) to absolute time */ if (flags !=TIMER_ABSTIME ) {
@@ -668,7 +662,19 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime (); exp =ktime_add (now, exp); } +if (exp <0 ) + exp =KTIME_MAX ; + interval =timespec64_to_ktime (new_setting->it_interval); +if (interval <0 ) + interval =KTIME_MAX ; + +/* If the timer was already set, cancel it */ +if (alarm_try_to_cancel (&timr->it.alarm.alarmtimer) <0 ) +return TIMER_RETRY ; + +/* start the timer */ + timr->it.alarm.interval = interval;alarm_start (&timr->it.alarm.alarmtimer, exp);return 0 ; }
Signature · 1 line
1.7.9.3
Quoted 9 lines · Prarit Bhargava
Running the syzkaller
timer_hang_poc.c
(https://groups.google.com/forum/#!topic/syzkaller/355tWdc8oHY) causes a kernel hang by passing in a time that results in the timer being started with an expiration that exceedsKTIME_MAX.Check for overflow values of expiration (exp) and interval.
Also cleanup the code. Set and check the values, and then modify the timer.
This is already addressed in
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/urgent
I just did not come around to send it to Linus last week.
Thanks,
tglx