Skip to content

Commit c69a48c

Browse files
daxtenstorvalds
authored andcommitted
powerpc: make feature-fixup tests fortify-safe
Testing the fortified string functions[1] would cause a kernel panic on boot in test_feature_fixups() due to a buffer overflow in memcmp. This boils down to things like this: extern unsigned int ftr_fixup_test1; extern unsigned int ftr_fixup_test1_orig; check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0); We know that these are asm labels so it is safe to read up to 'size' bytes at those addresses. However, because we have passed the address of a single unsigned int to memcmp, the compiler believes the underlying object is in fact a single unsigned int. So if size > sizeof(unsigned int), there will be a panic at runtime. We can fix this by changing the types: instead of calling the asm labels unsigned ints, call them unsigned int[]s. Therefore the size isn't incorrectly determined at compile time and we get a regular unsafe memcmp and no panic. [1] http://openwall.com/lists/kernel-hardening/2017/05/09/2 Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Daniel Axtens <[email protected]> Signed-off-by: Kees Cook <[email protected]> Suggested-by: Michael Ellerman <[email protected]> Tested-by: Andrew Donnellan <[email protected]> Reviewed-by: Andrew Donnellan <[email protected]> Cc: Kees Cook <[email protected]> Cc: Daniel Micay <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 054f367 commit c69a48c

File tree

1 file changed

+90
-90
lines changed

1 file changed

+90
-90
lines changed

arch/powerpc/lib/feature-fixups.c

Lines changed: 90 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -233,192 +233,192 @@ static long calc_offset(struct fixup_entry *entry, unsigned int *p)
233233

234234
static void test_basic_patching(void)
235235
{
236-
extern unsigned int ftr_fixup_test1;
237-
extern unsigned int end_ftr_fixup_test1;
238-
extern unsigned int ftr_fixup_test1_orig;
239-
extern unsigned int ftr_fixup_test1_expected;
240-
int size = &end_ftr_fixup_test1 - &ftr_fixup_test1;
236+
extern unsigned int ftr_fixup_test1[];
237+
extern unsigned int end_ftr_fixup_test1[];
238+
extern unsigned int ftr_fixup_test1_orig[];
239+
extern unsigned int ftr_fixup_test1_expected[];
240+
int size = end_ftr_fixup_test1 - ftr_fixup_test1;
241241

242242
fixup.value = fixup.mask = 8;
243-
fixup.start_off = calc_offset(&fixup, &ftr_fixup_test1 + 1);
244-
fixup.end_off = calc_offset(&fixup, &ftr_fixup_test1 + 2);
243+
fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1);
244+
fixup.end_off = calc_offset(&fixup, ftr_fixup_test1 + 2);
245245
fixup.alt_start_off = fixup.alt_end_off = 0;
246246

247247
/* Sanity check */
248-
check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0);
248+
check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
249249

250250
/* Check we don't patch if the value matches */
251251
patch_feature_section(8, &fixup);
252-
check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0);
252+
check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
253253

254254
/* Check we do patch if the value doesn't match */
255255
patch_feature_section(0, &fixup);
256-
check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0);
256+
check(memcmp(ftr_fixup_test1, ftr_fixup_test1_expected, size) == 0);
257257

258258
/* Check we do patch if the mask doesn't match */
259-
memcpy(&ftr_fixup_test1, &ftr_fixup_test1_orig, size);
260-
check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_orig, size) == 0);
259+
memcpy(ftr_fixup_test1, ftr_fixup_test1_orig, size);
260+
check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
261261
patch_feature_section(~8, &fixup);
262-
check(memcmp(&ftr_fixup_test1, &ftr_fixup_test1_expected, size) == 0);
262+
check(memcmp(ftr_fixup_test1, ftr_fixup_test1_expected, size) == 0);
263263
}
264264

265265
static void test_alternative_patching(void)
266266
{
267-
extern unsigned int ftr_fixup_test2;
268-
extern unsigned int end_ftr_fixup_test2;
269-
extern unsigned int ftr_fixup_test2_orig;
270-
extern unsigned int ftr_fixup_test2_alt;
271-
extern unsigned int ftr_fixup_test2_expected;
272-
int size = &end_ftr_fixup_test2 - &ftr_fixup_test2;
267+
extern unsigned int ftr_fixup_test2[];
268+
extern unsigned int end_ftr_fixup_test2[];
269+
extern unsigned int ftr_fixup_test2_orig[];
270+
extern unsigned int ftr_fixup_test2_alt[];
271+
extern unsigned int ftr_fixup_test2_expected[];
272+
int size = end_ftr_fixup_test2 - ftr_fixup_test2;
273273

274274
fixup.value = fixup.mask = 0xF;
275-
fixup.start_off = calc_offset(&fixup, &ftr_fixup_test2 + 1);
276-
fixup.end_off = calc_offset(&fixup, &ftr_fixup_test2 + 2);
277-
fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test2_alt);
278-
fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test2_alt + 1);
275+
fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1);
276+
fixup.end_off = calc_offset(&fixup, ftr_fixup_test2 + 2);
277+
fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test2_alt);
278+
fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test2_alt + 1);
279279

280280
/* Sanity check */
281-
check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0);
281+
check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
282282

283283
/* Check we don't patch if the value matches */
284284
patch_feature_section(0xF, &fixup);
285-
check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0);
285+
check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
286286

287287
/* Check we do patch if the value doesn't match */
288288
patch_feature_section(0, &fixup);
289-
check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0);
289+
check(memcmp(ftr_fixup_test2, ftr_fixup_test2_expected, size) == 0);
290290

291291
/* Check we do patch if the mask doesn't match */
292-
memcpy(&ftr_fixup_test2, &ftr_fixup_test2_orig, size);
293-
check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_orig, size) == 0);
292+
memcpy(ftr_fixup_test2, ftr_fixup_test2_orig, size);
293+
check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
294294
patch_feature_section(~0xF, &fixup);
295-
check(memcmp(&ftr_fixup_test2, &ftr_fixup_test2_expected, size) == 0);
295+
check(memcmp(ftr_fixup_test2, ftr_fixup_test2_expected, size) == 0);
296296
}
297297

298298
static void test_alternative_case_too_big(void)
299299
{
300-
extern unsigned int ftr_fixup_test3;
301-
extern unsigned int end_ftr_fixup_test3;
302-
extern unsigned int ftr_fixup_test3_orig;
303-
extern unsigned int ftr_fixup_test3_alt;
304-
int size = &end_ftr_fixup_test3 - &ftr_fixup_test3;
300+
extern unsigned int ftr_fixup_test3[];
301+
extern unsigned int end_ftr_fixup_test3[];
302+
extern unsigned int ftr_fixup_test3_orig[];
303+
extern unsigned int ftr_fixup_test3_alt[];
304+
int size = end_ftr_fixup_test3 - ftr_fixup_test3;
305305

306306
fixup.value = fixup.mask = 0xC;
307-
fixup.start_off = calc_offset(&fixup, &ftr_fixup_test3 + 1);
308-
fixup.end_off = calc_offset(&fixup, &ftr_fixup_test3 + 2);
309-
fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test3_alt);
310-
fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test3_alt + 2);
307+
fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1);
308+
fixup.end_off = calc_offset(&fixup, ftr_fixup_test3 + 2);
309+
fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test3_alt);
310+
fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test3_alt + 2);
311311

312312
/* Sanity check */
313-
check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0);
313+
check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
314314

315315
/* Expect nothing to be patched, and the error returned to us */
316316
check(patch_feature_section(0xF, &fixup) == 1);
317-
check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0);
317+
check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
318318
check(patch_feature_section(0, &fixup) == 1);
319-
check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0);
319+
check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
320320
check(patch_feature_section(~0xF, &fixup) == 1);
321-
check(memcmp(&ftr_fixup_test3, &ftr_fixup_test3_orig, size) == 0);
321+
check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
322322
}
323323

324324
static void test_alternative_case_too_small(void)
325325
{
326-
extern unsigned int ftr_fixup_test4;
327-
extern unsigned int end_ftr_fixup_test4;
328-
extern unsigned int ftr_fixup_test4_orig;
329-
extern unsigned int ftr_fixup_test4_alt;
330-
extern unsigned int ftr_fixup_test4_expected;
331-
int size = &end_ftr_fixup_test4 - &ftr_fixup_test4;
326+
extern unsigned int ftr_fixup_test4[];
327+
extern unsigned int end_ftr_fixup_test4[];
328+
extern unsigned int ftr_fixup_test4_orig[];
329+
extern unsigned int ftr_fixup_test4_alt[];
330+
extern unsigned int ftr_fixup_test4_expected[];
331+
int size = end_ftr_fixup_test4 - ftr_fixup_test4;
332332
unsigned long flag;
333333

334334
/* Check a high-bit flag */
335335
flag = 1UL << ((sizeof(unsigned long) - 1) * 8);
336336
fixup.value = fixup.mask = flag;
337-
fixup.start_off = calc_offset(&fixup, &ftr_fixup_test4 + 1);
338-
fixup.end_off = calc_offset(&fixup, &ftr_fixup_test4 + 5);
339-
fixup.alt_start_off = calc_offset(&fixup, &ftr_fixup_test4_alt);
340-
fixup.alt_end_off = calc_offset(&fixup, &ftr_fixup_test4_alt + 2);
337+
fixup.start_off = calc_offset(&fixup, ftr_fixup_test4 + 1);
338+
fixup.end_off = calc_offset(&fixup, ftr_fixup_test4 + 5);
339+
fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test4_alt);
340+
fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test4_alt + 2);
341341

342342
/* Sanity check */
343-
check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0);
343+
check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
344344

345345
/* Check we don't patch if the value matches */
346346
patch_feature_section(flag, &fixup);
347-
check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0);
347+
check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
348348

349349
/* Check we do patch if the value doesn't match */
350350
patch_feature_section(0, &fixup);
351-
check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0);
351+
check(memcmp(ftr_fixup_test4, ftr_fixup_test4_expected, size) == 0);
352352

353353
/* Check we do patch if the mask doesn't match */
354-
memcpy(&ftr_fixup_test4, &ftr_fixup_test4_orig, size);
355-
check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_orig, size) == 0);
354+
memcpy(ftr_fixup_test4, ftr_fixup_test4_orig, size);
355+
check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
356356
patch_feature_section(~flag, &fixup);
357-
check(memcmp(&ftr_fixup_test4, &ftr_fixup_test4_expected, size) == 0);
357+
check(memcmp(ftr_fixup_test4, ftr_fixup_test4_expected, size) == 0);
358358
}
359359

360360
static void test_alternative_case_with_branch(void)
361361
{
362-
extern unsigned int ftr_fixup_test5;
363-
extern unsigned int end_ftr_fixup_test5;
364-
extern unsigned int ftr_fixup_test5_expected;
365-
int size = &end_ftr_fixup_test5 - &ftr_fixup_test5;
362+
extern unsigned int ftr_fixup_test5[];
363+
extern unsigned int end_ftr_fixup_test5[];
364+
extern unsigned int ftr_fixup_test5_expected[];
365+
int size = end_ftr_fixup_test5 - ftr_fixup_test5;
366366

367-
check(memcmp(&ftr_fixup_test5, &ftr_fixup_test5_expected, size) == 0);
367+
check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0);
368368
}
369369

370370
static void test_alternative_case_with_external_branch(void)
371371
{
372-
extern unsigned int ftr_fixup_test6;
373-
extern unsigned int end_ftr_fixup_test6;
374-
extern unsigned int ftr_fixup_test6_expected;
375-
int size = &end_ftr_fixup_test6 - &ftr_fixup_test6;
372+
extern unsigned int ftr_fixup_test6[];
373+
extern unsigned int end_ftr_fixup_test6[];
374+
extern unsigned int ftr_fixup_test6_expected[];
375+
int size = end_ftr_fixup_test6 - ftr_fixup_test6;
376376

377-
check(memcmp(&ftr_fixup_test6, &ftr_fixup_test6_expected, size) == 0);
377+
check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0);
378378
}
379379

380380
static void test_cpu_macros(void)
381381
{
382-
extern u8 ftr_fixup_test_FTR_macros;
383-
extern u8 ftr_fixup_test_FTR_macros_expected;
384-
unsigned long size = &ftr_fixup_test_FTR_macros_expected -
385-
&ftr_fixup_test_FTR_macros;
382+
extern u8 ftr_fixup_test_FTR_macros[];
383+
extern u8 ftr_fixup_test_FTR_macros_expected[];
384+
unsigned long size = ftr_fixup_test_FTR_macros_expected -
385+
ftr_fixup_test_FTR_macros;
386386

387387
/* The fixups have already been done for us during boot */
388-
check(memcmp(&ftr_fixup_test_FTR_macros,
389-
&ftr_fixup_test_FTR_macros_expected, size) == 0);
388+
check(memcmp(ftr_fixup_test_FTR_macros,
389+
ftr_fixup_test_FTR_macros_expected, size) == 0);
390390
}
391391

392392
static void test_fw_macros(void)
393393
{
394394
#ifdef CONFIG_PPC64
395-
extern u8 ftr_fixup_test_FW_FTR_macros;
396-
extern u8 ftr_fixup_test_FW_FTR_macros_expected;
397-
unsigned long size = &ftr_fixup_test_FW_FTR_macros_expected -
398-
&ftr_fixup_test_FW_FTR_macros;
395+
extern u8 ftr_fixup_test_FW_FTR_macros[];
396+
extern u8 ftr_fixup_test_FW_FTR_macros_expected[];
397+
unsigned long size = ftr_fixup_test_FW_FTR_macros_expected -
398+
ftr_fixup_test_FW_FTR_macros;
399399

400400
/* The fixups have already been done for us during boot */
401-
check(memcmp(&ftr_fixup_test_FW_FTR_macros,
402-
&ftr_fixup_test_FW_FTR_macros_expected, size) == 0);
401+
check(memcmp(ftr_fixup_test_FW_FTR_macros,
402+
ftr_fixup_test_FW_FTR_macros_expected, size) == 0);
403403
#endif
404404
}
405405

406406
static void test_lwsync_macros(void)
407407
{
408-
extern u8 lwsync_fixup_test;
409-
extern u8 end_lwsync_fixup_test;
410-
extern u8 lwsync_fixup_test_expected_LWSYNC;
411-
extern u8 lwsync_fixup_test_expected_SYNC;
412-
unsigned long size = &end_lwsync_fixup_test -
413-
&lwsync_fixup_test;
408+
extern u8 lwsync_fixup_test[];
409+
extern u8 end_lwsync_fixup_test[];
410+
extern u8 lwsync_fixup_test_expected_LWSYNC[];
411+
extern u8 lwsync_fixup_test_expected_SYNC[];
412+
unsigned long size = end_lwsync_fixup_test -
413+
lwsync_fixup_test;
414414

415415
/* The fixups have already been done for us during boot */
416416
if (cur_cpu_spec->cpu_features & CPU_FTR_LWSYNC) {
417-
check(memcmp(&lwsync_fixup_test,
418-
&lwsync_fixup_test_expected_LWSYNC, size) == 0);
417+
check(memcmp(lwsync_fixup_test,
418+
lwsync_fixup_test_expected_LWSYNC, size) == 0);
419419
} else {
420-
check(memcmp(&lwsync_fixup_test,
421-
&lwsync_fixup_test_expected_SYNC, size) == 0);
420+
check(memcmp(lwsync_fixup_test,
421+
lwsync_fixup_test_expected_SYNC, size) == 0);
422422
}
423423
}
424424

0 commit comments

Comments
 (0)