]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
EDAC/igen6: Fix NULL pointer dereference
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>
Wed, 18 Jun 2025 16:23:06 +0000 (00:23 +0800)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 18 Jun 2025 18:19:45 +0000 (20:19 +0200)
A kernel panic was reported with the following kernel log:

  EDAC igen6: Expected 2 mcs, but only 1 detected.
  BUG: unable to handle page fault for address: 000000000000d570
  ...
  Hardware name: Notebook V54x_6x_TU/V54x_6x_TU, BIOS Dasharo (coreboot+UEFI) v0.9.0 07/17/2024
  RIP: e030:ecclog_handler+0x7e/0xf0 [igen6_edac]
  ...
  igen6_probe+0x2a0/0x343 [igen6_edac]
  ...
  igen6_init+0xc5/0xff0 [igen6_edac]
  ...

This issue occurred because one memory controller was disabled by
the BIOS but the igen6_edac driver still checked all the memory
controllers, including this absent one, to identify the source of
the error. Accessing the null MMIO for the absent memory controller
resulted in the oops above.

Fix this issue by reverting the configuration structure to non-const
and updating the field 'res_cfg->num_imc' to reflect the number of
detected memory controllers.

Fixes: 20e190b1c1fd ("EDAC/igen6: Skip absent memory controllers")
Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Closes: https://lore.kernel.org/all/aFFN7RlXkaK_loQb@mail-itl/
Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Link: https://lore.kernel.org/r/20250618162307.1523736-1-qiuxu.zhuo@intel.com
drivers/edac/igen6_edac.c

index 1930dc00c79142576de3554de2d1afd829808d51..1cb5c67e78aee40ab8e7a26571cdb4389e974086 100644 (file)
 #define MEM_SLICE_HASH_MASK(v)         (GET_BITFIELD(v, 6, 19) << 6)
 #define MEM_SLICE_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26)
 
-static const struct res_config {
+static struct res_config {
        bool machine_check;
        /* The number of present memory controllers. */
        int num_imc;
@@ -479,7 +479,7 @@ static u64 rpl_p_err_addr(u64 ecclog)
        return ECC_ERROR_LOG_ADDR45(ecclog);
 }
 
-static const struct res_config ehl_cfg = {
+static struct res_config ehl_cfg = {
        .num_imc                = 1,
        .imc_base               = 0x5000,
        .ibecc_base             = 0xdc00,
@@ -489,7 +489,7 @@ static const struct res_config ehl_cfg = {
        .err_addr_to_imc_addr   = ehl_err_addr_to_imc_addr,
 };
 
-static const struct res_config icl_cfg = {
+static struct res_config icl_cfg = {
        .num_imc                = 1,
        .imc_base               = 0x5000,
        .ibecc_base             = 0xd800,
@@ -499,7 +499,7 @@ static const struct res_config icl_cfg = {
        .err_addr_to_imc_addr   = ehl_err_addr_to_imc_addr,
 };
 
-static const struct res_config tgl_cfg = {
+static struct res_config tgl_cfg = {
        .machine_check          = true,
        .num_imc                = 2,
        .imc_base               = 0x5000,
@@ -513,7 +513,7 @@ static const struct res_config tgl_cfg = {
        .err_addr_to_imc_addr   = tgl_err_addr_to_imc_addr,
 };
 
-static const struct res_config adl_cfg = {
+static struct res_config adl_cfg = {
        .machine_check          = true,
        .num_imc                = 2,
        .imc_base               = 0xd800,
@@ -524,7 +524,7 @@ static const struct res_config adl_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
-static const struct res_config adl_n_cfg = {
+static struct res_config adl_n_cfg = {
        .machine_check          = true,
        .num_imc                = 1,
        .imc_base               = 0xd800,
@@ -535,7 +535,7 @@ static const struct res_config adl_n_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
-static const struct res_config rpl_p_cfg = {
+static struct res_config rpl_p_cfg = {
        .machine_check          = true,
        .num_imc                = 2,
        .imc_base               = 0xd800,
@@ -547,7 +547,7 @@ static const struct res_config rpl_p_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
-static const struct res_config mtl_ps_cfg = {
+static struct res_config mtl_ps_cfg = {
        .machine_check          = true,
        .num_imc                = 2,
        .imc_base               = 0xd800,
@@ -558,7 +558,7 @@ static const struct res_config mtl_ps_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
-static const struct res_config mtl_p_cfg = {
+static struct res_config mtl_p_cfg = {
        .machine_check          = true,
        .num_imc                = 2,
        .imc_base               = 0xd800,
@@ -569,7 +569,7 @@ static const struct res_config mtl_p_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
-static const struct pci_device_id igen6_pci_tbl[] = {
+static struct pci_device_id igen6_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, DID_EHL_SKU5), (kernel_ulong_t)&ehl_cfg },
        { PCI_VDEVICE(INTEL, DID_EHL_SKU6), (kernel_ulong_t)&ehl_cfg },
        { PCI_VDEVICE(INTEL, DID_EHL_SKU7), (kernel_ulong_t)&ehl_cfg },
@@ -1350,9 +1350,11 @@ static int igen6_register_mcis(struct pci_dev *pdev, u64 mchbar)
                return -ENODEV;
        }
 
-       if (lmc < res_cfg->num_imc)
+       if (lmc < res_cfg->num_imc) {
                igen6_printk(KERN_WARNING, "Expected %d mcs, but only %d detected.",
                             res_cfg->num_imc, lmc);
+               res_cfg->num_imc = lmc;
+       }
 
        return 0;