[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250723104359.364547-5-ysk@kzalloc.com>
Date: Wed, 23 Jul 2025 10:44:03 +0000
From: Yunseong Kim <ysk@...lloc.com>
To: Will Deacon <will@...nel.org>,
Mark Rutland <mark.rutland@....com>
Cc: Hemendra Dassanayake <Hemendra.Dassanayake@....com>,
Austin Kim <austindh.kim@...il.com>,
Michelle Jin <shjy180909@...il.com>,
linux-arm-kernel@...ts.infradead.org,
linux-perf-users@...r.kernel.org,
linux-kernel@...r.kernel.org,
Yunseong Kim <ysk@...lloc.com>,
Yeoreum Yun <yeoreum.yun@....com>,
syzkaller@...glegroups.com
Subject: [PATCH] perf: arm_pmuv3: Fix kernel panic on UBSAN from negative hw.idx in armv8pmu_enable/disable_event()
When 'event->hw.idx' was negative in armv8pmu_enable/disable_event().
UBSAN: shift-out-of-bounds in drivers/perf/arm_pmuv3.c:716:25
shift exponent -1 is negative
UBSAN: shift-out-of-bounds in drivers/perf/arm_pmuv3.c:658:13
shift exponent -1 is negative
This occurred because a perf_event could reach armv8pmu event with a
negative idx, typically when a valid counter could not be allocated.
This issue was observed when running KVM on Radxa's Orion6 platform.
The issue was previously guarded indirectly by armv8pmu_event_is_chained(),
which internally warned and returned false for idx < 0. But since the
commit 29227d6ea157 ("arm64: perf: Clean up enable/disable calls"), this
check was removed.
To prevent undefined behavior, add an explicit guard to early return from
armv8pmu event if hw.idx < 0, similar to handling in other PMU drivers.
(e.g. intel_pmu_disable_event() on arch/x86/events/intel/core.c)
$ ./syz-execprog -executor=./syz-executor -repeat=0 -sandbox=none \
-disable=binfmt_misc,cgroups,close_fds,devlink_pci,ieee802154,net_dev,net_reset,nic_vf,swap,sysctl,tun,usb,vhci,wifi \
-procs=8 perf.syz
r0 = perf_event_open(&(0x7f0000000240)={
0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@perf_config_ext
}, 0x0, 0x0, 0xffffffffffffffff, 0x0)
perf_event_open(&(0x7f0000000280)={
0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@perf_config_ext
}, 0x0, 0x0, r0, 0x0)
perf_event_open(&(0x7f0000000540)={
0x3, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4,
@perf_bp={0x0, 0x2}, 0x20, 0x0, 0x0, 0x0, 0x2,
0x0, 0x0, 0x0, 0x0, 0x0, 0x81
}, 0x0, 0x0, r0, 0x0)
------------[ cut here ]------------
UBSAN: shift-out-of-bounds in drivers/perf/arm_pmuv3.c:716:25
shift exponent -1 is negative
CPU: 0 UID: 0 PID: 8405 Comm: syz.3.19 Tainted: G W 6.16.0-rc2-g5982a539cdce #3 PREEMPT
Tainted: [W]=WARN
Hardware name: QEMU KVM Virtual Machine, BIOS 2025.02-8 05/13/2025
Call trace:
show_stack+0x2c/0x3c (C)
__dump_stack+0x30/0x40
dump_stack_lvl+0xd8/0x12c
dump_stack+0x1c/0x28
ubsan_epilogue+0x14/0x48
__ubsan_handle_shift_out_of_bounds+0x2b0/0x34c
armv8pmu_enable_event+0x3c4/0x4b0
armpmu_start+0xc4/0x118
perf_event_unthrottle_group+0x3a8/0x50c
perf_adjust_freq_unthr_events+0x2f4/0x578
perf_adjust_freq_unthr_context+0x278/0x46c
perf_event_task_tick+0x394/0x5b0
sched_tick+0x314/0x6cc
update_process_times+0x374/0x4b0
tick_nohz_handler+0x334/0x480
__hrtimer_run_queues+0x3ec/0xb78
hrtimer_interrupt+0x2b8/0xb50
arch_timer_handler_virt+0x74/0x88
handle_percpu_devid_irq+0x174/0x308
generic_handle_domain_irq+0xe0/0x140
gic_handle_irq+0x6c/0x190
call_on_irq_stack+0x24/0x30
do_interrupt_handler+0xd4/0x138
el1_interrupt+0x34/0x54
el1h_64_irq_handler+0x18/0x24
el1h_64_irq+0x6c/0x70
generic_exec_single+0x2dc/0x304 (P)
smp_call_function_single+0x308/0x530
perf_install_in_context+0x4a0/0x798
__arm64_sys_perf_event_open+0x184c/0x1d50
invoke_syscall+0x98/0x2b8
el0_svc_common+0x130/0x23c
do_el0_svc+0x48/0x58
el0_svc+0x58/0x17c
el0t_64_sync_handler+0x78/0x108
el0t_64_sync+0x198/0x19c
---[ end trace ]---
------------[ cut here ]------------
UBSAN: shift-out-of-bounds in drivers/perf/arm_pmuv3.c:658:13
shift exponent -1 is negative
CPU: 0 UID: 0 PID: 8006 Comm: syz.0.19 Not tainted 6.16.0-rc2-g5982a539cdce #3 PREEMPT
Hardware name: QEMU KVM Virtual Machine, BIOS 2025.02-8 05/13/2025
Call trace:
show_stack+0x2c/0x3c (C)
__dump_stack+0x30/0x40
dump_stack_lvl+0xd8/0x12c
dump_stack+0x1c/0x28
ubsan_epilogue+0x14/0x48
__ubsan_handle_shift_out_of_bounds+0x2b0/0x34c
armv8pmu_disable_event+0x228/0x2f8
armpmu_stop+0xa0/0x104
perf_event_throttle_group+0x354/0x4cc
__perf_event_account_interrupt+0x26c/0x290
__perf_event_overflow+0xe8/0xd28
perf_event_overflow+0x38/0x4c
armv8pmu_handle_irq+0x244/0x320
armpmu_dispatch_irq+0x6c/0x9c
handle_percpu_devid_irq+0x174/0x308
generic_handle_domain_irq+0xe0/0x140
gic_handle_irq+0x6c/0x190
call_on_irq_stack+0x24/0x30
do_interrupt_handler+0xd4/0x138
el1_interrupt+0x34/0x54
el1h_64_irq_handler+0x18/0x24
el1h_64_irq+0x6c/0x70
generic_exec_single+0x2dc/0x304 (P)
smp_call_function_single+0x308/0x530
perf_install_in_context+0x4a0/0x798
__arm64_sys_perf_event_open+0x184c/0x1d50
invoke_syscall+0x98/0x2b8
el0_svc_common+0x130/0x23c
do_el0_svc+0x48/0x58
el0_svc+0x58/0x17c
el0t_64_sync_handler+0x78/0x108
el0t_64_sync+0x198/0x19c
---[ end trace ]---
------------[ cut here ]------------
UBSAN: shift-out-of-bounds in drivers/perf/arm_pmuv3.c:730:26
shift exponent -1 is negative
CPU: 0 UID: 0 PID: 8006 Comm: syz.0.19 Not tainted 6.16.0-rc2-g5982a539cdce #3 PREEMPT
Hardware name: QEMU KVM Virtual Machine, BIOS 2025.02-8 05/13/2025
Call trace:
show_stack+0x2c/0x3c (C)
__dump_stack+0x30/0x40
dump_stack_lvl+0xd8/0x12c
dump_stack+0x1c/0x28
ubsan_epilogue+0x14/0x48
__ubsan_handle_shift_out_of_bounds+0x2b0/0x34c
armv8pmu_disable_event+0x298/0x2f8
armpmu_stop+0xa0/0x104
perf_event_throttle_group+0x354/0x4cc
__perf_event_account_interrupt+0x26c/0x290
__perf_event_overflow+0xe8/0xd28
perf_event_overflow+0x38/0x4c
armv8pmu_handle_irq+0x244/0x320
armpmu_dispatch_irq+0x6c/0x9c
handle_percpu_devid_irq+0x174/0x308
generic_handle_domain_irq+0xe0/0x140
gic_handle_irq+0x6c/0x190
call_on_irq_stack+0x24/0x30
do_interrupt_handler+0xd4/0x138
el1_interrupt+0x34/0x54
el1h_64_irq_handler+0x18/0x24
el1h_64_irq+0x6c/0x70
generic_exec_single+0x2dc/0x304 (P)
smp_call_function_single+0x308/0x530
perf_install_in_context+0x4a0/0x798
__arm64_sys_perf_event_open+0x184c/0x1d50
invoke_syscall+0x98/0x2b8
el0_svc_common+0x130/0x23c
do_el0_svc+0x48/0x58
el0_svc+0x58/0x17c
el0t_64_sync_handler+0x78/0x108
el0t_64_sync+0x198/0x19c
---[ end trace ]---
Fixes: 29227d6ea157 ("arm64: perf: Clean up enable/disable calls")
Signed-off-by: Yunseong Kim <ysk@...lloc.com>
Tested-by: Yunseong Kim <ysk@...lloc.com>
Cc: Yeoreum Yun <yeoreum.yun@....com>
Cc: syzkaller@...glegroups.com
---
drivers/perf/arm_pmuv3.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c
index 3db9f4ed17e8..846d69643fd8 100644
--- a/drivers/perf/arm_pmuv3.c
+++ b/drivers/perf/arm_pmuv3.c
@@ -795,6 +795,9 @@ static void armv8pmu_enable_user_access(struct arm_pmu *cpu_pmu)
static void armv8pmu_enable_event(struct perf_event *event)
{
+ if (unlikely(event->hw.idx < 0))
+ return;
+
armv8pmu_write_event_type(event);
armv8pmu_enable_event_irq(event);
armv8pmu_enable_event_counter(event);
@@ -802,6 +805,9 @@ static void armv8pmu_enable_event(struct perf_event *event)
static void armv8pmu_disable_event(struct perf_event *event)
{
+ if (unlikely(event->hw.idx < 0))
+ return;
+
armv8pmu_disable_event_counter(event);
armv8pmu_disable_event_irq(event);
}
--
2.50.0
Powered by blists - more mailing lists