From: Kees Cook kees@kernel.org
[ Upstream commit 368556dd234dc4a506a35a0c99c0eee2ab475c77 ]
The nested loop in iwl_mld_send_proto_offload() confuses Clang into thinking there could be a final loop iteration past the end of the "nsc" array (which is only 4 entries). The FORTIFY checking in memcmp() (via ipv6_addr_cmp()) notices this (due to the available bytes in the out-of-bounds position of &nsc[4] being 0), and errors out, failing the build. For some reason (likely due to architectural loop unrolling configurations), this is only exposed on ARM builds currently. Due to Clang's lack of inline tracking[1], the warning is not very helpful:
include/linux/fortify-string.h:719:4: error: call to '__read_overflow' declared with 'error' attribute: detected read beyond size of object (1st parameter) 719 | __read_overflow(); | ^ 1 error generated.
But this was tracked down to iwl_mld_send_proto_offload()'s ipv6_addr_cmp() call.
An upstream Clang bug has been filed[2] to track this. For now fix the build by explicitly bounding the inner loop by "n_nsc", which is what "c" is already limited to.
Reported-by: Nathan Chancellor nathan@kernel.org Closes: https://github.com/ClangBuiltLinux/linux/issues/2076 Link: https://github.com/llvm/llvm-project/pull/73552 [1] Link: https://github.com/llvm/llvm-project/issues/136603 [2] Link: https://lore.kernel.org/r/20250421204153.work.935-kees@kernel.org Signed-off-by: Kees Cook kees@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
Now let me analyze the similar commits to understand the backporting patterns: **YES** This commit should be backported to stable kernel trees. ## Extensive Analysis ### Code Change Analysis The commit modifies a single line in `drivers/net/wireless/intel/iwlwifi/mld/d3.c`, changing: ```c for (j = 0; j < c; j++) ``` to: ```c for (j = 0; j < n_nsc && j < c; j++) ``` This change adds an explicit upper bound (`n_nsc`) to prevent the loop iterator `j` from exceeding the size of the `nsc` array (which has 4 entries). ### Why This Should Be Backported **1. Build Failure Fix**: This commit fixes a concrete build failure when using Clang compiler with ARM architecture and `CONFIG_FORTIFY_SOURCE=y`. Build failures are critical issues that prevent kernel compilation entirely. **2. Compiler Support**: The fix enables Clang compilation support for the iwlwifi driver, which is important for kernel diversity and CI/build systems that use Clang. **3. Minimal Risk**: The change is extremely small and contained: - Only adds an additional bounds check (`j < n_nsc`) - No functional logic changes - The added check is logically correct and safe - Cannot introduce regressions as it only makes the loop more restrictive **4. Pattern Matches "YES" Commits**: This fix aligns closely with similar commits marked as "YES": - **Similar Commit #2** (wil6210 fortify warnings): Fixed FORTIFY warnings with struct_group, minimal risk - **Similar Commit #3** (mlxsw LLVM workaround): Explicitly worked around LLVM/Clang compiler issues - **Similar Commit #4** (ath9k fortify warnings): Fixed fortify warnings with struct_group - **Similar Commit #5** (plfxlc clang fortify): Fixed clang-specific fortify warning **5. Architecture- Specific but Affects Real Users**: While currently only exposed on ARM builds with Clang, this affects legitimate build configurations used in production environments. **6. No Side Effects**: The fix purely constrains loop bounds without changing algorithmic behavior. The original code was functionally correct but triggered false positive compiler analysis. ### Technical Justification **Bug Analysis**: Clang's loop unrolling optimization incorrectly analyzes that the variable `c` could reach 4, making the inner loop potentially access `nsc[4]` (out of bounds). The kernel's FORTIFY_SOURCE checking detects this theoretical overflow and fails the build. **Fix Correctness**: The added bound `j < n_nsc` is mathematically correct since: - `n_nsc` represents the actual size of the `nsc` array (4 entries) - `c` is already bounded by `n_nsc` in the outer loop condition - Adding `j < n_nsc` makes this constraint explicit to the compiler **No Functional Impact**: Since `c` never exceeds `n_nsc` in correct execution, the additional check `j < n_nsc` never actually triggers - it exists purely to satisfy the compiler's static analysis. ### Comparison to "NO" Reference Unlike **Similar Commit #1** (iwlwifi fall-through warnings) which was marked "NO" because it only addressed code style/warning improvements without fixing actual bugs, this commit fixes a real build failure that prevents compilation. ### Conclusion This is a textbook example of a good stable backport candidate: it fixes a concrete build issue with minimal risk, follows established patterns for compiler workarounds, and has zero functional impact on runtime behavior. The fix enables continued Clang compiler support for a critical wireless driver without introducing any regression risk.
drivers/net/wireless/intel/iwlwifi/mld/d3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index ee99298eebf59..7ce01ad3608e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -1757,7 +1757,7 @@ iwl_mld_send_proto_offload(struct iwl_mld *mld,
addrconf_addr_solict_mult(&wowlan_data->target_ipv6_addrs[i], &solicited_addr); - for (j = 0; j < c; j++) + for (j = 0; j < n_nsc && j < c; j++) if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr, &solicited_addr) == 0) break;