mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
hardening updates for v6.16-rc1
- Update overflow helpers to ease refactoring of on-stack flex array instances (Gustavo A. R. Silva, Kees Cook) - lkdtm: Use SLAB_NO_MERGE instead of constructors (Harry Yoo) - Simplify CONFIG_CC_HAS_COUNTED_BY (Jan Hendrik Farr) - Disable u64 usercopy KUnit test on 32-bit SPARC (Thomas Weißschuh) - Add missed designated initializers now exposed by fixed randstruct (Nathan Chancellor, Kees Cook) - Document compilers versions for __builtin_dynamic_object_size - Remove ARM_SSP_PER_TASK GCC plugin - Fix GCC plugin randstruct, add selftests, and restore COMPILE_TEST builds - Kbuild: induce full rebuilds when dependencies change with GCC plugins, the Clang sanitizer .scl file, or the randstruct seed. - Kbuild: Switch from -Wvla to -Wvla-larger-than=1 - Correct several __nonstring uses for -Wunterminated-string-initialization -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCaDUq9gAKCRA2KwveOeQk u+ZCAQDhqpOE/yn5gfjyplIvaTtzj9CaW6g11AmPYrimJCuj3QD9G+0o35kzlXOw f0ZIj2U7LFNgbLos+20hQwhMFf1Zhgg= =OYzD -----END PGP SIGNATURE----- Merge tag 'hardening-v6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux Pull hardening updates from Kees Cook: - Update overflow helpers to ease refactoring of on-stack flex array instances (Gustavo A. R. Silva, Kees Cook) - lkdtm: Use SLAB_NO_MERGE instead of constructors (Harry Yoo) - Simplify CONFIG_CC_HAS_COUNTED_BY (Jan Hendrik Farr) - Disable u64 usercopy KUnit test on 32-bit SPARC (Thomas Weißschuh) - Add missed designated initializers now exposed by fixed randstruct (Nathan Chancellor, Kees Cook) - Document compilers versions for __builtin_dynamic_object_size - Remove ARM_SSP_PER_TASK GCC plugin - Fix GCC plugin randstruct, add selftests, and restore COMPILE_TEST builds - Kbuild: induce full rebuilds when dependencies change with GCC plugins, the Clang sanitizer .scl file, or the randstruct seed. - Kbuild: Switch from -Wvla to -Wvla-larger-than=1 - Correct several __nonstring uses for -Wunterminated-string-initialization * tag 'hardening-v6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (23 commits) Revert "hardening: Disable GCC randstruct for COMPILE_TEST" lib/tests: randstruct: Add deep function pointer layout test lib/tests: Add randstruct KUnit test randstruct: gcc-plugin: Remove bogus void member net: qede: Initialize qede_ll_ops with designated initializer scsi: qedf: Use designated initializer for struct qed_fcoe_cb_ops md/bcache: Mark __nonstring look-up table integer-wrap: Force full rebuild when .scl file changes randstruct: Force full rebuild when seed changes gcc-plugins: Force full rebuild when plugins change kbuild: Switch from -Wvla to -Wvla-larger-than=1 hardening: simplify CONFIG_CC_HAS_COUNTED_BY overflow: Fix direct struct member initialization in _DEFINE_FLEX() kunit/overflow: Add tests for STACK_FLEX_ARRAY_SIZE() helper overflow: Add STACK_FLEX_ARRAY_SIZE() helper input/joystick: magellan: Mark __nonstring look-up table const watchdog: exar: Shorten identity name to fit correctly mod_devicetable: Enlarge the maximum platform_device_id name length overflow: Clarify expectations for getting DEFINE_FLEX variable sizes compiler_types: Identify compiler versions for __builtin_dynamic_object_size ...
This commit is contained in:
commit
48cfc5791d
|
|
@ -12935,6 +12935,7 @@ F: include/linux/overflow.h
|
|||
F: include/linux/randomize_kstack.h
|
||||
F: include/linux/ucopysize.h
|
||||
F: kernel/configs/hardening.config
|
||||
F: lib/tests/randstruct_kunit.c
|
||||
F: lib/tests/usercopy_kunit.c
|
||||
F: mm/usercopy.c
|
||||
F: security/Kconfig.hardening
|
||||
|
|
|
|||
|
|
@ -1380,8 +1380,7 @@ config CC_HAVE_STACKPROTECTOR_TLS
|
|||
config STACKPROTECTOR_PER_TASK
|
||||
bool "Use a unique stack canary value for each task"
|
||||
depends on STACKPROTECTOR && CURRENT_POINTER_IN_TPIDRURO && !XIP_DEFLATED_DATA
|
||||
depends on GCC_PLUGINS || CC_HAVE_STACKPROTECTOR_TLS
|
||||
select GCC_PLUGIN_ARM_SSP_PER_TASK if !CC_HAVE_STACKPROTECTOR_TLS
|
||||
depends on CC_HAVE_STACKPROTECTOR_TLS
|
||||
default y
|
||||
help
|
||||
Due to the fact that GCC uses an ordinary symbol reference from
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
|
|||
|
||||
ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \
|
||||
-I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
|
||||
-I$(obj) $(DISABLE_ARM_SSP_PER_TASK_PLUGIN)
|
||||
-I$(obj)
|
||||
ccflags-remove-$(CONFIG_FUNCTION_TRACER) += -pg
|
||||
asflags-y := -DZIMAGE
|
||||
|
||||
|
|
|
|||
|
|
@ -545,7 +545,8 @@ static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid)
|
|||
|
||||
static struct uuid_entry *uuid_find_empty(struct cache_set *c)
|
||||
{
|
||||
static const char zero_uuid[16] = { 0 };
|
||||
static const char zero_uuid[16] __nonstring =
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
return uuid_find(c, zero_uuid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,23 +355,12 @@ static void lkdtm_SLAB_FREE_PAGE(void)
|
|||
free_page(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have constructors to keep the caches distinctly separated without
|
||||
* needing to boot with "slab_nomerge".
|
||||
*/
|
||||
static void ctor_double_free(void *region)
|
||||
{ }
|
||||
static void ctor_a(void *region)
|
||||
{ }
|
||||
static void ctor_b(void *region)
|
||||
{ }
|
||||
|
||||
void __init lkdtm_heap_init(void)
|
||||
{
|
||||
double_free_cache = kmem_cache_create("lkdtm-heap-double_free",
|
||||
64, 0, 0, ctor_double_free);
|
||||
a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a);
|
||||
b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b);
|
||||
64, 0, SLAB_NO_MERGE, NULL);
|
||||
a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, SLAB_NO_MERGE, NULL);
|
||||
b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, SLAB_NO_MERGE, NULL);
|
||||
}
|
||||
|
||||
void __exit lkdtm_heap_exit(void)
|
||||
|
|
|
|||
|
|
@ -699,7 +699,7 @@ static u32 qedf_get_login_failures(void *cookie)
|
|||
}
|
||||
|
||||
static struct qed_fcoe_cb_ops qedf_cb_ops = {
|
||||
{
|
||||
.common = {
|
||||
.link_update = qedf_link_update,
|
||||
.bw_update = qedf_bw_update,
|
||||
.schedule_recovery_handler = qedf_schedule_recovery_handler,
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ static const struct watchdog_info exar_wdt_info = {
|
|||
.options = WDIOF_KEEPALIVEPING |
|
||||
WDIOF_SETTIMEOUT |
|
||||
WDIOF_MAGICCLOSE,
|
||||
.identity = "Exar/MaxLinear XR28V38x Watchdog",
|
||||
.identity = "Exar XR28V38x Watchdog",
|
||||
};
|
||||
|
||||
static const struct watchdog_ops exar_wdt_ops = {
|
||||
|
|
|
|||
|
|
@ -12,3 +12,33 @@
|
|||
* and add dependency on include/config/CC_VERSION_TEXT, which is touched
|
||||
* by Kconfig when the version string from the compiler changes.
|
||||
*/
|
||||
|
||||
/* Additional tree-wide dependencies start here. */
|
||||
|
||||
/*
|
||||
* If any of the GCC plugins change, we need to rebuild everything that
|
||||
* was built with them, as they may have changed their behavior and those
|
||||
* behaviors may need to be synchronized across all translation units.
|
||||
*/
|
||||
#ifdef GCC_PLUGINS
|
||||
#include <generated/gcc-plugins.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the randstruct seed itself changes (whether for GCC plugins or
|
||||
* Clang), the entire tree needs to be rebuilt since the randomization of
|
||||
* structures may change between compilation units if not.
|
||||
*/
|
||||
#ifdef RANDSTRUCT
|
||||
#include <generated/randstruct_hash.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If any external changes affect Clang's integer wrapping sanitizer
|
||||
* behavior, a full rebuild is needed as the coverage for wrapping types
|
||||
* may have changed, which may impact the expected behaviors that should
|
||||
* not differ between compilation units.
|
||||
*/
|
||||
#ifdef INTEGER_WRAP
|
||||
#include <generated/integer-wrap.h>
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -449,6 +449,11 @@ struct ftrace_likely_data {
|
|||
/*
|
||||
* When the size of an allocated object is needed, use the best available
|
||||
* mechanism to find it. (For cases where sizeof() cannot be used.)
|
||||
*
|
||||
* Optional: only supported since gcc >= 12
|
||||
*
|
||||
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
|
||||
* clang: https://clang.llvm.org/docs/LanguageExtensions.html#evaluating-object-size
|
||||
*/
|
||||
#if __has_builtin(__builtin_dynamic_object_size)
|
||||
#define __struct_size(p) __builtin_dynamic_object_size(p, 0)
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ struct dmi_system_id {
|
|||
#define DMI_MATCH(a, b) { .slot = a, .substr = b }
|
||||
#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 }
|
||||
|
||||
#define PLATFORM_NAME_SIZE 20
|
||||
#define PLATFORM_NAME_SIZE 24
|
||||
#define PLATFORM_MODULE_PREFIX "platform:"
|
||||
|
||||
struct platform_device_id {
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
|
|||
* @name: Name for a variable to define.
|
||||
* @member: Name of the array member.
|
||||
* @count: Number of elements in the array; must be compile-time const.
|
||||
* @initializer: initializer expression (could be empty for no init).
|
||||
* @initializer: Initializer expression (e.g., pass `= { }` at minimum).
|
||||
*/
|
||||
#define _DEFINE_FLEX(type, name, member, count, initializer...) \
|
||||
_Static_assert(__builtin_constant_p(count), \
|
||||
|
|
@ -404,7 +404,7 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
|
|||
union { \
|
||||
u8 bytes[struct_size_t(type, member, count)]; \
|
||||
type obj; \
|
||||
} name##_u initializer; \
|
||||
} name##_u = { .obj initializer }; \
|
||||
type *name = (type *)&name##_u
|
||||
|
||||
/**
|
||||
|
|
@ -419,6 +419,9 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
|
|||
* Define a zeroed, on-stack, instance of @type structure with a trailing
|
||||
* flexible array member.
|
||||
* Use __struct_size(@name) to get compile-time size of it afterwards.
|
||||
* Use __member_size(@name->member) to get compile-time size of @name members.
|
||||
* Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
|
||||
* elements in array @member.
|
||||
*/
|
||||
#define DEFINE_RAW_FLEX(type, name, member, count) \
|
||||
_DEFINE_FLEX(type, name, member, count, = {})
|
||||
|
|
@ -436,8 +439,22 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
|
|||
* Define a zeroed, on-stack, instance of @TYPE structure with a trailing
|
||||
* flexible array member.
|
||||
* Use __struct_size(@NAME) to get compile-time size of it afterwards.
|
||||
* Use __member_size(@NAME->member) to get compile-time size of @NAME members.
|
||||
* Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
|
||||
* elements in array @member.
|
||||
*/
|
||||
#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT) \
|
||||
_DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .obj.COUNTER = COUNT, })
|
||||
_DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .COUNTER = COUNT, })
|
||||
|
||||
/**
|
||||
* STACK_FLEX_ARRAY_SIZE() - helper macro for DEFINE_FLEX() family.
|
||||
* Returns the number of elements in @array.
|
||||
*
|
||||
* @name: Name for a variable defined in DEFINE_RAW_FLEX()/DEFINE_FLEX().
|
||||
* @array: Name of the array member.
|
||||
*/
|
||||
#define STACK_FLEX_ARRAY_SIZE(name, array) \
|
||||
(__member_size((name)->array) / sizeof(*(name)->array) + \
|
||||
__must_be_array((name)->array))
|
||||
|
||||
#endif /* __LINUX_OVERFLOW_H */
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#define MODULE_VERMAGIC_MODVERSIONS ""
|
||||
#endif
|
||||
#ifdef RANDSTRUCT
|
||||
#include <generated/randstruct_hash.h>
|
||||
#define MODULE_RANDSTRUCT "RANDSTRUCT_" RANDSTRUCT_HASHED_SEED
|
||||
#else
|
||||
#define MODULE_RANDSTRUCT
|
||||
|
|
|
|||
|
|
@ -116,13 +116,14 @@ config CC_HAS_NO_PROFILE_FN_ATTR
|
|||
def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
|
||||
|
||||
config CC_HAS_COUNTED_BY
|
||||
# TODO: when gcc 15 is released remove the build test and add
|
||||
# a gcc version check
|
||||
def_bool $(success,echo 'struct flex { int count; int array[] __attribute__((__counted_by__(count))); };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
|
||||
bool
|
||||
# clang needs to be at least 19.1.3 to avoid __bdos miscalculations
|
||||
# https://github.com/llvm/llvm-project/pull/110497
|
||||
# https://github.com/llvm/llvm-project/pull/112636
|
||||
depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
|
||||
default y if CC_IS_CLANG && CLANG_VERSION >= 190103
|
||||
# supported since gcc 15.1.0
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
|
||||
default y if CC_IS_GCC && GCC_VERSION >= 150100
|
||||
|
||||
config CC_HAS_MULTIDIMENSIONAL_NONSTRING
|
||||
def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
|
||||
|
|
|
|||
|
|
@ -2863,6 +2863,14 @@ config OVERFLOW_KUNIT_TEST
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config RANDSTRUCT_KUNIT_TEST
|
||||
tristate "Test randstruct structure layout randomization at runtime" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Builds unit tests for the checking CONFIG_RANDSTRUCT=y, which
|
||||
randomizes structure layouts.
|
||||
|
||||
config STACKINIT_KUNIT_TEST
|
||||
tristate "Test level of stack variable initialization" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ CFLAGS_test_bitops.o += -Werror
|
|||
obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
|
||||
obj-$(CONFIG_TEST_IDA) += test_ida.o
|
||||
obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
|
||||
CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)
|
||||
CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable)
|
||||
UBSAN_SANITIZE_test_ubsan.o := y
|
||||
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
|
|||
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
|
||||
obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
|
||||
obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
|
||||
obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o
|
||||
obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
|
||||
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
|
||||
obj-$(CONFIG_SLUB_KUNIT_TEST) += slub_kunit.o
|
||||
|
|
|
|||
|
|
@ -1210,6 +1210,10 @@ static void DEFINE_FLEX_test(struct kunit *test)
|
|||
KUNIT_EXPECT_EQ(test, __struct_size(empty->array), 0);
|
||||
KUNIT_EXPECT_EQ(test, __member_size(empty->array), 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, STACK_FLEX_ARRAY_SIZE(two, array), 2);
|
||||
KUNIT_EXPECT_EQ(test, STACK_FLEX_ARRAY_SIZE(eight, array), 8);
|
||||
KUNIT_EXPECT_EQ(test, STACK_FLEX_ARRAY_SIZE(empty, array), 0);
|
||||
|
||||
/* If __counted_by is not being used, array size will have the on-stack size. */
|
||||
if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
|
||||
array_size_override = 2 * sizeof(s16);
|
||||
|
|
|
|||
334
lib/tests/randstruct_kunit.c
Normal file
334
lib/tests/randstruct_kunit.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Test cases for struct randomization, i.e. CONFIG_RANDSTRUCT=y.
|
||||
*
|
||||
* For example, see:
|
||||
* "Running tests with kunit_tool" at Documentation/dev-tools/kunit/start.rst
|
||||
* ./tools/testing/kunit/kunit.py run randstruct [--raw_output] \
|
||||
* [--make_option LLVM=1] \
|
||||
* --kconfig_add CONFIG_RANDSTRUCT_FULL=y
|
||||
*
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define DO_MANY_MEMBERS(macro, args...) \
|
||||
macro(a, args) \
|
||||
macro(b, args) \
|
||||
macro(c, args) \
|
||||
macro(d, args) \
|
||||
macro(e, args) \
|
||||
macro(f, args) \
|
||||
macro(g, args) \
|
||||
macro(h, args)
|
||||
|
||||
#define do_enum(x, ignored) MEMBER_NAME_ ## x,
|
||||
enum randstruct_member_names {
|
||||
DO_MANY_MEMBERS(do_enum)
|
||||
MEMBER_NAME_MAX,
|
||||
};
|
||||
/* Make sure the macros are working: want 8 test members. */
|
||||
_Static_assert(MEMBER_NAME_MAX == 8, "Number of test members changed?!");
|
||||
|
||||
/* This is an unsigned long member to match the function pointer size */
|
||||
#define unsigned_long_member(x, ignored) unsigned long x;
|
||||
struct randstruct_untouched {
|
||||
DO_MANY_MEMBERS(unsigned_long_member)
|
||||
};
|
||||
|
||||
/* Struct explicitly marked with __randomize_layout. */
|
||||
struct randstruct_shuffled {
|
||||
DO_MANY_MEMBERS(unsigned_long_member)
|
||||
} __randomize_layout;
|
||||
#undef unsigned_long_member
|
||||
|
||||
/* Struct implicitly randomized from being all func ptrs. */
|
||||
#define func_member(x, ignored) size_t (*x)(int);
|
||||
struct randstruct_funcs_untouched {
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
} __no_randomize_layout;
|
||||
|
||||
struct randstruct_funcs_shuffled {
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
};
|
||||
|
||||
#define func_body(x, ignored) \
|
||||
static noinline size_t func_##x(int arg) \
|
||||
{ \
|
||||
return offsetof(struct randstruct_funcs_untouched, x); \
|
||||
}
|
||||
DO_MANY_MEMBERS(func_body)
|
||||
|
||||
/* Various mixed types. */
|
||||
#define mixed_members \
|
||||
bool a; \
|
||||
short b; \
|
||||
unsigned int c __aligned(16); \
|
||||
size_t d; \
|
||||
char e; \
|
||||
u64 f; \
|
||||
union { \
|
||||
struct randstruct_shuffled shuffled; \
|
||||
uintptr_t g; \
|
||||
}; \
|
||||
union { \
|
||||
void *ptr; \
|
||||
char h; \
|
||||
};
|
||||
|
||||
struct randstruct_mixed_untouched {
|
||||
mixed_members
|
||||
};
|
||||
|
||||
struct randstruct_mixed_shuffled {
|
||||
mixed_members
|
||||
} __randomize_layout;
|
||||
#undef mixed_members
|
||||
|
||||
struct contains_randstruct_untouched {
|
||||
int before;
|
||||
struct randstruct_untouched untouched;
|
||||
int after;
|
||||
};
|
||||
|
||||
struct contains_randstruct_shuffled {
|
||||
int before;
|
||||
struct randstruct_shuffled shuffled;
|
||||
int after;
|
||||
};
|
||||
|
||||
struct contains_func_untouched {
|
||||
struct randstruct_funcs_shuffled inner;
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
} __no_randomize_layout;
|
||||
|
||||
struct contains_func_shuffled {
|
||||
struct randstruct_funcs_shuffled inner;
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
};
|
||||
#undef func_member
|
||||
|
||||
#define check_mismatch(x, untouched, shuffled) \
|
||||
if (offsetof(untouched, x) != offsetof(shuffled, x)) \
|
||||
mismatches++; \
|
||||
kunit_info(test, #shuffled "::" #x " @ %zu (vs %zu)\n", \
|
||||
offsetof(shuffled, x), \
|
||||
offsetof(untouched, x)); \
|
||||
|
||||
#define check_pair(outcome, untouched, shuffled, checker...) \
|
||||
mismatches = 0; \
|
||||
DO_MANY_MEMBERS(checker, untouched, shuffled) \
|
||||
kunit_info(test, "Differing " #untouched " vs " #shuffled " member positions: %d\n", \
|
||||
mismatches); \
|
||||
KUNIT_##outcome##_MSG(test, mismatches, 0, \
|
||||
#untouched " vs " #shuffled " layouts: unlucky or broken?\n");
|
||||
|
||||
static void randstruct_layout_same(struct kunit *test)
|
||||
{
|
||||
int mismatches;
|
||||
|
||||
check_pair(EXPECT_EQ, struct randstruct_untouched, struct randstruct_untouched,
|
||||
check_mismatch)
|
||||
check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_shuffled,
|
||||
check_mismatch)
|
||||
}
|
||||
|
||||
static void randstruct_layout_mixed(struct kunit *test)
|
||||
{
|
||||
int mismatches;
|
||||
|
||||
check_pair(EXPECT_EQ, struct randstruct_mixed_untouched, struct randstruct_mixed_untouched,
|
||||
check_mismatch)
|
||||
check_pair(EXPECT_GT, struct randstruct_mixed_untouched, struct randstruct_mixed_shuffled,
|
||||
check_mismatch)
|
||||
}
|
||||
|
||||
static void randstruct_layout_fptr(struct kunit *test)
|
||||
{
|
||||
int mismatches;
|
||||
|
||||
check_pair(EXPECT_EQ, struct randstruct_untouched, struct randstruct_untouched,
|
||||
check_mismatch)
|
||||
check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_funcs_shuffled,
|
||||
check_mismatch)
|
||||
check_pair(EXPECT_GT, struct randstruct_funcs_untouched, struct randstruct_funcs_shuffled,
|
||||
check_mismatch)
|
||||
}
|
||||
|
||||
#define check_mismatch_prefixed(x, prefix, untouched, shuffled) \
|
||||
check_mismatch(prefix.x, untouched, shuffled)
|
||||
|
||||
static void randstruct_layout_fptr_deep(struct kunit *test)
|
||||
{
|
||||
int mismatches;
|
||||
|
||||
if (IS_ENABLED(CONFIG_CC_IS_CLANG))
|
||||
kunit_skip(test, "Clang randstruct misses inner functions: https://github.com/llvm/llvm-project/issues/138355");
|
||||
|
||||
check_pair(EXPECT_EQ, struct contains_func_untouched, struct contains_func_untouched,
|
||||
check_mismatch_prefixed, inner)
|
||||
|
||||
check_pair(EXPECT_GT, struct contains_func_untouched, struct contains_func_shuffled,
|
||||
check_mismatch_prefixed, inner)
|
||||
}
|
||||
|
||||
#undef check_pair
|
||||
#undef check_mismatch
|
||||
|
||||
#define check_mismatch(x, ignore) \
|
||||
KUNIT_EXPECT_EQ_MSG(test, untouched->x, shuffled->x, \
|
||||
"Mismatched member value in %s initializer\n", \
|
||||
name);
|
||||
|
||||
static void test_check_init(struct kunit *test, const char *name,
|
||||
struct randstruct_untouched *untouched,
|
||||
struct randstruct_shuffled *shuffled)
|
||||
{
|
||||
DO_MANY_MEMBERS(check_mismatch)
|
||||
}
|
||||
|
||||
static void test_check_mixed_init(struct kunit *test, const char *name,
|
||||
struct randstruct_mixed_untouched *untouched,
|
||||
struct randstruct_mixed_shuffled *shuffled)
|
||||
{
|
||||
DO_MANY_MEMBERS(check_mismatch)
|
||||
}
|
||||
#undef check_mismatch
|
||||
|
||||
#define check_mismatch(x, ignore) \
|
||||
KUNIT_EXPECT_EQ_MSG(test, untouched->untouched.x, \
|
||||
shuffled->shuffled.x, \
|
||||
"Mismatched member value in %s initializer\n", \
|
||||
name);
|
||||
static void test_check_contained_init(struct kunit *test, const char *name,
|
||||
struct contains_randstruct_untouched *untouched,
|
||||
struct contains_randstruct_shuffled *shuffled)
|
||||
{
|
||||
DO_MANY_MEMBERS(check_mismatch)
|
||||
}
|
||||
#undef check_mismatch
|
||||
|
||||
#define check_mismatch(x, ignore) \
|
||||
KUNIT_EXPECT_PTR_EQ_MSG(test, untouched->x, shuffled->x, \
|
||||
"Mismatched member value in %s initializer\n", \
|
||||
name);
|
||||
|
||||
static void test_check_funcs_init(struct kunit *test, const char *name,
|
||||
struct randstruct_funcs_untouched *untouched,
|
||||
struct randstruct_funcs_shuffled *shuffled)
|
||||
{
|
||||
DO_MANY_MEMBERS(check_mismatch)
|
||||
}
|
||||
#undef check_mismatch
|
||||
|
||||
static void randstruct_initializers(struct kunit *test)
|
||||
{
|
||||
#define init_members \
|
||||
.a = 1, \
|
||||
.b = 3, \
|
||||
.c = 5, \
|
||||
.d = 7, \
|
||||
.e = 11, \
|
||||
.f = 13, \
|
||||
.g = 17, \
|
||||
.h = 19,
|
||||
struct randstruct_untouched untouched = {
|
||||
init_members
|
||||
};
|
||||
struct randstruct_shuffled shuffled = {
|
||||
init_members
|
||||
};
|
||||
struct randstruct_mixed_untouched mixed_untouched = {
|
||||
init_members
|
||||
};
|
||||
struct randstruct_mixed_shuffled mixed_shuffled = {
|
||||
init_members
|
||||
};
|
||||
struct contains_randstruct_untouched contains_untouched = {
|
||||
.untouched = {
|
||||
init_members
|
||||
},
|
||||
};
|
||||
struct contains_randstruct_shuffled contains_shuffled = {
|
||||
.shuffled = {
|
||||
init_members
|
||||
},
|
||||
};
|
||||
#define func_member(x, ignored) \
|
||||
.x = func_##x,
|
||||
struct randstruct_funcs_untouched funcs_untouched = {
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
};
|
||||
struct randstruct_funcs_shuffled funcs_shuffled = {
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
};
|
||||
|
||||
test_check_init(test, "named", &untouched, &shuffled);
|
||||
test_check_init(test, "unnamed", &untouched,
|
||||
&(struct randstruct_shuffled){
|
||||
init_members
|
||||
});
|
||||
|
||||
test_check_contained_init(test, "named", &contains_untouched, &contains_shuffled);
|
||||
test_check_contained_init(test, "unnamed", &contains_untouched,
|
||||
&(struct contains_randstruct_shuffled){
|
||||
.shuffled = (struct randstruct_shuffled){
|
||||
init_members
|
||||
},
|
||||
});
|
||||
|
||||
test_check_contained_init(test, "named", &contains_untouched, &contains_shuffled);
|
||||
test_check_contained_init(test, "unnamed copy", &contains_untouched,
|
||||
&(struct contains_randstruct_shuffled){
|
||||
/* full struct copy initializer */
|
||||
.shuffled = shuffled,
|
||||
});
|
||||
|
||||
test_check_mixed_init(test, "named", &mixed_untouched, &mixed_shuffled);
|
||||
test_check_mixed_init(test, "unnamed", &mixed_untouched,
|
||||
&(struct randstruct_mixed_shuffled){
|
||||
init_members
|
||||
});
|
||||
|
||||
test_check_funcs_init(test, "named", &funcs_untouched, &funcs_shuffled);
|
||||
test_check_funcs_init(test, "unnamed", &funcs_untouched,
|
||||
&(struct randstruct_funcs_shuffled){
|
||||
DO_MANY_MEMBERS(func_member)
|
||||
});
|
||||
|
||||
#undef func_member
|
||||
#undef init_members
|
||||
}
|
||||
|
||||
static int randstruct_test_init(struct kunit *test)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_RANDSTRUCT))
|
||||
kunit_skip(test, "Not built with CONFIG_RANDSTRUCT=y");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct kunit_case randstruct_test_cases[] = {
|
||||
KUNIT_CASE(randstruct_layout_same),
|
||||
KUNIT_CASE(randstruct_layout_mixed),
|
||||
KUNIT_CASE(randstruct_layout_fptr),
|
||||
KUNIT_CASE(randstruct_layout_fptr_deep),
|
||||
KUNIT_CASE(randstruct_initializers),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite randstruct_test_suite = {
|
||||
.name = "randstruct",
|
||||
.init = randstruct_test_init,
|
||||
.test_cases = randstruct_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&randstruct_test_suite);
|
||||
|
||||
MODULE_DESCRIPTION("Test cases for struct randomization");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
!defined(CONFIG_MICROBLAZE) && \
|
||||
!defined(CONFIG_NIOS2) && \
|
||||
!defined(CONFIG_PPC32) && \
|
||||
!defined(CONFIG_SPARC32) && \
|
||||
!defined(CONFIG_SUPERH))
|
||||
# define TEST_U64
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ CFLAGS_shadow.o := $(CC_FLAGS_KASAN_RUNTIME)
|
|||
CFLAGS_hw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
|
||||
CFLAGS_sw_tags.o := $(CC_FLAGS_KASAN_RUNTIME)
|
||||
|
||||
CFLAGS_KASAN_TEST := $(CFLAGS_KASAN) $(call cc-disable-warning, vla)
|
||||
CFLAGS_KASAN_TEST := $(CFLAGS_KASAN)
|
||||
ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
|
||||
# If compiler instruments memintrinsics by prefixing them with __asan/__hwasan,
|
||||
# we need to treat them normally (as builtins), otherwise the compiler won't
|
||||
|
|
@ -44,6 +44,7 @@ ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
|
|||
CFLAGS_KASAN_TEST += -fno-builtin
|
||||
endif
|
||||
|
||||
CFLAGS_REMOVE_kasan_test_c.o += $(call cc-option, -Wvla-larger-than=1)
|
||||
CFLAGS_kasan_test_c.o := $(CFLAGS_KASAN_TEST)
|
||||
RUSTFLAGS_kasan_test_rust.o := $(RUSTFLAGS_KASAN)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,8 +58,13 @@ endif
|
|||
# These result in bogus false positives
|
||||
KBUILD_CFLAGS += $(call cc-option, -Wno-dangling-pointer)
|
||||
|
||||
# Variable Length Arrays (VLAs) should not be used anywhere in the kernel
|
||||
KBUILD_CFLAGS += -Wvla
|
||||
# Stack Variable Length Arrays (VLAs) must not be used in the kernel.
|
||||
# Function array parameters should, however, be usable, but -Wvla will
|
||||
# warn for those. Clang has no way yet to distinguish between the VLA
|
||||
# types, so depend on GCC for now to keep stack VLAs out of the tree.
|
||||
# https://github.com/llvm/llvm-project/issues/57098
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98217
|
||||
KBUILD_CFLAGS += $(call cc-option,-Wvla-larger-than=1)
|
||||
|
||||
# disable pointer signed / unsigned warnings in gcc 4.0
|
||||
KBUILD_CFLAGS += -Wno-pointer-sign
|
||||
|
|
|
|||
|
|
@ -36,15 +36,9 @@ ifdef CONFIG_GCC_PLUGIN_STACKLEAK
|
|||
endif
|
||||
export DISABLE_STACKLEAK_PLUGIN
|
||||
|
||||
gcc-plugin-$(CONFIG_GCC_PLUGIN_ARM_SSP_PER_TASK) += arm_ssp_per_task_plugin.so
|
||||
ifdef CONFIG_GCC_PLUGIN_ARM_SSP_PER_TASK
|
||||
DISABLE_ARM_SSP_PER_TASK_PLUGIN += -fplugin-arg-arm_ssp_per_task_plugin-disable
|
||||
endif
|
||||
export DISABLE_ARM_SSP_PER_TASK_PLUGIN
|
||||
|
||||
# All the plugin CFLAGS are collected here in case a build target needs to
|
||||
# filter them out of the KBUILD_CFLAGS.
|
||||
GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
|
||||
GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) -DGCC_PLUGINS
|
||||
export GCC_PLUGINS_CFLAGS
|
||||
|
||||
# Add the flags to the build!
|
||||
|
|
|
|||
|
|
@ -296,6 +296,19 @@ $(foreach m, $1, \
|
|||
$(addprefix $(obj)/, $(call suffix-search, $(patsubst $(obj)/%,%,$m), $2, $3))))
|
||||
endef
|
||||
|
||||
# Remove ".." and "." from a path, without using "realpath"
|
||||
# Usage:
|
||||
# $(call normalize_path,path/to/../file)
|
||||
define normalize_path
|
||||
$(strip $(eval elements :=) \
|
||||
$(foreach elem,$(subst /, ,$1), \
|
||||
$(if $(filter-out .,$(elem)), \
|
||||
$(if $(filter ..,$(elem)), \
|
||||
$(eval elements := $(wordlist 2,$(words $(elements)),x $(elements))), \
|
||||
$(eval elements := $(elements) $(elem))))) \
|
||||
$(subst $(space),/,$(elements)))
|
||||
endef
|
||||
|
||||
# Build commands
|
||||
# ===========================================================================
|
||||
# These are shared by some Makefile.* files.
|
||||
|
|
@ -343,6 +356,11 @@ quiet_cmd_copy = COPY $@
|
|||
$(obj)/%: $(src)/%_shipped
|
||||
$(call cmd,copy)
|
||||
|
||||
# Touch a file
|
||||
# ===========================================================================
|
||||
quiet_cmd_touch = TOUCH $(call normalize_path,$@)
|
||||
cmd_touch = touch $@
|
||||
|
||||
# Commands useful for building a boot image
|
||||
# ===========================================================================
|
||||
#
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ ubsan-cflags-$(CONFIG_UBSAN_TRAP) += $(call cc-option,-fsanitize-trap=undefined
|
|||
export CFLAGS_UBSAN := $(ubsan-cflags-y)
|
||||
|
||||
ubsan-integer-wrap-cflags-$(CONFIG_UBSAN_INTEGER_WRAP) += \
|
||||
-DINTEGER_WRAP \
|
||||
-fsanitize-undefined-ignore-overflow-pattern=all \
|
||||
-fsanitize=signed-integer-overflow \
|
||||
-fsanitize=unsigned-integer-overflow \
|
||||
|
|
|
|||
|
|
@ -14,3 +14,8 @@ cmd_create_randstruct_seed = \
|
|||
$(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
|
||||
$(call if_changed,create_randstruct_seed)
|
||||
always-$(CONFIG_RANDSTRUCT) += randstruct.seed
|
||||
|
||||
# integer-wrap: if the .scl file changes, we need to do a full rebuild.
|
||||
$(obj)/../../include/generated/integer-wrap.h: $(srctree)/scripts/integer-wrap-ignore.scl FORCE
|
||||
$(call if_changed,touch)
|
||||
always-$(CONFIG_UBSAN_INTEGER_WRAP) += ../../include/generated/integer-wrap.h
|
||||
|
|
|
|||
|
|
@ -46,8 +46,4 @@ config GCC_PLUGIN_LATENT_ENTROPY
|
|||
* https://grsecurity.net/
|
||||
* https://pax.grsecurity.net/
|
||||
|
||||
config GCC_PLUGIN_ARM_SSP_PER_TASK
|
||||
bool
|
||||
depends on GCC_PLUGINS && ARM
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -66,3 +66,7 @@ quiet_cmd_plugin_cxx_o_c = HOSTCXX $@
|
|||
|
||||
$(plugin-objs): $(obj)/%.o: $(src)/%.c FORCE
|
||||
$(call if_changed_dep,plugin_cxx_o_c)
|
||||
|
||||
$(obj)/../../include/generated/gcc-plugins.h: $(plugin-single) $(plugin-multi) FORCE
|
||||
$(call if_changed,touch)
|
||||
always-y += ../../include/generated/gcc-plugins.h
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "gcc-common.h"
|
||||
|
||||
__visible int plugin_is_GPL_compatible;
|
||||
|
||||
static unsigned int canary_offset;
|
||||
|
||||
static unsigned int arm_pertask_ssp_rtl_execute(void)
|
||||
{
|
||||
rtx_insn *insn;
|
||||
|
||||
for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
|
||||
const char *sym;
|
||||
rtx body;
|
||||
rtx current;
|
||||
|
||||
/*
|
||||
* Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
|
||||
*/
|
||||
if (!INSN_P(insn))
|
||||
continue;
|
||||
body = PATTERN(insn);
|
||||
if (GET_CODE(body) != SET ||
|
||||
GET_CODE(SET_SRC(body)) != SYMBOL_REF)
|
||||
continue;
|
||||
sym = XSTR(SET_SRC(body), 0);
|
||||
if (strcmp(sym, "__stack_chk_guard"))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Replace the source of the SET insn with an expression that
|
||||
* produces the address of the current task's stack canary value
|
||||
*/
|
||||
current = gen_reg_rtx(Pmode);
|
||||
|
||||
emit_insn_before(gen_load_tp_hard(current), insn);
|
||||
|
||||
SET_SRC(body) = gen_rtx_PLUS(Pmode, current,
|
||||
GEN_INT(canary_offset));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PASS_NAME arm_pertask_ssp_rtl
|
||||
|
||||
#define NO_GATE
|
||||
#include "gcc-generate-rtl-pass.h"
|
||||
|
||||
#if BUILDING_GCC_VERSION >= 9000
|
||||
static bool no(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
|
||||
{
|
||||
targetm.have_stack_protect_combined_set = no;
|
||||
targetm.have_stack_protect_combined_test = no;
|
||||
}
|
||||
#endif
|
||||
|
||||
__visible int plugin_init(struct plugin_name_args *plugin_info,
|
||||
struct plugin_gcc_version *version)
|
||||
{
|
||||
const char * const plugin_name = plugin_info->base_name;
|
||||
const int argc = plugin_info->argc;
|
||||
const struct plugin_argument *argv = plugin_info->argv;
|
||||
int i;
|
||||
|
||||
if (!plugin_default_version_check(version, &gcc_version)) {
|
||||
error(G_("incompatible gcc/plugin versions"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (!strcmp(argv[i].key, "disable"))
|
||||
return 0;
|
||||
|
||||
/* all remaining options require a value */
|
||||
if (!argv[i].value) {
|
||||
error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
|
||||
plugin_name, argv[i].key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i].key, "offset")) {
|
||||
canary_offset = atoi(argv[i].value);
|
||||
continue;
|
||||
}
|
||||
error(G_("unknown option '-fplugin-arg-%s-%s'"),
|
||||
plugin_name, argv[i].key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
|
||||
|
||||
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
|
||||
NULL, &arm_pertask_ssp_rtl_pass_info);
|
||||
|
||||
#if BUILDING_GCC_VERSION >= 9000
|
||||
register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
|
||||
arm_pertask_ssp_start_unit, NULL);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -344,29 +344,13 @@ static int relayout_struct(tree type)
|
|||
|
||||
shuffle(type, (tree *)newtree, shuffle_length);
|
||||
|
||||
/*
|
||||
* set up a bogus anonymous struct field designed to error out on unnamed struct initializers
|
||||
* as gcc provides no other way to detect such code
|
||||
*/
|
||||
list = make_node(FIELD_DECL);
|
||||
TREE_CHAIN(list) = newtree[0];
|
||||
TREE_TYPE(list) = void_type_node;
|
||||
DECL_SIZE(list) = bitsize_zero_node;
|
||||
DECL_NONADDRESSABLE_P(list) = 1;
|
||||
DECL_FIELD_BIT_OFFSET(list) = bitsize_zero_node;
|
||||
DECL_SIZE_UNIT(list) = size_zero_node;
|
||||
DECL_FIELD_OFFSET(list) = size_zero_node;
|
||||
DECL_CONTEXT(list) = type;
|
||||
// to satisfy the constify plugin
|
||||
TREE_READONLY(list) = 1;
|
||||
|
||||
for (i = 0; i < num_fields - 1; i++)
|
||||
TREE_CHAIN(newtree[i]) = newtree[i+1];
|
||||
TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
|
||||
|
||||
main_variant = TYPE_MAIN_VARIANT(type);
|
||||
for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
|
||||
TYPE_FIELDS(variant) = list;
|
||||
TYPE_FIELDS(variant) = newtree[0];
|
||||
TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
|
||||
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
|
||||
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ config CC_HAS_RANDSTRUCT
|
|||
|
||||
choice
|
||||
prompt "Randomize layout of sensitive kernel structures"
|
||||
default RANDSTRUCT_FULL if COMPILE_TEST && CC_HAS_RANDSTRUCT
|
||||
default RANDSTRUCT_FULL if COMPILE_TEST && (GCC_PLUGINS || CC_HAS_RANDSTRUCT)
|
||||
default RANDSTRUCT_NONE
|
||||
help
|
||||
If you enable this, the layouts of structures that are entirely
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user