From nobody Sat Sep 26 18:53:07 2026 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 ADCF1470105; Mon, 31 Aug 2026 13:35:05 +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=1788183307; cv=none; b=PxnnnlaVNyn+NQNzwU6Ucmqg9YDdSStwsyeP3hOY8YCXC9xuqOv9JCq3S7hoc8pEzNUIyUBrs0r6fe+iIk8r0b8sdphWS+8EfkGSowX9RlAl2f+wt5Ro1yK2VdnjK8nGYI1IZxpdAEDlQY6JHit101sZfXO01cSEMP+NrBLkzEk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788183307; c=relaxed/simple; bh=zoVrskEDuoFkW2T3zBTR2fSDYP97m4cdTJwOHY6miuM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Zj2UgNy/aXmRJXQ4gLh2MF+w3AqamneApgcfZQJ2kuODfVUdKK7lwJiUklglGRSJO3xFJFTQM0QHIo6yGC7tNcSdHaN7VUD1o1S3g/rwItJA5Gohq2GnzEZ0jgIBfHFO+ZmRS0vPallESEwT4W2DEpZ8yYNNiZCXdO7W2yi46CY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ipncZ0eF; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ipncZ0eF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2938A1F00A3D; Mon, 31 Aug 2026 13:35:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788183305; bh=001UyezUgqzBgR+joQcEPUm7bTKh8njlpvoggf2sAd0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ipncZ0eF45ZkS6hZ41WTwFVBfPGhYcl8HoedRWmuhL0EIQTwLIny7Uv1ohup2IvvL pSv8VBzOHhzx3J6H/dsZf8Ys5azdqz2jRz5+bzy2K3cBmyoVdDXHPP9MifzMNpTHei 98bmruotPjIwVMolYvTaU4rUgPoxtFFd2cdvDpd1pv2q5Z0eOPR2HSFRKlUakLcX2C v0yhCYNjrYVH4Br2YNyRlBB3fGWIqsJB2N9V6lBn1879qjkXV7zjxUeVhjkFURTNQ4 QwY5pdu3bob1iMb3w6xqVDNYLWuRQ6QXPxX2UQgogq5vql0o/RX8IPvhpvgb8aBnE0 Y0HtoSBaH/T9g== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Candice Li , Hawking Zhang , Alex Deucher , Sasha Levin , christian.koenig@amd.com, airlied@gmail.com, simona@ffwll.ch, amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 6.18] drm/amdgpu: validate RAS EEPROM tbl_size before record count Date: Mon, 31 Aug 2026 09:21:37 -0400 Message-ID: <20260831133314.4125787-69-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org> References: <20260831133314.4125787-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.18.48 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Candice Li [ Upstream commit c83e4a45ff9a0b7aa1c48246102009a99ccef11b ] Corrupt EEPROM data can set tbl_size below the table header size. Guard the RAS_NUM_RECS macros against undersized tbl_size and reset the table during init when tbl_size is below the minimum for the table version instead of trusting the header. Signed-off-by: Candice Li Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: ## Phase 1: Commit Message Forensics ### Step 1.1: Subject Line **Record:** `[drm/amdgpu]` `[validate]` =E2=80=94 Validate RAS EEPROM `tbl_= size` before computing record count from the EEPROM table header. ### Step 1.2: Commit Message Tags **Record:** - **Signed-off-by:** Candice Li `` (author) - **Reviewed-by:** Hawking Zhang `` - **Signed-off-by:** Alex Deucher `` (drm/amdgpu maintainer) - No `Fixes:`, `Reported-by:`, `Link:`, `Cc: stable@vger.kernel.org`, `Tested-by:`, or syzbot tags - Notable absence: no fuzzer or user bug report; maintainer-reviewed driver fix only ### Step 1.3: Commit Body Analysis **Record:** - **Bug:** Corrupt EEPROM can set `tbl_size` below the minimum size for the table version (20 bytes for V1, 276 bytes for V2.1/V3). - **Symptom:** `RAS_NUM_RECS` / `RAS_NUM_RECS_V2_1` perform unsigned subtraction on undersized `tbl_size`, producing incorrect record counts; driver should not trust the header. - **Fix approach:** Guard macros to return 0 on undersized `tbl_size`; during `amdgpu_ras_eeprom_init()`, detect undersized `tbl_size` and reset the table via `amdgpu_ras_eeprom_reset_table()` instead of proceeding. - **Root cause:** Missing minimum-size validation before using `tbl_size` in record-count arithmetic. ### Step 1.4: Hidden Bug Fix Detection **Record:** Yes =E2=80=94 described as validation, but it is a real correct= ness bug fix. Undersized `tbl_size` causes unsigned underflow in `RAS_NUM_RECS*` macros. The init-path change converts a permanent init failure (`-EINVAL`, EEPROM marked invalid) into self-healing table reset, matching the existing invalid-header recovery pattern. --- ## Phase 2: Diff Analysis ### Step 2.1: Change Inventory **Record:** - **File:** `drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c` only - **Scope:** ~20 lines changed (macro guards + two init checks) - **Functions/macros modified:** `RAS_NUM_RECS`, `RAS_NUM_RECS_V2_1`, `amdgpu_ras_eeprom_init()` - **Classification:** Single-file surgical fix ### Step 2.2: Code Flow Change **Record:** - **Macro hunks:** Before =E2=80=94 unconditional `(tbl_size - header_size)= / record_size` (unsigned underflow when `tbl_size` too small). After =E2=80= =94 return `0u` if below minimum, else compute normally. - **V2.1/V3 init hunk:** Before =E2=80=94 compute `ras_num_recs` immediatel= y. After =E2=80=94 if `tbl_size < 276`, log error and reset table. - **V1 init hunk:** Before =E2=80=94 compute immediately. After =E2=80=94 i= f `tbl_size < 20`, log error and reset table. - **Path affected:** Driver init on GPUs with RAS EEPROM support (probe- time `amdgpu_ras_eeprom_init()`). ### Step 2.3: Bug Mechanism **Record:** - **Category:** Memory safety / logic correctness (unsigned arithmetic on corrupt data) - **Mechanism:** `tbl_size` is `uint32_t`. When `tbl_size < RAS_TABLE_HEADER_SIZE` (V1) or `< RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE` (V2.1/V3), subtraction wraps to a very large value. Commit 5df0d6addb7e9=E2=80=99s `ras_num_recs > ras_max_record_coun= t` check catches this and returns `-EINVAL`, but EEPROM stays permanently disabled. This commit adds explicit minimum-size validation and auto- recovery. ### Step 2.4: Fix Quality **Record:** Obviously correct and minimal. Mirrors `6ffc6e056febb` (=E2=80=9CReset RAS table if header is invalid=E2=80=9D). Low regression ri= sk: only triggers on already-corrupt EEPROM headers; reset path is well-tested. No API changes. --- ## Phase 3: Git History Investigation ### Step 3.1: Blame **Record:** - `RAS_NUM_RECS` introduced in `63d4c081a556a` (2021-04-06, =E2=80=9COptimi= ze EEPROM RAS table I/O=E2=80=9D) - `RAS_NUM_RECS_V2_1` introduced in `65183faec89f3e` (2023-05-30, =E2=80=9C= Add RAS table v2.1 macro definition=E2=80=9D) - Buggy unsigned arithmetic present since those commits; this tree is **v6.18.44** ### Step 3.2: Fixes: Tag **Record:** N/A =E2=80=94 no `Fixes:` tag in commit message. ### Step 3.3: Related File History **Record:** Related validation commits already in this tree: - `5df0d6addb7e9` =E2=80=94 =E2=80=9CAdd basic validation for RAS header=E2= =80=9D (max record count check) - `6ffc6e056febb` =E2=80=94 =E2=80=9CReset RAS table if header is invalid= =E2=80=9D - `660261df61fb7` =E2=80=94 =E2=80=9Crefine eeprom data check=E2=80=9D (che= cksum on unload) - `89232d0db3ca9` =E2=80=94 =E2=80=9Creturn when ras table checksum is erro= r=E2=80=9D Standalone fix; not part of a numbered series. ### Step 3.4: Author Context **Record:** Candice Li is an AMD contributor. Related validation work by Lijo Lazar and ganglxie in the same file. Alex Deucher (maintainer) signed off. ### Step 3.5: Dependencies **Record:** Requires `RAS_NUM_RECS_V2_1`, `amdgpu_ras_eeprom_reset_table()`, and the version switch in init =E2=80=94= all present in v6.18.44. User diff shows HBM3E context from newer mainline; that block is **not** in this tree and is **not** part of the patch hunks. Applies standalone to 6.18.44 init switch. --- ## Phase 4: Mailing List and External Research ### Step 4.1: Original Discussion **Record:** Commit hash not in this checkout; `b4 dig -c` could not match. Lore search blocked by Anubis bot protection. **UNVERIFIED:** full mailing-list review thread. ### Step 4.2: Reviewers **Record:** **UNVERIFIED** via b4. Commit message shows Reviewed-by Hawking Zhang (AMD) and Signed-off-by Alex Deucher (maintainer). ### Step 4.3: Bug Reports **Record:** N/A =E2=80=94 no `Reported-by:` or `Link:` tags. ### Step 4.4: Related Patches **Record:** Part of ongoing amdgpu RAS EEPROM validation hardening; prior related commits are already in v6.18.44. ### Step 4.5: Stable List History **Record:** **UNVERIFIED** =E2=80=94 could not search lore stable archive. --- ## Phase 5: Code Semantic Analysis ### Step 5.1: Key Functions **Record:** `RAS_NUM_RECS`, `RAS_NUM_RECS_V2_1`, `amdgpu_ras_eeprom_init()` ### Step 5.2: Callers **Record:** `amdgpu_ras_eeprom_init()` called from `amdgpu_ras_init_badpage_info()` in `amdgpu_ras.c:3590`, which runs during GPU RAS initialization at probe. Affects VEGA20, Arcturus, Sienna Cichlid, Aldebaran, and other RAS-EEPROM-capable dGPUs per `__is_ras_eeprom_supported()`. ### Step 5.3: Callees **Record:** On undersized `tbl_size`, calls `amdgpu_ras_eeprom_reset_table()` which rewrites a valid header to EEPROM via I2C. ### Step 5.4: Reachability **Record:** Triggered at every boot on affected hardware when EEPROM `tbl_size` is corrupt. Not userspace-triggerable directly, but affects all boots on affected systems. Corrupt EEPROM is a realistic hardware/partial-write scenario on datacenter GPUs. ### Step 5.5: Similar Patterns **Record:** Same recovery pattern as `6ffc6e056febb` for invalid header magic. Complements `5df0d6addb7e9` max-record validation. --- ## Phase 6: Cross-Reference Against Local Tree (v6.18.44) ### Step 6.1: Buggy Code Present? **Record:** **Yes.** Current tree at lines 145=E2=80=93150 has unguarded `RAS_NUM_RECS` macros; `amdgpu_ras_eeprom_init()` at lines 1415=E2=80=931432 lacks `tbl_size` minimum checks. Bug present since 2021/2023; partial mitigation since `5df0d6addb7e9` (Mar 2025). ### Step 6.2: Backport Complications **Record:** Expected **clean apply** =E2=80=94 init switch structure matche= s; no HBM3E block in 6.18.44 that would conflict. Only line-number offset differs; context-based apply should work. ### Step 6.3: Related Fixes Already Present? **Record:** Max record count validation (`5df0d6addb7e9`) and invalid- header reset (`6ffc6e056febb`) are present. **This specific `tbl_size` minimum validation is NOT present.** --- ## Phase 7: Subsystem Context ### Step 7.1: Subsystem and Criticality **Record:** `drivers/gpu/drm/amd/amdgpu` =E2=80=94 **IMPORTANT** (AMD datacenter/enterprise GPU RAS reliability; not universal but critical for affected hardware). ### Step 7.2: Subsystem Activity **Record:** Actively maintained =E2=80=94 4 EEPROM-related commits in recent file history on this tree. --- ## Phase 8: Impact and Risk Assessment ### Step 8.1: Who Is Affected **Record:** Users of AMD GPUs with RAS EEPROM support (VEGA20, Arcturus, MI-series, RDNA/CDNA dGPUs with HBM RAS). Config: `CONFIG_DRM_AMDGPU` with supported ASICs. ### Step 8.2: Trigger Conditions **Record:** Corrupt EEPROM `tbl_size` field on boot. Uncommon but realistic (wear, partial write, hardware glitch). Not unprivileged- triggerable; hardware/firmware corruption path. ### Step 8.3: Failure Mode Severity **Record:** - **Without fix:** Undersized `tbl_size` =E2=86=92 unsigned underflow =E2= =86=92 `ras_num_recs > ras_max_record_count` =E2=86=92 `-EINVAL` =E2=86=92 `is_e= eprom_valid =3D false` every boot. GPU runs but RAS EEPROM bad-page tracking is permanently disabled until manual intervention. Verified: all `tbl_size < 20` (V1) and `tbl_size < 276` (V2.1) underflow cases produce record counts above max (Python verification). - **With fix:** Table auto-reset; RAS EEPROM functionality restored. - **Severity:** **MEDIUM-HIGH** for affected datacenter hardware (operational RAS degradation, not kernel crash). No OOM path because `amdgpu_ras_load_bad_pages()` is gated on `is_eeprom_valid` (line 3600). ### Step 8.4: Risk-Benefit **Record:** - **Benefit:** Self-healing corrupt EEPROM; defense-in-depth on macros; consistent with existing reset-on-corruption policy. - **Risk:** Very low =E2=80=94 ~20 lines, only error/corruption path, uses existing reset function. - **Ratio:** Moderate benefit, very low risk. Worth backporting given prior similar fixes already in 6.18.y. --- ## Phase 9: Final Synthesis ### Step 9.1: Evidence Summary **FOR backport:** - Fixes real corrupt-EEPROM bug (unsigned underflow + incorrect trust of header) - Auto-recovery instead of permanent EEPROM disable on every boot - Small, surgical, maintainer-reviewed - Prerequisites present in v6.18.44 - Consistent with already-backported validation series (`5df0d6`, `6ffc6e`, `660261`, `89232d`) - Affects production RAS-capable AMD GPUs **AGAINST backport:** - Existing max-record check already prevents huge `kcalloc` / OOM (since Mar 2025) - No crash, deadlock, or security exploit demonstrated - No user/syzbot report - Primary improvement is operational recovery, not crash prevention - Lore review unverified **UNRESOLVED:** Mailing-list discussion and stable-list nomination history. ### Step 9.2: Stable Rules Checklist 1. Obviously correct and tested? **PASS** =E2=80=94 logic is straightforwar= d; reviewed by AMD engineer and maintainer (no runtime test tag). 2. Fixes real bug affecting users? **PASS** =E2=80=94 corrupt EEPROM leaves= RAS tracking disabled on every boot on affected hardware. 3. Important issue? **PASS (MEDIUM-HIGH)** =E2=80=94 datacenter RAS reliabi= lity degradation on supported GPUs; not a kernel crash but materially impacts production GPU health tracking. 4. Small and contained? **PASS** =E2=80=94 one file, ~20 lines. 5. No new features/APIs? **PASS** =E2=80=94 validation and recovery only. 6. Can apply to local tree? **PASS** =E2=80=94 code exists; patch should ap= ply cleanly to v6.18.44. ### Step 9.3: Exception Categories **Record:** Hardware workaround for corrupt EEPROM data on existing RAS- EEPROM driver =E2=80=94 analogous to quirk/validation exception category. ### Step 9.4: Decision Rationale This commit completes the RAS EEPROM validation work already present in v6.18.44. While the max-record check added in `5df0d6addb7e9` prevents the worst outcome (huge allocation), corrupt undersized `tbl_size` still causes permanent EEPROM init failure on every boot. The fix follows the established pattern of resetting corrupt tables rather than leaving the driver in a degraded state. It is small, obviously correct, low-risk, and relevant to this tree=E2=80=99s existing amdgpu RAS EEPROM code. --- ## Verification - **[Phase 1]** Parsed commit message: subject, tags (SOB, Reviewed-by, no Fixes/Reported-by/Link) - **[Phase 2]** Diff analysis: 1 file, macro guards + 2 init checks in `amdgpu_ras_eeprom_init()` - **[Phase 3]** `git describe HEAD`: v6.18.44 - **[Phase 3]** `git blame` lines 145=E2=80=93150: macros from 63d4c081a556a (2021), 65183faec89f3e (2023) - **[Phase 3]** `git log -15 -- amdgpu_ras_eeprom.c`: related validation commits present - **[Phase 3]** `git show 5df0d6addb7e9`: added max record count validation - **[Phase 3]** `git show 6ffc6e056febb`: reset on invalid header magic - **[Phase 3]** `git merge-base --is-ancestor`: 5df0d6 and 65183fa both in tree - **[Phase 4]** `b4 dig`: no commit hash available in tree =E2=80=94 no mat= ch - **[Phase 4]** lore.kernel.org fetch: blocked by Anubis =E2=80=94 **UNVERIFIED** - **[Phase 5]** `grep amdgpu_ras_eeprom_init`: caller at `amdgpu_ras.c:3590` - **[Phase 5]** `grep RAS_NUM_RECS`: only used in `amdgpu_ras_eeprom_init()` - **[Phase 5]** `grep is_eeprom_valid`: gates `amdgpu_ras_load_bad_pages` at line 3600 - **[Phase 6]** Read current `amdgpu_ras_eeprom.c` lines 145=E2=80=93150, 1415=E2=80=931444: buggy code confirmed present - **[Phase 6]** Python verification: all `tbl_size < 20` (V1) and `tbl_size < 276` (V2.1) underflow cases produce record counts > max =E2= =80=94 existing check returns `-EINVAL` - **[Phase 8]** Read `amdgpu_ras_init_badpage_info()`: `is_eeprom_valid =3D !ret`; load gated on validity - **[Phase 8]** `tbl_size` type confirmed `uint32_t` in `amdgpu_ras_eeprom.h:51` **YES** .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/d= rm/amd/amdgpu/amdgpu_ras_eeprom.c index 652aa085b6263..51382d604b1f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -142,12 +142,15 @@ #define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \ (_C)->ras_max_record_count) =20 -#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \ - RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE) +#define RAS_NUM_RECS(_tbl_hdr) \ + (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE) ? 0u : \ + (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE)) =20 -#define RAS_NUM_RECS_V2_1(_tbl_hdr) (((_tbl_hdr)->tbl_size - \ - RAS_TABLE_HEADER_SIZE - \ - RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE) +#define RAS_NUM_RECS_V2_1(_tbl_hdr) \ + (((_tbl_hdr)->tbl_size < RAS_TABLE_HEADER_SIZE + \ + RAS_TABLE_V2_1_INFO_SIZE) ? 0u : \ + (((_tbl_hdr)->tbl_size - RAS_TABLE_HEADER_SIZE - \ + RAS_TABLE_V2_1_INFO_SIZE) / RAS_TABLE_RECORD_SIZE)) =20 #define to_amdgpu_device(x) ((container_of(x, struct amdgpu_ras, eeprom_co= ntrol))->adev) =20 @@ -1415,11 +1418,24 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom= _control *control) switch (hdr->version) { case RAS_TABLE_VER_V2_1: case RAS_TABLE_VER_V3: + if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE) { + dev_err(adev->dev, + "RAS header invalid, tbl_size %u smaller than minimum %u, resetting ta= ble\n", + hdr->tbl_size, + RAS_TABLE_HEADER_SIZE + RAS_TABLE_V2_1_INFO_SIZE); + return amdgpu_ras_eeprom_reset_table(control); + } control->ras_num_recs =3D RAS_NUM_RECS_V2_1(hdr); control->ras_record_offset =3D RAS_RECORD_START_V2_1; control->ras_max_record_count =3D RAS_MAX_RECORD_COUNT_V2_1; break; case RAS_TABLE_VER_V1: + if (hdr->tbl_size < RAS_TABLE_HEADER_SIZE) { + dev_err(adev->dev, + "RAS header invalid, tbl_size %u smaller than minimum %u, resetting ta= ble\n", + hdr->tbl_size, RAS_TABLE_HEADER_SIZE); + return amdgpu_ras_eeprom_reset_table(control); + } control->ras_num_recs =3D RAS_NUM_RECS(hdr); control->ras_record_offset =3D RAS_RECORD_START; control->ras_max_record_count =3D RAS_MAX_RECORD_COUNT; --=20 2.53.0