From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AC61459AD7; Tue, 25 Aug 2026 13:51:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665878; cv=none; b=EO3HdjjRp35euNcAJVoWHYMY1UON+e+QuduxMYzu5rkrqXHGPNrVkD23V6Api4LkrdWtfpLe+yH26M+MQZjIZvYq4b1iPvYZgMKAt+Z5yQDo0C0XukYQrMKRGHBQ4tDBno1QY/p9BD+CV0EN6G3YYsVBZyoqBmZ37UHr6e9AAMI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665878; c=relaxed/simple; bh=6dd0QSce0XgYnuzaglZra8yTuRimKngnqLZm942ZBRM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZMPHR5PQ0soYEUDqm6ajmr8ws78Y6RTx/pjkPbPD6IfQa54Ke6wQJDrezE7bCKmccLGoIZ3I/JL7Y9G9Bkzrvge1csZC+Gi+X+shAa8jxR+6oVPEz8towsk8xG8fwaJybkiQWZ0rkMYCRr6GAXxhtir5UiZhxdg/plpuUN3uh3s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=FxP9xaji; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="FxP9xaji" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BFFC51F000E9; Tue, 25 Aug 2026 13:51:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787665877; bh=fXCTBP16mL3Li9oCBaMzi+SRyz36OZij+dTWZdgmJPA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FxP9xaji32WE+i0VKbtkxSsRMHRFuJuHCVxCaKYZ9dEGzfJ52vKxM2eLxRMq1zeBr jDToAni0g7o8EZ6XkUETxVJ6gyhPPqm3n5pqAHuThsAvsKmXxGosCS86fGjrCSVyfH RWAT4fHLSaVbqcRGF2lyMrdbae9d4baAdOXO69gs= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Steffen Persvold , Manivannan Sadhasivam Subject: [PATCH 6.1 01/79] PCI: host-generic: Fix NULL pointer dereference on 32-bit CAM systems Date: Tue, 25 Aug 2026 15:25:41 +0200 Message-ID: <20260825132541.730637297@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825132541.677185791@linuxfoundation.org> References: <20260825132541.677185791@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.1-stable review patch. If anyone has any objections, please let me know. ------------------ From: Steffen Persvold commit 008cb88edb41f3c7c8e0ed763ff9f26719830984 upstream. On 32-bit systems the config space is too large to ioremap in one go, so pci_ecam_create() maps each bus segment separately and relies on the ->add_bus callback (pci_ecam_add_bus) to populate the per-bus mapping in cfg->winp[]. pci_ecam_map_bus() then uses that mapping as the base for every config access. The generic ECAM ops (pci_generic_ecam_ops) already provide the ->add_bus and ->remove_bus callbacks, but the CAM (legacy) ops in pci-host-generic.c do not. As a result, on a 32-bit host using "pci-host-cam-generic" the per-bus mapping is never set up and the first config read dereferences a NULL base, crashing during bus enumeration: Unable to handle kernel NULL pointer dereference at virtual address 00000800 Oops [#1] CPU: 0 PID: 1 Comm: swapper Not tainted 6.9.7+ #43 Hardware name: Digilent Nexys-Video-A7 RV32 (DT) epc : pci_generic_config_read+0x40/0xb0 ra : pci_generic_config_read+0x2c/0xb0 [] pci_generic_config_read+0x40/0xb0 [] pci_bus_read_config_dword+0x50/0xb0 [] pci_bus_generic_read_dev_vendor_id+0x3c/0x1ec [] pci_scan_single_device+0xa4/0x11c [] pci_scan_slot+0x9c/0x23c [] pci_scan_child_bus_extend+0x58/0x2f4 [] pci_scan_root_bus_bridge+0x64/0xe8 [] pci_host_probe+0x20/0xc8 [] pci_host_common_probe+0x144/0x1e4 Fix this by giving the CAM ops the same ->add_bus/->remove_bus callbacks. Since pci_ecam_add_bus() and pci_ecam_remove_bus() are static to ecam.c, move the CAM ops definition there as pci_generic_cam_ops (mirroring pci_generic_ecam_ops) and export it for pci-host-generic.c to reference. Fixes: 8fe55ef23387 ("PCI: Dynamically map ECAM regions") Signed-off-by: Steffen Persvold [mani: removed timestamp from log] Signed-off-by: Manivannan Sadhasivam Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260709122446.3151899-1-spersvold@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/pci/controller/pci-host-generic.c | 11 +---------- drivers/pci/ecam.c | 13 +++++++++++++ include/linux/pci-ecam.h | 3 +++ 3 files changed, 17 insertions(+), 10 deletions(-) --- a/drivers/pci/controller/pci-host-generic.c +++ b/drivers/pci/controller/pci-host-generic.c @@ -14,15 +14,6 @@ #include #include -static const struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = { - .bus_shift = 16, - .pci_ops = { - .map_bus = pci_ecam_map_bus, - .read = pci_generic_config_read, - .write = pci_generic_config_write, - } -}; - static bool pci_dw_valid_device(struct pci_bus *bus, unsigned int devfn) { struct pci_config_window *cfg = bus->sysdata; @@ -58,7 +49,7 @@ static const struct pci_ecam_ops pci_dw_ static const struct of_device_id gen_pci_of_match[] = { { .compatible = "pci-host-cam-generic", - .data = &gen_pci_cfg_cam_bus_ops }, + .data = &pci_generic_cam_ops }, { .compatible = "pci-host-ecam-generic", .data = &pci_generic_ecam_ops }, --- a/drivers/pci/ecam.c +++ b/drivers/pci/ecam.c @@ -208,6 +208,19 @@ const struct pci_ecam_ops pci_generic_ec }; EXPORT_SYMBOL_GPL(pci_generic_ecam_ops); +/* CAM ops */ +const struct pci_ecam_ops pci_generic_cam_ops = { + .bus_shift = 16, + .pci_ops = { + .add_bus = pci_ecam_add_bus, + .remove_bus = pci_ecam_remove_bus, + .map_bus = pci_ecam_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, + } +}; +EXPORT_SYMBOL_GPL(pci_generic_cam_ops); + #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) /* ECAM ops for 32-bit access only (non-compliant) */ const struct pci_ecam_ops pci_32b_ops = { --- a/include/linux/pci-ecam.h +++ b/include/linux/pci-ecam.h @@ -77,6 +77,9 @@ void __iomem *pci_ecam_map_bus(struct pc /* default ECAM ops */ extern const struct pci_ecam_ops pci_generic_ecam_ops; +/* default CAM ops */ +extern const struct pci_ecam_ops pci_generic_cam_ops; + #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) extern const struct pci_ecam_ops pci_32b_ops; /* 32-bit accesses only */ extern const struct pci_ecam_ops pci_32b_read_ops; /* 32-bit read only */