Re: [PATCH] kernel: mark all struct k_clock instances const

From: Thomas Gleixner
Date: Mon May 22 2017 - 18:17:50 EST


On Mon, 15 May 2017, Christoph Hellwig wrote:

> And keep a pointer to it instead of a copy in the posix_clocks array.
>
> Based on similar changes in the Grsecurity patchset, but redone from
> scratch including a few tweaks.

Hmm, that adds another level of indirection, but yes, we can do it.

> diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
> index 0e7fcb04f01e..e501403dd860 100644
> --- a/drivers/char/mmtimer.c
> +++ b/drivers/char/mmtimer.c
> @@ -53,7 +53,7 @@ MODULE_LICENSE("GPL");
>
> #define RTC_BITS 55 /* 55 bits for this implementation */
>
> -static struct k_clock sgi_clock;
> +static const struct k_clock sgi_clock;

Bah. This mmtimer which is used by 3 people in the world requires that we
keep the register_clock() function around after init and even export it.

In fact it makes no sense at all to keep that register function around with
your changes. The patch below makes all of this const in the !MMTIMER
case. If MMTIMER is enabled the thing is equaly secure as now.

Thanks,

tglx
8<-----------------
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -53,7 +53,7 @@ MODULE_LICENSE("GPL");

#define RTC_BITS 55 /* 55 bits for this implementation */

-static struct k_clock sgi_clock;
+static const struct k_clock sgi_clock;

extern unsigned long sn_rtc_cycles_per_second;

@@ -772,7 +772,7 @@ static int sgi_clock_getres(const clocki
return 0;
}

-static struct k_clock sgi_clock = {
+static const struct k_clock sgi_clock = {
.clock_set = sgi_clock_set,
.clock_get = sgi_clock_get,
.clock_getres = sgi_clock_getres,
@@ -840,7 +840,7 @@ static int __init mmtimer_init(void)
}

sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second;
- posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock);
+ posix_clocks[CLOCK_SGI_CYCLE] = &sgi_clock;

printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
sn_rtc_cycles_per_second/(unsigned long)1E6);
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -105,10 +105,15 @@ struct k_clock {
struct itimerspec64 *cur_setting);
};

-extern struct k_clock clock_posix_cpu;
-extern struct k_clock clock_posix_dynamic;
+extern const struct k_clock clock_posix_cpu;
+extern const struct k_clock clock_posix_dynamic;
+extern const struct k_clock clock_process;
+extern const struct k_clock clock_thread;
+extern const struct k_clock alarm_clock;

-void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock);
+#ifdef CONFIG_MMTIMER
+extern const struct k_clock *posix_clocks[MAX_CLOCKS];
+#endif

/* function to call to trigger timer event */
int posix_timer_event(struct k_itimer *timr, int si_private);
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -860,6 +860,18 @@ static struct platform_driver alarmtimer
}
};

+#ifdef CONFIG_POSIX_TIMERS
+const struct k_clock alarm_clock = {
+ .clock_getres = alarm_clock_getres,
+ .clock_get = alarm_clock_get,
+ .timer_create = alarm_timer_create,
+ .timer_set = alarm_timer_set,
+ .timer_del = alarm_timer_del,
+ .timer_get = alarm_timer_get,
+ .nsleep = alarm_timer_nsleep,
+};
+#endif
+
/**
* alarmtimer_init - Initialize alarm timer code
*
@@ -871,23 +883,9 @@ static int __init alarmtimer_init(void)
struct platform_device *pdev;
int error = 0;
int i;
- struct k_clock alarm_clock = {
- .clock_getres = alarm_clock_getres,
- .clock_get = alarm_clock_get,
- .timer_create = alarm_timer_create,
- .timer_set = alarm_timer_set,
- .timer_del = alarm_timer_del,
- .timer_get = alarm_timer_get,
- .nsleep = alarm_timer_nsleep,
- };

alarmtimer_rtc_timer_init();

- if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
- posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
- posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
- }
-
/* Initialize alarm bases */
alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real;
--- a/kernel/time/posix-clock.c
+++ b/kernel/time/posix-clock.c
@@ -434,7 +434,7 @@ static int pc_timer_settime(struct k_iti
return err;
}

-struct k_clock clock_posix_dynamic = {
+const struct k_clock clock_posix_dynamic = {
.clock_getres = pc_clock_getres,
.clock_set = pc_clock_settime,
.clock_get = pc_clock_gettime,
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1413,7 +1413,7 @@ static int thread_cpu_timer_create(struc
return posix_cpu_timer_create(timer);
}

-struct k_clock clock_posix_cpu = {
+const struct k_clock clock_posix_cpu = {
.clock_getres = posix_cpu_clock_getres,
.clock_set = posix_cpu_clock_set,
.clock_get = posix_cpu_clock_get,
@@ -1425,24 +1425,16 @@ struct k_clock clock_posix_cpu = {
.timer_get = posix_cpu_timer_get,
};

-static __init int init_posix_cpu_timers(void)
-{
- struct k_clock process = {
- .clock_getres = process_cpu_clock_getres,
- .clock_get = process_cpu_clock_get,
- .timer_create = process_cpu_timer_create,
- .nsleep = process_cpu_nsleep,
- .nsleep_restart = process_cpu_nsleep_restart,
- };
- struct k_clock thread = {
- .clock_getres = thread_cpu_clock_getres,
- .clock_get = thread_cpu_clock_get,
- .timer_create = thread_cpu_timer_create,
- };
-
- posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
- posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+const struct k_clock clock_process = {
+ .clock_getres = process_cpu_clock_getres,
+ .clock_get = process_cpu_clock_get,
+ .timer_create = process_cpu_timer_create,
+ .nsleep = process_cpu_nsleep,
+ .nsleep_restart = process_cpu_nsleep_restart,
+};

- return 0;
-}
-__initcall(init_posix_cpu_timers);
+const struct k_clock clock_thread = {
+ .clock_getres = thread_cpu_clock_getres,
+ .clock_get = thread_cpu_clock_get,
+ .timer_create = thread_cpu_timer_create,
+};
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -125,7 +125,32 @@ static DEFINE_SPINLOCK(hash_lock);
* which we beg off on and pass to do_sys_settimeofday().
*/

-static struct k_clock posix_clocks[MAX_CLOCKS];
+static const struct k_clock clock_realtime;
+static const struct k_clock clock_monotonic;
+static const struct k_clock clock_monotonic_raw;
+static const struct k_clock clock_realtime_coarse;
+static const struct k_clock clock_monotonic_coarse;
+static const struct k_clock clock_tai;
+static const struct k_clock clock_boottime;
+
+#ifndef CONFIG_MMTIMER
+static const struct k_clock * const posix_clocks[MAX_CLOCKS] = {
+#else
+EXPORT_SYMBOL_GPL(posix_clocks);
+const struct k_clock * const posix_clocks[MAX_CLOCKS] = {
+#endif
+ [CLOCK_REALTIME] = &clock_realtime,
+ [CLOCK_MONOTONIC] = &clock_monotonic,
+ [CLOCK_PROCESS_CPUTIME_ID] = &clock_process,
+ [CLOCK_THREAD_CPUTIME_ID] = &clock_thread,
+ [CLOCK_MONOTONIC_RAW] = &clock_monotonic_raw,
+ [CLOCK_REALTIME_COARSE] = &clock_realtime_coarse,
+ [CLOCK_MONOTONIC_COARSE] = &clock_monotonic_coarse,
+ [CLOCK_BOOTTIME] = &clock_boottime,
+ [CLOCK_REALTIME_ALARM] = &alarm_clock,
+ [CLOCK_BOOTTIME_ALARM] = &alarm_clock,
+ [CLOCK_TAI] = &clock_tai,
+};

/*
* These ones are defined below.
@@ -280,74 +305,72 @@ static int posix_get_hrtimer_res(clockid
return 0;
}

+static const struct k_clock clock_realtime = {
+ .clock_getres = posix_get_hrtimer_res,
+ .clock_get = posix_clock_realtime_get,
+ .clock_set = posix_clock_realtime_set,
+ .clock_adj = posix_clock_realtime_adj,
+ .nsleep = common_nsleep,
+ .nsleep_restart = hrtimer_nanosleep_restart,
+ .timer_create = common_timer_create,
+ .timer_set = common_timer_set,
+ .timer_get = common_timer_get,
+ .timer_del = common_timer_del,
+};
+
+static const struct k_clock clock_monotonic = {
+ .clock_getres = posix_get_hrtimer_res,
+ .clock_get = posix_ktime_get_ts,
+ .nsleep = common_nsleep,
+ .nsleep_restart = hrtimer_nanosleep_restart,
+ .timer_create = common_timer_create,
+ .timer_set = common_timer_set,
+ .timer_get = common_timer_get,
+ .timer_del = common_timer_del,
+};
+
+static const struct k_clock clock_monotonic_raw = {
+ .clock_getres = posix_get_hrtimer_res,
+ .clock_get = posix_get_monotonic_raw,
+};
+
+static const struct k_clock clock_realtime_coarse = {
+ .clock_getres = posix_get_coarse_res,
+ .clock_get = posix_get_realtime_coarse,
+};
+
+static const struct k_clock clock_monotonic_coarse = {
+ .clock_getres = posix_get_coarse_res,
+ .clock_get = posix_get_monotonic_coarse,
+};
+
+static const struct k_clock clock_tai = {
+ .clock_getres = posix_get_hrtimer_res,
+ .clock_get = posix_get_tai,
+ .nsleep = common_nsleep,
+ .nsleep_restart = hrtimer_nanosleep_restart,
+ .timer_create = common_timer_create,
+ .timer_set = common_timer_set,
+ .timer_get = common_timer_get,
+ .timer_del = common_timer_del,
+};
+
+static const struct k_clock clock_boottime = {
+ .clock_getres = posix_get_hrtimer_res,
+ .clock_get = posix_get_boottime,
+ .nsleep = common_nsleep,
+ .nsleep_restart = hrtimer_nanosleep_restart,
+ .timer_create = common_timer_create,
+ .timer_set = common_timer_set,
+ .timer_get = common_timer_get,
+ .timer_del = common_timer_del,
+};
+
/*
* Initialize everything, well, just everything in Posix clocks/timers ;)
*/
static __init int init_posix_timers(void)
{
- struct k_clock clock_realtime = {
- .clock_getres = posix_get_hrtimer_res,
- .clock_get = posix_clock_realtime_get,
- .clock_set = posix_clock_realtime_set,
- .clock_adj = posix_clock_realtime_adj,
- .nsleep = common_nsleep,
- .nsleep_restart = hrtimer_nanosleep_restart,
- .timer_create = common_timer_create,
- .timer_set = common_timer_set,
- .timer_get = common_timer_get,
- .timer_del = common_timer_del,
- };
- struct k_clock clock_monotonic = {
- .clock_getres = posix_get_hrtimer_res,
- .clock_get = posix_ktime_get_ts,
- .nsleep = common_nsleep,
- .nsleep_restart = hrtimer_nanosleep_restart,
- .timer_create = common_timer_create,
- .timer_set = common_timer_set,
- .timer_get = common_timer_get,
- .timer_del = common_timer_del,
- };
- struct k_clock clock_monotonic_raw = {
- .clock_getres = posix_get_hrtimer_res,
- .clock_get = posix_get_monotonic_raw,
- };
- struct k_clock clock_realtime_coarse = {
- .clock_getres = posix_get_coarse_res,
- .clock_get = posix_get_realtime_coarse,
- };
- struct k_clock clock_monotonic_coarse = {
- .clock_getres = posix_get_coarse_res,
- .clock_get = posix_get_monotonic_coarse,
- };
- struct k_clock clock_tai = {
- .clock_getres = posix_get_hrtimer_res,
- .clock_get = posix_get_tai,
- .nsleep = common_nsleep,
- .nsleep_restart = hrtimer_nanosleep_restart,
- .timer_create = common_timer_create,
- .timer_set = common_timer_set,
- .timer_get = common_timer_get,
- .timer_del = common_timer_del,
- };
- struct k_clock clock_boottime = {
- .clock_getres = posix_get_hrtimer_res,
- .clock_get = posix_get_boottime,
- .nsleep = common_nsleep,
- .nsleep_restart = hrtimer_nanosleep_restart,
- .timer_create = common_timer_create,
- .timer_set = common_timer_set,
- .timer_get = common_timer_get,
- .timer_del = common_timer_del,
- };
-
- posix_timers_register_clock(CLOCK_REALTIME, &clock_realtime);
- posix_timers_register_clock(CLOCK_MONOTONIC, &clock_monotonic);
- posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);
- posix_timers_register_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse);
- posix_timers_register_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse);
- posix_timers_register_clock(CLOCK_BOOTTIME, &clock_boottime);
- posix_timers_register_clock(CLOCK_TAI, &clock_tai);
-
posix_timers_cache = kmem_cache_create("posix_timers_cache",
sizeof (struct k_itimer), 0, SLAB_PANIC,
NULL);
@@ -521,30 +544,6 @@ static struct pid *good_sigevent(sigeven
return task_pid(rtn);
}

-void posix_timers_register_clock(const clockid_t clock_id,
- struct k_clock *new_clock)
-{
- if ((unsigned) clock_id >= MAX_CLOCKS) {
- printk(KERN_WARNING "POSIX clock register failed for clock_id %d\n",
- clock_id);
- return;
- }
-
- if (!new_clock->clock_get) {
- printk(KERN_WARNING "POSIX clock id %d lacks clock_get()\n",
- clock_id);
- return;
- }
- if (!new_clock->clock_getres) {
- printk(KERN_WARNING "POSIX clock id %d lacks clock_getres()\n",
- clock_id);
- return;
- }
-
- posix_clocks[clock_id] = *new_clock;
-}
-EXPORT_SYMBOL_GPL(posix_timers_register_clock);
-
static struct k_itimer * alloc_posix_timer(void)
{
struct k_itimer *tmr;
@@ -581,15 +580,16 @@ static void release_posix_timer(struct k
call_rcu(&tmr->it.rcu, k_itimer_rcu_free);
}

-static struct k_clock *clockid_to_kclock(const clockid_t id)
+static const struct k_clock *clockid_to_kclock(const clockid_t id)
{
if (id < 0)
return (id & CLOCKFD_MASK) == CLOCKFD ?
&clock_posix_dynamic : &clock_posix_cpu;

- if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres)
+ if (id >= MAX_CLOCKS || !posix_clocks[id] ||
+ !posix_clocks[id]->clock_getres)
return NULL;
- return &posix_clocks[id];
+ return posix_clocks[id];
}

static int common_timer_create(struct k_itimer *new_timer)
@@ -604,7 +604,7 @@ SYSCALL_DEFINE3(timer_create, const cloc
struct sigevent __user *, timer_event_spec,
timer_t __user *, created_timer_id)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct k_itimer *new_timer;
int error, new_timer_id;
sigevent_t event;
@@ -781,7 +781,7 @@ SYSCALL_DEFINE2(timer_gettime, timer_t,
struct itimerspec64 cur_setting64;
struct itimerspec cur_setting;
struct k_itimer *timr;
- struct k_clock *kc;
+ const struct k_clock *kc;
unsigned long flags;
int ret = 0;

@@ -890,7 +890,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t,
struct itimerspec new_spec, old_spec;
struct k_itimer *timr;
unsigned long flag;
- struct k_clock *kc;
+ const struct k_clock *kc;
int error = 0;

if (!new_setting)
@@ -939,7 +939,7 @@ static int common_timer_del(struct k_iti

static inline int timer_delete_hook(struct k_itimer *timer)
{
- struct k_clock *kc = clockid_to_kclock(timer->it_clock);
+ const struct k_clock *kc = clockid_to_kclock(timer->it_clock);

if (WARN_ON_ONCE(!kc || !kc->timer_del))
return -EINVAL;
@@ -1018,7 +1018,7 @@ void exit_itimers(struct signal_struct *
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
const struct timespec __user *, tp)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 new_tp64;
struct timespec new_tp;

@@ -1035,7 +1035,7 @@ SYSCALL_DEFINE2(clock_settime, const clo
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
struct timespec __user *,tp)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 kernel_tp64;
struct timespec kernel_tp;
int error;
@@ -1055,7 +1055,7 @@ SYSCALL_DEFINE2(clock_gettime, const clo
SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
struct timex __user *, utx)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timex ktx;
int err;

@@ -1078,7 +1078,7 @@ SYSCALL_DEFINE2(clock_adjtime, const clo
SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
struct timespec __user *, tp)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 rtn_tp64;
struct timespec rtn_tp;
int error;
@@ -1110,7 +1110,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const c
const struct timespec __user *, rqtp,
struct timespec __user *, rmtp)
{
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 t64;
struct timespec t;

@@ -1136,7 +1136,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const c
long clock_nanosleep_restart(struct restart_block *restart_block)
{
clockid_t which_clock = restart_block->nanosleep.clockid;
- struct k_clock *kc = clockid_to_kclock(which_clock);
+ const struct k_clock *kc = clockid_to_kclock(which_clock);

if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
return -EINVAL;