lkdtm/fortify: Consolidate FORTIFY_SOURCE tests
The FORTIFY_SOURCE tests were split between bugs.c and fortify.c. Move tests into fortify.c, standardize their naming, add CONFIG hints, and add them to the lkdtm selftests. Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20210818174855.2307828-3-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c75be56e35
commit
fe8e353bfd
@ -507,53 +507,3 @@ noinline void lkdtm_CORRUPT_PAC(void)
|
||||
pr_err("XFAIL: this test is arm64-only\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void lkdtm_FORTIFY_OBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
} target[2] = {};
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Using volatile prevents the compiler from determining the value of
|
||||
* 'size' at compile time. Without that, we would get a compile error
|
||||
* rather than a runtime error.
|
||||
*/
|
||||
volatile int size = 11;
|
||||
|
||||
pr_info("trying to read past the end of a struct\n");
|
||||
|
||||
result = memcmp(&target[0], &target[1], size);
|
||||
|
||||
/* Print result to prevent the code from being eliminated */
|
||||
pr_err("FAIL: fortify did not catch an object overread!\n"
|
||||
"\"%d\" was the memcmp result.\n", result);
|
||||
}
|
||||
|
||||
void lkdtm_FORTIFY_SUBOBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
char b[10];
|
||||
} target;
|
||||
char *src;
|
||||
|
||||
src = kmalloc(20, GFP_KERNEL);
|
||||
strscpy(src, "over ten bytes", 20);
|
||||
|
||||
pr_info("trying to strcpy past the end of a member of a struct\n");
|
||||
|
||||
/*
|
||||
* strncpy(target.a, src, 20); will hit a compile error because the
|
||||
* compiler knows at build time that target.a < 20 bytes. Use strcpy()
|
||||
* to force a runtime error.
|
||||
*/
|
||||
strcpy(target.a, src);
|
||||
|
||||
/* Use target.a to prevent the code from being eliminated */
|
||||
pr_err("FAIL: fortify did not catch an sub-object overrun!\n"
|
||||
"\"%s\" was copied.\n", target.a);
|
||||
|
||||
kfree(src);
|
||||
}
|
||||
|
@ -118,8 +118,6 @@ static const struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(UNSET_SMEP),
|
||||
CRASHTYPE(CORRUPT_PAC),
|
||||
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
|
||||
CRASHTYPE(FORTIFY_OBJECT),
|
||||
CRASHTYPE(FORTIFY_SUBOBJECT),
|
||||
CRASHTYPE(SLAB_LINEAR_OVERFLOW),
|
||||
CRASHTYPE(VMALLOC_LINEAR_OVERFLOW),
|
||||
CRASHTYPE(WRITE_AFTER_FREE),
|
||||
@ -179,6 +177,8 @@ static const struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(USERCOPY_KERNEL),
|
||||
CRASHTYPE(STACKLEAK_ERASING),
|
||||
CRASHTYPE(CFI_FORWARD_PROTO),
|
||||
CRASHTYPE(FORTIFIED_OBJECT),
|
||||
CRASHTYPE(FORTIFIED_SUBOBJECT),
|
||||
CRASHTYPE(FORTIFIED_STRSCPY),
|
||||
CRASHTYPE(DOUBLE_FAULT),
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
|
@ -8,6 +8,59 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static volatile int fortify_scratch_space;
|
||||
|
||||
void lkdtm_FORTIFIED_OBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
} target[2] = {};
|
||||
/*
|
||||
* Using volatile prevents the compiler from determining the value of
|
||||
* 'size' at compile time. Without that, we would get a compile error
|
||||
* rather than a runtime error.
|
||||
*/
|
||||
volatile int size = 11;
|
||||
|
||||
pr_info("trying to read past the end of a struct\n");
|
||||
|
||||
/* Store result to global to prevent the code from being eliminated */
|
||||
fortify_scratch_space = memcmp(&target[0], &target[1], size);
|
||||
|
||||
pr_err("FAIL: fortify did not block an object overread!\n");
|
||||
pr_expected_config(CONFIG_FORTIFY_SOURCE);
|
||||
}
|
||||
|
||||
void lkdtm_FORTIFIED_SUBOBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
char b[10];
|
||||
} target;
|
||||
volatile int size = 20;
|
||||
char *src;
|
||||
|
||||
src = kmalloc(size, GFP_KERNEL);
|
||||
strscpy(src, "over ten bytes", size);
|
||||
size = strlen(src) + 1;
|
||||
|
||||
pr_info("trying to strcpy past the end of a member of a struct\n");
|
||||
|
||||
/*
|
||||
* memcpy(target.a, src, 20); will hit a compile error because the
|
||||
* compiler knows at build time that target.a < 20 bytes. Use a
|
||||
* volatile to force a runtime error.
|
||||
*/
|
||||
memcpy(target.a, src, size);
|
||||
|
||||
/* Store result to global to prevent the code from being eliminated */
|
||||
fortify_scratch_space = target.a[3];
|
||||
|
||||
pr_err("FAIL: fortify did not block an sub-object overrun!\n");
|
||||
pr_expected_config(CONFIG_FORTIFY_SOURCE);
|
||||
|
||||
kfree(src);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls fortified strscpy to test that it returns the same result as vanilla
|
||||
|
@ -74,8 +74,6 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
|
||||
void lkdtm_UNSET_SMEP(void);
|
||||
void lkdtm_DOUBLE_FAULT(void);
|
||||
void lkdtm_CORRUPT_PAC(void);
|
||||
void lkdtm_FORTIFY_OBJECT(void);
|
||||
void lkdtm_FORTIFY_SUBOBJECT(void);
|
||||
|
||||
/* heap.c */
|
||||
void __init lkdtm_heap_init(void);
|
||||
@ -150,6 +148,8 @@ void lkdtm_STACKLEAK_ERASING(void);
|
||||
void lkdtm_CFI_FORWARD_PROTO(void);
|
||||
|
||||
/* fortify.c */
|
||||
void lkdtm_FORTIFIED_OBJECT(void);
|
||||
void lkdtm_FORTIFIED_SUBOBJECT(void);
|
||||
void lkdtm_FORTIFIED_STRSCPY(void);
|
||||
|
||||
/* powerpc.c */
|
||||
|
@ -73,4 +73,6 @@ USERCOPY_KERNEL
|
||||
STACKLEAK_ERASING OK: the rest of the thread stack is properly erased
|
||||
CFI_FORWARD_PROTO
|
||||
FORTIFIED_STRSCPY
|
||||
FORTIFIED_OBJECT
|
||||
FORTIFIED_SUBOBJECT
|
||||
PPC_SLB_MULTIHIT Recovered
|
||||
|
Loading…
x
Reference in New Issue
Block a user