diff options
| author | Kees Cook <keescook@chromium.org> | 2017-07-05 00:41:31 -0400 |
|---|---|---|
| committer | Kees Cook <keescook@chromium.org> | 2017-07-05 00:41:31 -0400 |
| commit | d1185a8c5dd21182012e6dd531b00fd72f4d30cb (patch) | |
| tree | 1c394d6e27bad00e0f3aba4e59ca19823d0486d5 /scripts | |
| parent | 6f7da290413ba713f0cdd9ff1a2a9bb129ef4f6c (diff) | |
| parent | 03232e0ddebdc2c9d088e6748075704885f039a5 (diff) | |
Merge branch 'merge/randstruct' into for-next/gcc-plugins
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Makefile.gcc-plugins | 4 | ||||
| -rw-r--r-- | scripts/gcc-plugins/.gitignore | 1 | ||||
| -rw-r--r-- | scripts/gcc-plugins/Makefile | 8 | ||||
| -rw-r--r-- | scripts/gcc-plugins/gcc-common.h | 12 | ||||
| -rw-r--r-- | scripts/gcc-plugins/gen-random-seed.sh | 8 | ||||
| -rw-r--r-- | scripts/gcc-plugins/randomize_layout_plugin.c | 1028 |
6 files changed, 1061 insertions, 0 deletions
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 82335533620e..2e0e2eaa397f 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins | |||
| @@ -29,6 +29,10 @@ ifdef CONFIG_GCC_PLUGINS | |||
| 29 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose | 29 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose |
| 30 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN | 30 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN |
| 31 | 31 | ||
| 32 | gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so | ||
| 33 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += -DRANDSTRUCT_PLUGIN | ||
| 34 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) += -fplugin-arg-randomize_layout_plugin-performance-mode | ||
| 35 | |||
| 32 | GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) | 36 | GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) |
| 33 | 37 | ||
| 34 | export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR | 38 | export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR |
diff --git a/scripts/gcc-plugins/.gitignore b/scripts/gcc-plugins/.gitignore new file mode 100644 index 000000000000..de92ed9e3d83 --- /dev/null +++ b/scripts/gcc-plugins/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| randomize_layout_seed.h | |||
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 8b29dc17c73c..214eb2335c31 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile | |||
| @@ -18,6 +18,14 @@ endif | |||
| 18 | 18 | ||
| 19 | export HOSTLIBS | 19 | export HOSTLIBS |
| 20 | 20 | ||
| 21 | $(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h | ||
| 22 | quiet_cmd_create_randomize_layout_seed = GENSEED $@ | ||
| 23 | cmd_create_randomize_layout_seed = \ | ||
| 24 | $(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h | ||
| 25 | $(objtree)/$(obj)/randomize_layout_seed.h: FORCE | ||
| 26 | $(call if_changed,create_randomize_layout_seed) | ||
| 27 | targets = randomize_layout_seed.h randomize_layout_hash.h | ||
| 28 | |||
| 21 | $(HOSTLIBS)-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p))) | 29 | $(HOSTLIBS)-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p))) |
| 22 | always := $($(HOSTLIBS)-y) | 30 | always := $($(HOSTLIBS)-y) |
| 23 | 31 | ||
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index b232ab15624c..6948898b3cdf 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h | |||
| @@ -63,6 +63,13 @@ | |||
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | #if BUILDING_GCC_VERSION >= 4006 | 65 | #if BUILDING_GCC_VERSION >= 4006 |
| 66 | /* | ||
| 67 | * The c-family headers were moved into a subdirectory in GCC version | ||
| 68 | * 4.7, but most plugin-building users of GCC 4.6 are using the Debian | ||
| 69 | * or Ubuntu package, which has an out-of-tree patch to move this to the | ||
| 70 | * same location as found in 4.7 and later: | ||
| 71 | * https://sources.debian.net/src/gcc-4.6/4.6.3-14/debian/patches/pr45078.diff/ | ||
| 72 | */ | ||
| 66 | #include "c-family/c-common.h" | 73 | #include "c-family/c-common.h" |
| 67 | #else | 74 | #else |
| 68 | #include "c-common.h" | 75 | #include "c-common.h" |
| @@ -946,4 +953,9 @@ static inline void debug_gimple_stmt(const_gimple s) | |||
| 946 | get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep) | 953 | get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep) |
| 947 | #endif | 954 | #endif |
| 948 | 955 | ||
| 956 | #if BUILDING_GCC_VERSION < 7000 | ||
| 957 | #define SET_DECL_ALIGN(decl, align) DECL_ALIGN(decl) = (align) | ||
| 958 | #define SET_DECL_MODE(decl, mode) DECL_MODE(decl) = (mode) | ||
| 959 | #endif | ||
| 960 | |||
| 949 | #endif | 961 | #endif |
diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh new file mode 100644 index 000000000000..7514850f4815 --- /dev/null +++ b/scripts/gcc-plugins/gen-random-seed.sh | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | if [ ! -f "$1" ]; then | ||
| 4 | SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'` | ||
| 5 | echo "const char *randstruct_seed = \"$SEED\";" > "$1" | ||
| 6 | HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'` | ||
| 7 | echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2" | ||
| 8 | fi | ||
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c new file mode 100644 index 000000000000..cdaac8c66734 --- /dev/null +++ b/scripts/gcc-plugins/randomize_layout_plugin.c | |||
| @@ -0,0 +1,1028 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014-2016 by Open Source Security, Inc., Brad Spengler <spender@grsecurity.net> | ||
| 3 | * and PaX Team <pageexec@freemail.hu> | ||
| 4 | * Licensed under the GPL v2 | ||
| 5 | * | ||
| 6 | * Note: the choice of the license means that the compilation process is | ||
| 7 | * NOT 'eligible' as defined by gcc's library exception to the GPL v3, | ||
| 8 | * but for the kernel it doesn't matter since it doesn't link against | ||
| 9 | * any of the gcc libraries | ||
| 10 | * | ||
| 11 | * Usage: | ||
| 12 | * $ # for 4.5/4.6/C based 4.7 | ||
| 13 | * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c | ||
| 14 | * $ # for C++ based 4.7/4.8+ | ||
| 15 | * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c | ||
| 16 | * $ gcc -fplugin=./randomize_layout_plugin.so test.c -O2 | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "gcc-common.h" | ||
| 20 | #include "randomize_layout_seed.h" | ||
| 21 | |||
| 22 | #if BUILDING_GCC_MAJOR < 4 || (BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR < 7) | ||
| 23 | #error "The RANDSTRUCT plugin requires GCC 4.7 or newer." | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #define ORIG_TYPE_NAME(node) \ | ||
| 27 | (TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous") | ||
| 28 | |||
| 29 | #define INFORM(loc, msg, ...) inform(loc, "randstruct: " msg, ##__VA_ARGS__) | ||
| 30 | #define MISMATCH(loc, how, ...) INFORM(loc, "casting between randomized structure pointer types (" how "): %qT and %qT\n", __VA_ARGS__) | ||
| 31 | |||
| 32 | __visible int plugin_is_GPL_compatible; | ||
| 33 | |||
| 34 | static int performance_mode; | ||
| 35 | |||
| 36 | static struct plugin_info randomize_layout_plugin_info = { | ||
| 37 | .version = "201402201816vanilla", | ||
| 38 | .help = "disable\t\t\tdo not activate plugin\n" | ||
| 39 | "performance-mode\tenable cacheline-aware layout randomization\n" | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct whitelist_entry { | ||
| 43 | const char *pathname; | ||
| 44 | const char *lhs; | ||
| 45 | const char *rhs; | ||
| 46 | }; | ||
| 47 | |||
| 48 | static const struct whitelist_entry whitelist[] = { | ||
| 49 | /* NIU overloads mapping with page struct */ | ||
| 50 | { "drivers/net/ethernet/sun/niu.c", "page", "address_space" }, | ||
| 51 | /* unix_skb_parms via UNIXCB() buffer */ | ||
| 52 | { "net/unix/af_unix.c", "unix_skb_parms", "char" }, | ||
| 53 | /* big_key payload.data struct splashing */ | ||
| 54 | { "security/keys/big_key.c", "path", "void *" }, | ||
| 55 | /* walk struct security_hook_heads as an array of struct list_head */ | ||
| 56 | { "security/security.c", "list_head", "security_hook_heads" }, | ||
| 57 | { } | ||
| 58 | }; | ||
| 59 | |||
| 60 | /* from old Linux dcache.h */ | ||
| 61 | static inline unsigned long | ||
| 62 | partial_name_hash(unsigned long c, unsigned long prevhash) | ||
| 63 | { | ||
| 64 | return (prevhash + (c << 4) + (c >> 4)) * 11; | ||
| 65 | } | ||
| 66 | static inline unsigned int | ||
| 67 | name_hash(const unsigned char *name) | ||
| 68 | { | ||
| 69 | unsigned long hash = 0; | ||
| 70 | unsigned int len = strlen((const char *)name); | ||
| 71 | while (len--) | ||
| 72 | hash = partial_name_hash(*name++, hash); | ||
| 73 | return (unsigned int)hash; | ||
| 74 | } | ||
| 75 | |||
| 76 | static tree handle_randomize_layout_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs) | ||
| 77 | { | ||
| 78 | tree type; | ||
| 79 | |||
| 80 | *no_add_attrs = true; | ||
| 81 | if (TREE_CODE(*node) == FUNCTION_DECL) { | ||
| 82 | error("%qE attribute does not apply to functions (%qF)", name, *node); | ||
| 83 | return NULL_TREE; | ||
| 84 | } | ||
| 85 | |||
| 86 | if (TREE_CODE(*node) == PARM_DECL) { | ||
| 87 | error("%qE attribute does not apply to function parameters (%qD)", name, *node); | ||
| 88 | return NULL_TREE; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (TREE_CODE(*node) == VAR_DECL) { | ||
| 92 | error("%qE attribute does not apply to variables (%qD)", name, *node); | ||
| 93 | return NULL_TREE; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (TYPE_P(*node)) { | ||
| 97 | type = *node; | ||
| 98 | } else { | ||
| 99 | gcc_assert(TREE_CODE(*node) == TYPE_DECL); | ||
| 100 | type = TREE_TYPE(*node); | ||
| 101 | } | ||
| 102 | |||
| 103 | if (TREE_CODE(type) != RECORD_TYPE) { | ||
| 104 | error("%qE attribute used on %qT applies to struct types only", name, type); | ||
| 105 | return NULL_TREE; | ||
| 106 | } | ||
| 107 | |||
| 108 | if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(type))) { | ||
| 109 | error("%qE attribute is already applied to the type %qT", name, type); | ||
| 110 | return NULL_TREE; | ||
