From a125c22f649ded5a2d6e038a13e4a46e4f1a4ab8 Mon Sep 17 00:00:00 2001 From: Jongwon Lee Date: Thu, 1 Oct 2026 20:03:11 +0900 Subject: [PATCH 1/2] mce-amd-smca: don't use bank_type uninitialized decode_smca_error() leaves bank_type untouched when the IPID matches no entry in smca_hwid_mcatypes[]. The test meant to catch that is "i >= MAX_NR_BANKS" (64), but the loop only runs to ARRAY_SIZE(smca_hwid_mcatypes), which is 37, so it can never be true. The uninitialized value then indexes smca_names[] and smca_mce_descs[]. An mce_record with an IPID that is not in the table decodes differently on every run; valgrind reports the uninitialized reads. Set bank_type to N_SMCA_BANK_TYPES up front so that case falls into the "Don't know how to decode this bank" check just below. The "i >= MAX_NR_BANKS" test stays: aecf33a ("rasdaemon: Enumerate memory on noncpu nodes") moved it off ARRAY_SIZE() so that non-CPU nodes without a table match keep SMCA_UMC_V2. Signed-off-by: Jongwon Lee --- events-arch-x86/mce-amd-smca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/events-arch-x86/mce-amd-smca.c b/events-arch-x86/mce-amd-smca.c index ac808c02..2ecfcf51 100644 --- a/events-arch-x86/mce-amd-smca.c +++ b/events-arch-x86/mce-amd-smca.c @@ -918,7 +918,8 @@ static inline void fixup_hwid(struct mce_priv *m, uint32_t *hwid_mcatype) /* Decode extended errors according to Scalable MCA specification */ void decode_smca_error(struct mce_event *e, struct mce_priv *m) { - enum smca_bank_types bank_type; + /* stays unknown if the IPID matches no entry and is not a non-CPU node */ + enum smca_bank_types bank_type = N_SMCA_BANK_TYPES; const char *ip_name; uint32_t mcatype_hwid = 0; unsigned short xec = (e->status >> 16) & 0x3f; From bde53afb24844a3c1d88a341d288b7e76031a2b4 Mon Sep 17 00:00:00 2001 From: Jongwon Lee Date: Thu, 1 Oct 2026 20:03:11 +0900 Subject: [PATCH 2/2] ras-erst: free mce_priv on cleanup ras_erst_init() allocates ras->mce_priv through init_mce_priv(), but x86-mce-erst registers no cleanup. The only free_mce_priv() caller is x86-mce-event's cleanup, and modules_cleanup_type() skips modules whose is_enabled is false, so nothing frees it if that module failed to initialize. Add the cleanup. free_mce_priv() clears ras->mce_priv, so having both modules call it is fine. With the allocation x86-mce-event needs made to fail, LeakSanitizer reports 96 bytes direct plus 560 indirect. Signed-off-by: Jongwon Lee --- events-arch-x86/ras-erst.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/events-arch-x86/ras-erst.c b/events-arch-x86/ras-erst.c index c4b9406a..e5f8800d 100644 --- a/events-arch-x86/ras-erst.c +++ b/events-arch-x86/ras-erst.c @@ -238,10 +238,20 @@ static int ras_erst_init(struct ras_module_ctx *ctx) return 0; } +/* + * x86-mce-event's cleanup does not run if that module failed to init, so + * free mce_priv here too. free_mce_priv() clears the pointer. + */ +static void ras_erst_cleanup(struct ras_module_ctx *ctx) +{ + free_mce_priv(ctx->ras); +} + static const struct ras_module_entry ras_erst_module = { .name = "x86-mce-erst", .level = SUB_EVENT_MODULE, .init = ras_erst_init, + .cleanup = ras_erst_cleanup, }; REGISTER_RAS_MODULE(ras_erst_module);