[PATCH AUTOSEL 6.15 2/9] wifi: iwlwifi: mld: Work around Clang loop unrolling bug

Sasha Levin
2025-06-04T11:49:31Z

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;
--
2.39.5