Commit febee6d2 authored by John Stultz's avatar John Stultz Committed by Ben Hutchings

alarmtimer: Fix bug where relative alarm timers were treated as absolute

commit 16927776 upstream.

Sharvil noticed with the posix timer_settime interface, using the
CLOCK_REALTIME_ALARM or CLOCK_BOOTTIME_ALARM clockid, if the users
tried to specify a relative time timer, it would incorrectly be
treated as absolute regardless of the state of the flags argument.

This patch corrects this, properly checking the absolute/relative flag,
as well as adds further error checking that no invalid flag bits are set.
Reported-by: default avatarSharvil Nanavati <sharvil@google.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Sharvil Nanavati <sharvil@google.com>
Link: http://lkml.kernel.org/r/1404767171-6902-1-git-send-email-john.stultz@linaro.orgSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 831068ee
...@@ -563,9 +563,14 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, ...@@ -563,9 +563,14 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
struct itimerspec *new_setting, struct itimerspec *new_setting,
struct itimerspec *old_setting) struct itimerspec *old_setting)
{ {
ktime_t exp;
if (!rtcdev) if (!rtcdev)
return -ENOTSUPP; return -ENOTSUPP;
if (flags & ~TIMER_ABSTIME)
return -EINVAL;
if (old_setting) if (old_setting)
alarm_timer_get(timr, old_setting); alarm_timer_get(timr, old_setting);
...@@ -575,8 +580,16 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, ...@@ -575,8 +580,16 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
/* start the timer */ /* start the timer */
timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
alarm_start(&timr->it.alarm.alarmtimer, exp = timespec_to_ktime(new_setting->it_value);
timespec_to_ktime(new_setting->it_value)); /* Convert (if necessary) to absolute time */
if (flags != TIMER_ABSTIME) {
ktime_t now;
now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
exp = ktime_add(now, exp);
}
alarm_start(&timr->it.alarm.alarmtimer, exp);
return 0; return 0;
} }
...@@ -708,6 +721,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, ...@@ -708,6 +721,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
if (!alarmtimer_get_rtcdev()) if (!alarmtimer_get_rtcdev())
return -ENOTSUPP; return -ENOTSUPP;
if (flags & ~TIMER_ABSTIME)
return -EINVAL;
if (!capable(CAP_WAKE_ALARM)) if (!capable(CAP_WAKE_ALARM))
return -EPERM; return -EPERM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment