mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yunseong Kim <ysk@kzalloc.com>
To: Will Deacon <will@kernel.org>, Mark Rutland <mark.rutland@arm.com>
Cc: Hemendra Dassanayake <Hemendra.Dassanayake@arm.com>,
	Austin Kim <austindh.kim@gmail.com>,
	Michelle Jin <shjy180909@gmail.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	Yunseong Kim <ysk@kzalloc.com>, Yeoreum Yun <yeoreum.yun@arm.com>,
	syzkaller@googlegroups.com
Subject: [PATCH] perf: arm_pmuv3: Fix kernel panic on UBSAN from negative hw.idx in armv8pmu_enable/disable_event()
Date: Wed, 23 Jul 2025 10:44:03 +0000	[thread overview]
Message-ID: <20250723104359.364547-5-ysk@kzalloc.com> (raw)

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@kzalloc.com>
Tested-by: Yunseong Kim <ysk@kzalloc.com>
Cc: Yeoreum Yun <yeoreum.yun@arm.com>
Cc: syzkaller@googlegroups.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


             reply	other threads:[~2025-07-23 11:02 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-23 10:44 Yunseong Kim [this message]
2025-07-23 12:35 ` Mark Rutland
2025-07-23 17:39   ` Mark Rutland
2025-07-23 18:57     ` Yunseong Kim
2025-07-24 11:07       ` Mark Rutland
2025-07-24 19:22         ` Yunseong Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250723104359.364547-5-ysk@kzalloc.com \
    --to=ysk@kzalloc.com \
    --cc=Hemendra.Dassanayake@arm.com \
    --cc=austindh.kim@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=shjy180909@gmail.com \
    --cc=syzkaller@googlegroups.com \
    --cc=will@kernel.org \
    --cc=yeoreum.yun@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®