NetBSD Problem Report #60936
From www@netbsd.org Thu Oct 29 06:28:06 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.netbsd.org", Issuer "YR1" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 37B9C1A923B
for <gnats-bugs@gnats.NetBSD.org>; Thu, 29 Oct 2026 06:28:06 +0000 (UTC)
Message-Id: <20261029062804.D71141A923C@mollari.NetBSD.org>
Date: Thu, 29 Oct 2026 06:28:04 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: interrupt disestablish/establish cycle corrupts evcnts
X-Send-Pr-Version: www-1.0
X-From4GNATS: "campbell+netbsd@mumble.net via gnats" <gnats-admin@NetBSD.org>
>Number: 60936
>Category: port-amd64
>Synopsis: interrupt disestablish/establish cycle corrupts evcnts
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: knakahara
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Oct 29 06:30:00 +0000 2026
>Last-Modified: Thu Oct 29 07:55:23 +0000 2026
>Originator: Taylor R Campbell
>Release: current, 11, 10, ...
>Organization:
The Use-after-BSD Interruption, Inc.
>Environment:
>Description:
After suspend/resume, I noticed some interrupt-related evcnts
were missing from `vmstat -ve'. Iterating over the allevents
list in gdb shows that the linked list structure is corrupted.
I suspect this is happening here:
492 isp = ci->ci_isources[slot];
493 if (isp == NULL) {
494 const char *via;
495
496 isp = chained;
497 KASSERT(isp != NULL);
498 if (pic->pic_type == PIC_MSI || pic->pic_type == PIC_MSIX)
499 via = "vec";
500 else
501 via = "pin";
502 snprintf(isp->is_evname, sizeof (isp->is_evname),
503 "%s %d", via, pin);
504 evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
505 pic->pic_name, isp->is_evname);
506 isp->is_active_cpu = ci->ci_cpuid;
507 ci->ci_isources[slot] = isp;
508 }
https://nxr.netbsd.org/xref/src/sys/arch/x86/x86/intr.c?r=1.169#492
I added a check to evcnt_attach_dynamic to see whether the
evcnt is already listed:
TAILQ_FOREACH(ev1, &allevents, ev_list) {
if (((char *)ev <= (char *)ev1 &&
(char *)(ev + 1) > (char *)ev1) ||
((char *)ev1 <= (char *)ev &&
(char *)(ev1 + 1) > (char *)ev)) {
printf("%s: overwriting %p [%s %s] as %p [%s %s]\n",
__func__,
ev1, ev1->ev_group, ev1->ev_name, ev, group, name);
db_stacktrace();
}
}
And sure enough:
[ 20843.030419] evcnt_attach_dynamic: overwriting 0xffff8c8091f6e038 [msix1 vec 0] as 0xffff8c8091f6e038 [msix1 vec 0]
[ 20843.030419] intr_allocate_slot_cpu() at netbsd:intr_allocate_slot_cpu+0x15e
[ 20843.031419] intr_allocate_slot() at netbsd:intr_allocate_slot+0x12a
[ 20843.032419] intr_establish_xname() at netbsd:intr_establish_xname+0x160
[ 20843.033419] x86_pci_msix_establish() at netbsd:x86_pci_msix_establish+0x7e
[ 20843.034419] nvme_pci_intr_establish() at netbsd:nvme_pci_intr_establish+0x133
[ 20843.035419] nvme_resume() at netbsd:nvme_resume+0x3f
[ 20843.036419] nvme_pci_resume() at netbsd:nvme_pci_resume+0x11
[ 20843.037419] device_pmf_driver_resume() at netbsd:device_pmf_driver_resume+0x3d
[ 20843.038419] pmf_device_resume() at netbsd:pmf_device_resume+0x110
[ 20843.039419] pmf_system_resume() at netbsd:pmf_system_resume+0xd9
[ 20843.040419] acpi_enter_sleep_state() at netbsd:acpi_enter_sleep_state+0x14e
[ 20843.041419] sysctl_hw_acpi_sleepstate() at netbsd:sysctl_hw_acpi_sleepstate+0xe8
[ 20843.042419] sysctl_dispatch() at netbsd:sysctl_dispatch+0xbd
[ 20843.043419] sys___sysctl() at netbsd:sys___sysctl+0xec
[ 20843.044419] syscall() at netbsd:syscall+0xaf
[ 20843.044419] --- syscall (number 202) ---
It's not immediately clear to me how this chained intrsource
data structure is supposed to work (well, evidently it doesn't
work!), but it seems that either:
(a) pci_intr_disestablish -- as used by the nvme(4) suspend
handler -- doesn't correctly detach the evcnt when it
should (possibly leading to use-after-free!), or
(b) intr_allocate_slot_cpu needs to recognize when the chained
interrupt source is already attached and not issue another
evcnt_attach_dynamic.
>How-To-Repeat:
suspend/resume a laptop with nvme
>Fix:
Yes, please!
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: port-amd64-maintainer->knakahara
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Thu, 29 Oct 2026 07:55:23 +0000
Responsible-Changed-Why:
Can I trouble you to take a look? Looks like you added this code
as part of pci_intr_distribute.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.