History

x86/amd_node: Fix potential NULL pointer dereference

amd_smn_read/write() are exported functions around __amd_smn_rw(), so they are always available even if amd_smn_init() fails. In that case, 'amd_roots' is NULL and __amd_smn_rw() will access uninitialized memory. Then, commit: 83518453074d ("x86/amd_node: Add SMN offsets to exclusive region access") added the 'smn_exclusive' flag, which indicated the calls to pci_request_config_region_exclusive() succeeded, to prevent concurrent userspace access. Commit: 0a4b61d9c2e4 ("x86/amd_node: Fix AMD root device caching") re-ordered initialization so pci_request_config_region_exclusive() is called earlier and a failure exits amd_smn_init() before allocating 'amd_roots'. The setting of 'smn_exclusive' moved to the end of amd_smn_init(), after 'amd_roots' is allocated. It became redundant and can be removed. Replace 'smn_exclusive' with directly checking 'amd_roots', to fix a potential NULL pointer dereference and to simplify the logic. [ bp: Reorg commit message, touchup comment. ] [ mingo: Rebase & further touchups. ]

Jason Andryuk committed 2 months ago

Commit aefdbd51 parent 72bd92b1 file · +8 −6Browse files

Unified · Split

arch/x86/kernel/amd_node.c+8−6
@@ -38,7 +38,6 @@ static struct pci_dev **amd_roots; · 37 unmodified lines
3838
3939 /* Protect the PCI config register pairs used for SMN. */
4040 static DEFINE_MUTEX(smn_mutex);
41−static bool smn_exclusive;
4241
4342 #define SMN_INDEX_OFFSET 0x60
4443 #define SMN_DATA_OFFSET 0x64
@@ -91,11 +90,16 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b · 46 unmodified lines
9190 if (node >= amd_num_nodes())
9291 return err;
9392
94− root = amd_roots[node];
95− if (!root)
93+ /*
94+ * Uninitialized amd_roots indicates pci_request_config_region_exclusive()
95+ * didn't run or failed and thus the kernel cannot rely on having
96+ * exclusive access to SMN registers so prevent that.
97+ */
98+ if (!amd_roots)
9699 return err;
97100
98− if (!smn_exclusive)
101+ root = amd_roots[node];
102+ if (!root)
99103 return err;
100104
101105 guard(mutex)(&smn_mutex);
@@ -313,8 +317,6 @@ static int __init amd_smn_init(void) · 211 unmodified lines
313317 debugfs_create_file("value", 0600, debugfs_dir, NULL, &smn_value_fops);
314318 }
315319
316− smn_exclusive = true;
317−
318320 return 0;
319321 }
320322