Skip to content

Commit 3f68535

Browse files
john stultzKAGA-KOKO
authored andcommitted
clocksource: sanity check sysfs clocksource changes
Thomas, Andrew and Ingo pointed out that we don't have any safety checks in the clocksource sysfs entries to make sure sysadmins don't try to change the clocksource to a non high-res timer capable clocksource (such as jiffies) when high-res timers (HRT) is enabled. Doing so will likely hang a system. Correct this by filtering non HRT clocksources from available_clocksources and not accepting non HRT clocksources with HRT enabled. Signed-off-by: John Stultz <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 7d27558 commit 3f68535

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

include/linux/hrtimer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
305305

306306
extern ktime_t ktime_get(void);
307307
extern ktime_t ktime_get_real(void);
308-
308+
extern int hrtimer_hres_active(void);
309309

310310
DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
311311

kernel/hrtimer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ static inline int hrtimer_is_hres_enabled(void)
476476
/*
477477
* Is the high resolution mode active ?
478478
*/
479-
static inline int hrtimer_hres_active(void)
479+
int hrtimer_hres_active(void)
480480
{
481481
return __get_cpu_var(hrtimer_bases).hres_active;
482482
}
@@ -704,7 +704,7 @@ static int hrtimer_switch_to_hres(void)
704704

705705
#else
706706

707-
static inline int hrtimer_hres_active(void) { return 0; }
707+
int hrtimer_hres_active(void) { return 0; }
708708
static inline int hrtimer_is_hres_enabled(void) { return 0; }
709709
static inline int hrtimer_switch_to_hres(void) { return 0; }
710710
static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }

kernel/time/clocksource.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/module.h>
3131
#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
3232
#include <linux/tick.h>
33+
#include <linux/hrtimer.h>
3334

3435
void timecounter_init(struct timecounter *tc,
3536
const struct cyclecounter *cc,
@@ -509,6 +510,18 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
509510
}
510511
}
511512

513+
/*
514+
* Check to make sure we don't switch to a non-HRT usable
515+
* clocksource if HRT is enabled and running
516+
*/
517+
if (hrtimer_hres_active() &&
518+
!(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
519+
printk(KERN_WARNING "%s clocksource is not HRT compatible. "
520+
"Cannot switch while in HRT mode\n", ovr->name);
521+
ovr = NULL;
522+
override_name[0] = 0;
523+
}
524+
512525
/* Reselect, when the override name has changed */
513526
if (ovr != clocksource_override) {
514527
clocksource_override = ovr;
@@ -537,7 +550,10 @@ sysfs_show_available_clocksources(struct sys_device *dev,
537550

538551
spin_lock_irq(&clocksource_lock);
539552
list_for_each_entry(src, &clocksource_list, list) {
540-
count += snprintf(buf + count,
553+
/* Don't show non-HRES clocksource if HRES is enabled */
554+
if (!hrtimer_hres_active() ||
555+
(src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
556+
count += snprintf(buf + count,
541557
max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
542558
"%s ", src->name);
543559
}

0 commit comments

Comments
 (0)