VYPR
Unrated severityNVD Advisory· Published Jun 3, 2026

CVE-2026-46257

CVE-2026-46257

Description

In the Linux kernel, the following vulnerability has been resolved:

clocksource/drivers/timer-sp804: Fix an Oops when read_current_timer is called on ARM32 platforms where the SP804 is not registered as the sched_clock.

On SP804, the delay timer shares the same clkevt instance with sched_clock. On some platforms, when sp804_clocksource_and_sched_clock_init is called with use_sched_clock not set to 1, sched_clkevt is not properly initialized. However, sp804_register_delay_timer is invoked unconditionally, and read_current_timer() subsequently calls sp804_read on an uninitialized sched_clkevt, leading to a kernel Oops when accessing sched_clkevt->value.

Declare a dedicated clkevt instance exclusively for delay timer, instead of sharing the same clkevt with sched_clock. This ensures that read_current_timer continues to work correctly regardless of whether SP804 is selected as the sched_clock.

Affected products

1

Patches

4
694921a93f3e

clocksource/drivers/timer-sp804: Fix an Oops when read_current_timer is called on ARM32 platforms where the SP804 is not registered as the sched_clock.

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitStephen Eta ZhouDec 25, 2025Fixed in 7.0via kernel-cna
1 file changed · +9 6
  • drivers/clocksource/timer-sp804.c+9 6 modified
    diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
    index e82a95ea47247..d698584273596 100644
    --- a/drivers/clocksource/timer-sp804.c
    +++ b/drivers/clocksource/timer-sp804.c
    @@ -106,21 +106,25 @@ static u64 notrace sp804_read(void)
     	return ~readl_relaxed(sched_clkevt->value);
     }
     
    +/* Register delay timer backed by the hardware counter */
     #ifdef CONFIG_ARM
     static struct delay_timer delay;
    +static struct sp804_clkevt *delay_clkevt;
    +
     static unsigned long sp804_read_delay_timer_read(void)
     {
    -	return sp804_read();
    +	return ~readl_relaxed(delay_clkevt->value);
     }
     
    -static void sp804_register_delay_timer(int freq)
    +static void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq)
     {
    +	delay_clkevt = clk;
     	delay.freq = freq;
     	delay.read_current_timer = sp804_read_delay_timer_read;
     	register_current_timer_delay(&delay);
     }
     #else
    -static inline void sp804_register_delay_timer(int freq) {}
    +static inline void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq) {}
     #endif
     
     static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
    @@ -135,8 +139,6 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	if (rate < 0)
     		return -EINVAL;
     
    -	sp804_register_delay_timer(rate);
    -
     	clkevt = sp804_clkevt_get(base);
     
     	writel(0, clkevt->ctrl);
    @@ -152,6 +154,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	clocksource_mmio_init(clkevt->value, name,
     		rate, 200, 32, clocksource_mmio_readl_down);
     
    +	sp804_register_delay_timer(clkevt, rate);
    +
     	if (use_sched_clock) {
     		sched_clkevt = clkevt;
     		sched_clock_register(sp804_read, 32, rate);
    -- 
    cgit 1.3-korg
    
    
    
693b0b594b0f

clocksource/drivers/timer-sp804: Fix an Oops when read_current_timer is called on ARM32 platforms where the SP804 is not registered as the sched_clock.

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitStephen Eta ZhouDec 25, 2025Fixed in 6.19.4via kernel-cna
1 file changed · +9 6
  • drivers/clocksource/timer-sp804.c+9 6 modified
    diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
    index e82a95ea47247..d698584273596 100644
    --- a/drivers/clocksource/timer-sp804.c
    +++ b/drivers/clocksource/timer-sp804.c
    @@ -106,21 +106,25 @@ static u64 notrace sp804_read(void)
     	return ~readl_relaxed(sched_clkevt->value);
     }
     
    +/* Register delay timer backed by the hardware counter */
     #ifdef CONFIG_ARM
     static struct delay_timer delay;
    +static struct sp804_clkevt *delay_clkevt;
    +
     static unsigned long sp804_read_delay_timer_read(void)
     {
    -	return sp804_read();
    +	return ~readl_relaxed(delay_clkevt->value);
     }
     
    -static void sp804_register_delay_timer(int freq)
    +static void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq)
     {
    +	delay_clkevt = clk;
     	delay.freq = freq;
     	delay.read_current_timer = sp804_read_delay_timer_read;
     	register_current_timer_delay(&delay);
     }
     #else
    -static inline void sp804_register_delay_timer(int freq) {}
    +static inline void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq) {}
     #endif
     
     static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
    @@ -135,8 +139,6 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	if (rate < 0)
     		return -EINVAL;
     
    -	sp804_register_delay_timer(rate);
    -
     	clkevt = sp804_clkevt_get(base);
     
     	writel(0, clkevt->ctrl);
    @@ -152,6 +154,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	clocksource_mmio_init(clkevt->value, name,
     		rate, 200, 32, clocksource_mmio_readl_down);
     
    +	sp804_register_delay_timer(clkevt, rate);
    +
     	if (use_sched_clock) {
     		sched_clkevt = clkevt;
     		sched_clock_register(sp804_read, 32, rate);
    -- 
    cgit 1.3-korg
    
    
    
693b0b594b0f

clocksource/drivers/timer-sp804: Fix an Oops when read_current_timer is called on ARM32 platforms where the SP804 is not registered as the sched_clock.

1 file changed · +9 6
  • drivers/clocksource/timer-sp804.c+9 6 modified
    diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
    index e82a95ea47247..d698584273596 100644
    --- a/drivers/clocksource/timer-sp804.c
    +++ b/drivers/clocksource/timer-sp804.c
    @@ -106,21 +106,25 @@ static u64 notrace sp804_read(void)
     	return ~readl_relaxed(sched_clkevt->value);
     }
     
    +/* Register delay timer backed by the hardware counter */
     #ifdef CONFIG_ARM
     static struct delay_timer delay;
    +static struct sp804_clkevt *delay_clkevt;
    +
     static unsigned long sp804_read_delay_timer_read(void)
     {
    -	return sp804_read();
    +	return ~readl_relaxed(delay_clkevt->value);
     }
     
    -static void sp804_register_delay_timer(int freq)
    +static void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq)
     {
    +	delay_clkevt = clk;
     	delay.freq = freq;
     	delay.read_current_timer = sp804_read_delay_timer_read;
     	register_current_timer_delay(&delay);
     }
     #else
    -static inline void sp804_register_delay_timer(int freq) {}
    +static inline void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq) {}
     #endif
     
     static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
    @@ -135,8 +139,6 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	if (rate < 0)
     		return -EINVAL;
     
    -	sp804_register_delay_timer(rate);
    -
     	clkevt = sp804_clkevt_get(base);
     
     	writel(0, clkevt->ctrl);
    @@ -152,6 +154,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	clocksource_mmio_init(clkevt->value, name,
     		rate, 200, 32, clocksource_mmio_readl_down);
     
    +	sp804_register_delay_timer(clkevt, rate);
    +
     	if (use_sched_clock) {
     		sched_clkevt = clkevt;
     		sched_clock_register(sp804_read, 32, rate);
    -- 
    cgit 1.3-korg
    
    
    
694921a93f3e

clocksource/drivers/timer-sp804: Fix an Oops when read_current_timer is called on ARM32 platforms where the SP804 is not registered as the sched_clock.

1 file changed · +9 6
  • drivers/clocksource/timer-sp804.c+9 6 modified
    diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
    index e82a95ea47247..d698584273596 100644
    --- a/drivers/clocksource/timer-sp804.c
    +++ b/drivers/clocksource/timer-sp804.c
    @@ -106,21 +106,25 @@ static u64 notrace sp804_read(void)
     	return ~readl_relaxed(sched_clkevt->value);
     }
     
    +/* Register delay timer backed by the hardware counter */
     #ifdef CONFIG_ARM
     static struct delay_timer delay;
    +static struct sp804_clkevt *delay_clkevt;
    +
     static unsigned long sp804_read_delay_timer_read(void)
     {
    -	return sp804_read();
    +	return ~readl_relaxed(delay_clkevt->value);
     }
     
    -static void sp804_register_delay_timer(int freq)
    +static void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq)
     {
    +	delay_clkevt = clk;
     	delay.freq = freq;
     	delay.read_current_timer = sp804_read_delay_timer_read;
     	register_current_timer_delay(&delay);
     }
     #else
    -static inline void sp804_register_delay_timer(int freq) {}
    +static inline void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq) {}
     #endif
     
     static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
    @@ -135,8 +139,6 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	if (rate < 0)
     		return -EINVAL;
     
    -	sp804_register_delay_timer(rate);
    -
     	clkevt = sp804_clkevt_get(base);
     
     	writel(0, clkevt->ctrl);
    @@ -152,6 +154,8 @@ static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
     	clocksource_mmio_init(clkevt->value, name,
     		rate, 200, 32, clocksource_mmio_readl_down);
     
    +	sp804_register_delay_timer(clkevt, rate);
    +
     	if (use_sched_clock) {
     		sched_clkevt = clkevt;
     		sched_clock_register(sp804_read, 32, rate);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

2

News mentions

1