Skip to content

Commit d985e43

Browse files
committed
kunit/stackinit: Use fill byte different from Clang i386 pattern
The byte initialization values used with -ftrivial-auto-var-init=pattern (CONFIG_INIT_STACK_ALL_PATTERN=y) depends on the compiler, architecture, and byte position relative to struct member types. On i386 with Clang, this includes the 0xFF value, which means it looks like nothing changes between the leaf byte filling pass and the expected "stack wiping" pass of the stackinit test. Use the byte fill value of 0x99 instead, fixing the test for i386 Clang builds. Reported-by: ernsteiswuerfel Closes: ClangBuiltLinux#2071 Fixes: 8c30d32 ("lib/test_stackinit: Handle Clang auto-initialization pattern") Tested-by: Nathan Chancellor <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 04e403e commit d985e43

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

lib/tests/stackinit_kunit.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
184184
#define INIT_UNION_assigned_copy(var_type) \
185185
INIT_STRUCT_assigned_copy(var_type)
186186

187+
/*
188+
* The "did we actually fill the stack?" check value needs
189+
* to be neither 0 nor any of the "pattern" bytes. The
190+
* pattern bytes are compiler, architecture, and type based,
191+
* so we have to pick a value that never appears for those
192+
* combinations. Use 0x99 which is not 0xFF, 0xFE, nor 0xAA.
193+
*/
194+
#define FILL_BYTE 0x99
195+
187196
/*
188197
* @name: unique string name for the test
189198
* @var_type: type to be tested for zeroing initialization
@@ -206,12 +215,12 @@ static noinline void test_ ## name (struct kunit *test) \
206215
ZERO_CLONE_ ## which(zero); \
207216
/* Clear entire check buffer for 0xFF overlap test. */ \
208217
memset(check_buf, 0x00, sizeof(check_buf)); \
209-
/* Fill stack with 0xFF. */ \
218+
/* Fill stack with FILL_BYTE. */ \
210219
ignored = leaf_ ##name((unsigned long)&ignored, 1, \
211220
FETCH_ARG_ ## which(zero)); \
212-
/* Verify all bytes overwritten with 0xFF. */ \
221+
/* Verify all bytes overwritten with FILL_BYTE. */ \
213222
for (sum = 0, i = 0; i < target_size; i++) \
214-
sum += (check_buf[i] != 0xFF); \
223+
sum += (check_buf[i] != FILL_BYTE); \
215224
/* Clear entire check buffer for later bit tests. */ \
216225
memset(check_buf, 0x00, sizeof(check_buf)); \
217226
/* Extract stack-defined variable contents. */ \
@@ -222,7 +231,8 @@ static noinline void test_ ## name (struct kunit *test) \
222231
* possible between the two leaf function calls. \
223232
*/ \
224233
KUNIT_ASSERT_EQ_MSG(test, sum, 0, \
225-
"leaf fill was not 0xFF!?\n"); \
234+
"leaf fill was not 0x%02X!?\n", \
235+
FILL_BYTE); \
226236
\
227237
/* Validate that compiler lined up fill and target. */ \
228238
KUNIT_ASSERT_TRUE_MSG(test, \
@@ -234,9 +244,9 @@ static noinline void test_ ## name (struct kunit *test) \
234244
(int)((ssize_t)(uintptr_t)fill_start - \
235245
(ssize_t)(uintptr_t)target_start)); \
236246
\
237-
/* Look for any bytes still 0xFF in check region. */ \
247+
/* Validate check region has no FILL_BYTE bytes. */ \
238248
for (sum = 0, i = 0; i < target_size; i++) \
239-
sum += (check_buf[i] == 0xFF); \
249+
sum += (check_buf[i] == FILL_BYTE); \
240250
\
241251
if (sum != 0 && xfail) \
242252
kunit_skip(test, \
@@ -271,12 +281,12 @@ static noinline int leaf_ ## name(unsigned long sp, bool fill, \
271281
* stack frame of SOME kind... \
272282
*/ \
273283
memset(buf, (char)(sp & 0xff), sizeof(buf)); \
274-
/* Fill variable with 0xFF. */ \
284+
/* Fill variable with FILL_BYTE. */ \
275285
if (fill) { \
276286
fill_start = &var; \
277287
fill_size = sizeof(var); \
278288
memset(fill_start, \
279-
(char)((sp & 0xff) | forced_mask), \
289+
FILL_BYTE & forced_mask, \
280290
fill_size); \
281291
} \
282292
\
@@ -469,7 +479,7 @@ static int noinline __leaf_switch_none(int path, bool fill)
469479
fill_start = &var;
470480
fill_size = sizeof(var);
471481

472-
memset(fill_start, forced_mask | 0x55, fill_size);
482+
memset(fill_start, (forced_mask | 0x55) & FILL_BYTE, fill_size);
473483
}
474484
memcpy(check_buf, target_start, target_size);
475485
break;
@@ -480,7 +490,7 @@ static int noinline __leaf_switch_none(int path, bool fill)
480490
fill_start = &var;
481491
fill_size = sizeof(var);
482492

483-
memset(fill_start, forced_mask | 0xaa, fill_size);
493+
memset(fill_start, (forced_mask | 0xaa) & FILL_BYTE, fill_size);
484494
}
485495
memcpy(check_buf, target_start, target_size);
486496
break;

0 commit comments

Comments
 (0)