Merge tag 'gcc-plugins-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull gcc plugins update from Kees Cook:
"This adds a new gcc plugin named "latent_entropy". It is designed to
extract as much possible uncertainty from a running system at boot
time as possible, hoping to capitalize on any possible variation in
CPU operation (due to runtime data differences, hardware differences,
SMP ordering, thermal timing variation, cache behavior, etc).

At the very least, this plugin is a much more comprehensive example
for how to manipulate kernel code using the gcc plugin internals"

* tag 'gcc-plugins-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
latent_entropy: Mark functions with __latent_entropy
gcc-plugins: Add latent_entropy plugin

Changed files
+725 -22
arch
powerpc
kernel
block
drivers
char
fs
include
init
kernel
lib
mm
net
core
scripts
+18
arch/Kconfig
··· 383 383 gcc-4.5 on). It is based on the commit "Add fuzzing coverage support" 384 384 by Dmitry Vyukov <dvyukov@google.com>. 385 385 386 + config GCC_PLUGIN_LATENT_ENTROPY 387 + bool "Generate some entropy during boot and runtime" 388 + depends on GCC_PLUGINS 389 + help 390 + By saying Y here the kernel will instrument some kernel code to 391 + extract some entropy from both original and artificially created 392 + program state. This will help especially embedded systems where 393 + there is little 'natural' source of entropy normally. The cost 394 + is some slowdown of the boot process (about 0.5%) and fork and 395 + irq processing. 396 + 397 + Note that entropy extracted this way is not cryptographically 398 + secure! 399 + 400 + This plugin was ported from grsecurity/PaX. More information at: 401 + * https://grsecurity.net/ 402 + * https://pax.grsecurity.net/ 403 + 386 404 config HAVE_CC_STACKPROTECTOR 387 405 bool 388 406 help
+5
arch/powerpc/kernel/Makefile
··· 14 14 CFLAGS_btext.o += -fPIC 15 15 endif 16 16 17 + CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 18 + CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 19 + CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 20 + CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 21 + 17 22 ifdef CONFIG_FUNCTION_TRACER 18 23 # Do not trace early boot code 19 24 CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
+1 -1
block/blk-softirq.c
··· 18 18 * Softirq action handler - move entries to local list and loop over them 19 19 * while passing them to the queue registered handler. 20 20 */ 21 - static void blk_done_softirq(struct softirq_action *h) 21 + static __latent_entropy void blk_done_softirq(struct softirq_action *h) 22 22 { 23 23 struct list_head *cpu_list, local_list; 24 24
+2 -2
drivers/char/random.c
··· 479 479 480 480 static void crng_reseed(struct crng_state *crng, struct entropy_store *r); 481 481 static void push_to_pool(struct work_struct *work); 482 - static __u32 input_pool_data[INPUT_POOL_WORDS]; 483 - static __u32 blocking_pool_data[OUTPUT_POOL_WORDS]; 482 + static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy; 483 + static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy; 484 484 485 485 static struct entropy_store input_pool = { 486 486 .poolinfo = &poolinfo_table[0],
+1
fs/namespace.c
··· 2824 2824 return new_ns; 2825 2825 } 2826 2826 2827 + __latent_entropy 2827 2828 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, 2828 2829 struct user_namespace *user_ns, struct fs_struct *new_fs) 2829 2830 {
+7
include/linux/compiler-gcc.h
··· 188 188 #endif /* GCC_VERSION >= 40300 */ 189 189 190 190 #if GCC_VERSION >= 40500 191 + 192 + #ifndef __CHECKER__ 193 + #ifdef LATENT_ENTROPY_PLUGIN 194 + #define __latent_entropy __attribute__((latent_entropy)) 195 + #endif 196 + #endif 197 + 191 198 /* 192 199 * Mark a position in code as unreachable. This can be used to 193 200 * suppress control flow warnings after asm blocks that transfer
+4
include/linux/compiler.h
··· 429 429 # define __attribute_const__ /* unimplemented */ 430 430 #endif 431 431 432 + #ifndef __latent_entropy 433 + # define __latent_entropy 434 + #endif 435 + 432 436 /* 433 437 * Tell gcc if a function is cold. The compiler will assume any path 434 438 * directly leading to the call is unlikely.
+1 -1
include/linux/fdtable.h
··· 105 105 void put_files_struct(struct files_struct *fs); 106 106 void reset_files_struct(struct files_struct *); 107 107 int unshare_files(struct files_struct **); 108 - struct files_struct *dup_fd(struct files_struct *, int *); 108 + struct files_struct *dup_fd(struct files_struct *, int *) __latent_entropy; 109 109 void do_close_on_exec(struct files_struct *); 110 110 int iterate_fd(struct files_struct *, unsigned, 111 111 int (*)(const void *, struct file *, unsigned),
+1 -1
include/linux/genhd.h
··· 437 437 extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask); 438 438 439 439 /* drivers/char/random.c */ 440 - extern void add_disk_randomness(struct gendisk *disk); 440 + extern void add_disk_randomness(struct gendisk *disk) __latent_entropy; 441 441 extern void rand_initialize_disk(struct gendisk *disk); 442 442 443 443 static inline sector_t get_start_sect(struct block_device *bdev)
+3 -2
include/linux/init.h
··· 39 39 40 40 /* These are for everybody (although not all archs will actually 41 41 discard it in modules) */ 42 - #define __init __section(.init.text) __cold notrace 42 + #define __init __section(.init.text) __cold notrace __latent_entropy 43 43 #define __initdata __section(.init.data) 44 44 #define __initconst __section(.init.rodata) 45 45 #define __exitdata __section(.exit.data) ··· 75 75 #define __exit __section(.exit.text) __exitused __cold notrace 76 76 77 77 /* Used for MEMORY_HOTPLUG */ 78 - #define __meminit __section(.meminit.text) __cold notrace 78 + #define __meminit __section(.meminit.text) __cold notrace \ 79 + __latent_entropy 79 80 #define __meminitdata __section(.meminit.data) 80 81 #define __meminitconst __section(.meminit.rodata) 81 82 #define __memexit __section(.memexit.text) __exitused __cold notrace
+13 -2
include/linux/random.h
··· 18 18 }; 19 19 20 20 extern void add_device_randomness(const void *, unsigned int); 21 + 22 + #if defined(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) && !defined(__CHECKER__) 23 + static inline void add_latent_entropy(void) 24 + { 25 + add_device_randomness((const void *)&latent_entropy, 26 + sizeof(latent_entropy)); 27 + } 28 + #else 29 + static inline void add_latent_entropy(void) {} 30 + #endif 31 + 21 32 extern void add_input_randomness(unsigned int type, unsigned int code, 22 - unsigned int value); 23 - extern void add_interrupt_randomness(int irq, int irq_flags); 33 + unsigned int value) __latent_entropy; 34 + extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy; 24 35 25 36 extern void get_random_bytes(void *buf, int nbytes); 26 37 extern int add_random_ready_callback(struct random_ready_callback *rdy);
+1
init/main.c
··· 789 789 } 790 790 WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf); 791 791 792 + add_latent_entropy(); 792 793 return ret; 793 794 } 794 795
+5 -2
kernel/fork.c
··· 547 547 } 548 548 549 549 #ifdef CONFIG_MMU 550 - static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) 550 + static __latent_entropy int dup_mmap(struct mm_struct *mm, 551 + struct mm_struct *oldmm) 551 552 { 552 553 struct vm_area_struct *mpnt, *tmp, *prev, **pprev; 553 554 struct rb_node **rb_link, *rb_parent; ··· 1442 1441 * parts of the process environment (as per the clone 1443 1442 * flags). The actual kick-off is left to the caller. 1444 1443 */ 1445 - static struct task_struct *copy_process(unsigned long clone_flags, 1444 + static __latent_entropy struct task_struct *copy_process( 1445 + unsigned long clone_flags, 1446 1446 unsigned long stack_start, 1447 1447 unsigned long stack_size, 1448 1448 int __user *child_tidptr, ··· 1928 1926 1929 1927 p = copy_process(clone_flags, stack_start, stack_size, 1930 1928 child_tidptr, NULL, trace, tls, NUMA_NO_NODE); 1929 + add_latent_entropy(); 1931 1930 /* 1932 1931 * Do this prior waking up the new thread - the thread pointer 1933 1932 * might get invalid after that point, if the thread exits quickly.
+1 -1
kernel/rcu/tiny.c
··· 170 170 false)); 171 171 } 172 172 173 - static void rcu_process_callbacks(struct softirq_action *unused) 173 + static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused) 174 174 { 175 175 __rcu_process_callbacks(&rcu_sched_ctrlblk); 176 176 __rcu_process_callbacks(&rcu_bh_ctrlblk);
+1 -1
kernel/rcu/tree.c
··· 3013 3013 /* 3014 3014 * Do RCU core processing for the current CPU. 3015 3015 */ 3016 - static void rcu_process_callbacks(struct softirq_action *unused) 3016 + static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused) 3017 3017 { 3018 3018 struct rcu_state *rsp; 3019 3019
+1 -1
kernel/sched/fair.c
··· 8522 8522 * run_rebalance_domains is triggered when needed from the scheduler tick. 8523 8523 * Also triggered for nohz idle balancing (with nohz_balancing_kick set). 8524 8524 */ 8525 - static void run_rebalance_domains(struct softirq_action *h) 8525 + static __latent_entropy void run_rebalance_domains(struct softirq_action *h) 8526 8526 { 8527 8527 struct rq *this_rq = this_rq(); 8528 8528 enum cpu_idle_type idle = this_rq->idle_balance ?
+2 -2
kernel/softirq.c
··· 496 496 } 497 497 EXPORT_SYMBOL(__tasklet_hi_schedule_first); 498 498 499 - static void tasklet_action(struct softirq_action *a) 499 + static __latent_entropy void tasklet_action(struct softirq_action *a) 500 500 { 501 501 struct tasklet_struct *list; 502 502 ··· 532 532 } 533 533 } 534 534 535 - static void tasklet_hi_action(struct softirq_action *a) 535 + static __latent_entropy void tasklet_hi_action(struct softirq_action *a) 536 536 { 537 537 struct tasklet_struct *list; 538 538
+1 -1
kernel/time/timer.c
··· 1633 1633 /* 1634 1634 * This function runs timers and the timer-tq in bottom half context. 1635 1635 */ 1636 - static void run_timer_softirq(struct softirq_action *h) 1636 + static __latent_entropy void run_timer_softirq(struct softirq_action *h) 1637 1637 { 1638 1638 struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); 1639 1639
+1 -1
lib/irq_poll.c
··· 74 74 } 75 75 EXPORT_SYMBOL(irq_poll_complete); 76 76 77 - static void irq_poll_softirq(struct softirq_action *h) 77 + static void __latent_entropy irq_poll_softirq(struct softirq_action *h) 78 78 { 79 79 struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll); 80 80 int rearm = 0, budget = irq_poll_budget;
+1 -1
lib/random32.c
··· 47 47 } 48 48 #endif 49 49 50 - static DEFINE_PER_CPU(struct rnd_state, net_rand_state); 50 + static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; 51 51 52 52 /** 53 53 * prandom_u32_state - seeded pseudo-random number generator.
+5
mm/page_alloc.c
··· 91 91 int _node_numa_mem_[MAX_NUMNODES]; 92 92 #endif 93 93 94 + #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY 95 + volatile u64 latent_entropy __latent_entropy; 96 + EXPORT_SYMBOL(latent_entropy); 97 + #endif 98 + 94 99 /* 95 100 * Array of node states. 96 101 */
+2 -2
net/core/dev.c
··· 3845 3845 } 3846 3846 EXPORT_SYMBOL(netif_rx_ni); 3847 3847 3848 - static void net_tx_action(struct softirq_action *h) 3848 + static __latent_entropy void net_tx_action(struct softirq_action *h) 3849 3849 { 3850 3850 struct softnet_data *sd = this_cpu_ptr(&softnet_data); 3851 3851 ··· 5198 5198 return work; 5199 5199 } 5200 5200 5201 - static void net_rx_action(struct softirq_action *h) 5201 + static __latent_entropy void net_rx_action(struct softirq_action *h) 5202 5202 { 5203 5203 struct softnet_data *sd = this_cpu_ptr(&softnet_data); 5204 5204 unsigned long time_limit = jiffies + 2;
+8 -1
scripts/Makefile.gcc-plugins
··· 6 6 7 7 gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so 8 8 9 + gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so 10 + gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN 11 + ifdef CONFIG_PAX_LATENT_ENTROPY 12 + DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable 13 + endif 14 + 9 15 ifdef CONFIG_GCC_PLUGIN_SANCOV 10 16 ifeq ($(CFLAGS_KCOV),) 11 17 # It is needed because of the gcc-plugin.sh and gcc version checks. ··· 27 21 28 22 GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) 29 23 30 - export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR SANCOV_PLUGIN 24 + export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR 25 + export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN 31 26 32 27 ifneq ($(PLUGINCC),) 33 28 # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.
+640
scripts/gcc-plugins/latent_entropy_plugin.c
··· 1 + /* 2 + * Copyright 2012-2016 by the PaX Team <pageexec@freemail.hu> 3 + * Copyright 2016 by Emese Revfy <re.emese@gmail.com> 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 + * This gcc plugin helps generate a little bit of entropy from program state, 12 + * used throughout the uptime of the kernel. Here is an instrumentation example: 13 + * 14 + * before: 15 + * void __latent_entropy test(int argc, char *argv[]) 16 + * { 17 + * if (argc <= 1) 18 + * printf("%s: no command arguments :(\n", *argv); 19 + * else 20 + * printf("%s: %d command arguments!\n", *argv, args - 1); 21 + * } 22 + * 23 + * after: 24 + * void __latent_entropy test(int argc, char *argv[]) 25 + * { 26 + * // latent_entropy_execute() 1. 27 + * unsigned long local_entropy; 28 + * // init_local_entropy() 1. 29 + * void *local_entropy_frameaddr; 30 + * // init_local_entropy() 3. 31 + * unsigned long tmp_latent_entropy; 32 + * 33 + * // init_local_entropy() 2. 34 + * local_entropy_frameaddr = __builtin_frame_address(0); 35 + * local_entropy = (unsigned long) local_entropy_frameaddr; 36 + * 37 + * // init_local_entropy() 4. 38 + * tmp_latent_entropy = latent_entropy; 39 + * // init_local_entropy() 5. 40 + * local_entropy ^= tmp_latent_entropy; 41 + * 42 + * // latent_entropy_execute() 3. 43 + * if (argc <= 1) { 44 + * // perturb_local_entropy() 45 + * local_entropy += 4623067384293424948; 46 + * printf("%s: no command arguments :(\n", *argv); 47 + * // perturb_local_entropy() 48 + * } else { 49 + * local_entropy ^= 3896280633962944730; 50 + * printf("%s: %d command arguments!\n", *argv, args - 1); 51 + * } 52 + * 53 + * // latent_entropy_execute() 4. 54 + * tmp_latent_entropy = rol(tmp_latent_entropy, local_entropy); 55 + * latent_entropy = tmp_latent_entropy; 56 + * } 57 + * 58 + * TODO: 59 + * - add ipa pass to identify not explicitly marked candidate functions 60 + * - mix in more program state (function arguments/return values, 61 + * loop variables, etc) 62 + * - more instrumentation control via attribute parameters 63 + * 64 + * BUGS: 65 + * - none known 66 + * 67 + * Options: 68 + * -fplugin-arg-latent_entropy_plugin-disable 69 + * 70 + * Attribute: __attribute__((latent_entropy)) 71 + * The latent_entropy gcc attribute can be only on functions and variables. 72 + * If it is on a function then the plugin will instrument it. If the attribute 73 + * is on a variable then the plugin will initialize it with a random value. 74 + * The variable must be an integer, an integer array type or a structure 75 + * with integer fields. 76 + */ 77 + 78 + #include "gcc-common.h" 79 + 80 + int plugin_is_GPL_compatible; 81 + 82 + static GTY(()) tree latent_entropy_decl; 83 + 84 + static struct plugin_info latent_entropy_plugin_info = { 85 + .version = "201606141920vanilla", 86 + .help = "disable\tturn off latent entropy instrumentation\n", 87 + }; 88 + 89 + static unsigned HOST_WIDE_INT seed; 90 + /* 91 + * get_random_seed() (this is a GCC function) generates the seed. 92 + * This is a simple random generator without any cryptographic security because 93 + * the entropy doesn't come from here. 94 + */ 95 + static unsigned HOST_WIDE_INT get_random_const(void) 96 + { 97 + unsigned int i; 98 + unsigned HOST_WIDE_INT ret = 0; 99 + 100 + for (i = 0; i < 8 * sizeof(ret); i++) { 101 + ret = (ret << 1) | (seed & 1); 102 + seed >>= 1; 103 + if (ret & 1) 104 + seed ^= 0xD800000000000000ULL; 105 + } 106 + 107 + return ret; 108 + } 109 + 110 + static tree tree_get_random_const(tree type) 111 + { 112 + unsigned long long mask; 113 + 114 + mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); 115 + mask = 2 * (mask - 1) + 1; 116 + 117 + if (TYPE_UNSIGNED(type)) 118 + return build_int_cstu(type, mask & get_random_const()); 119 + return build_int_cst(type, mask & get_random_const()); 120 + } 121 + 122 + static tree handle_latent_entropy_attribute(tree *node, tree name, 123 + tree args __unused, 124 + int flags __unused, 125 + bool *no_add_attrs) 126 + { 127 + tree type; 128 + #if BUILDING_GCC_VERSION <= 4007 129 + VEC(constructor_elt, gc) *vals; 130 + #else 131 + vec<constructor_elt, va_gc> *vals; 132 + #endif 133 + 134 + switch (TREE_CODE(*node)) { 135 + default: 136 + *no_add_attrs = true; 137 + error("%qE attribute only applies to functions and variables", 138 + name); 139 + break; 140 + 141 + case VAR_DECL: 142 + if (DECL_INITIAL(*node)) { 143 + *no_add_attrs = true; 144 + error("variable %qD with %qE attribute must not be initialized", 145 + *node, name); 146 + break; 147 + } 148 + 149 + if (!TREE_STATIC(*node)) { 150 + *no_add_attrs = true; 151 + error("variable %qD with %qE attribute must not be local", 152 + *node, name); 153 + break; 154 + } 155 + 156 + type = TREE_TYPE(*node); 157 + switch (TREE_CODE(type)) { 158 + default: 159 + *no_add_attrs = true; 160 + error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", 161 + *node, name); 162 + break; 163 + 164 + case RECORD_TYPE: { 165 + tree fld, lst = TYPE_FIELDS(type); 166 + unsigned int nelt = 0; 167 + 168 + for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) { 169 + tree fieldtype; 170 + 171 + fieldtype = TREE_TYPE(fld); 172 + if (TREE_CODE(fieldtype) == INTEGER_TYPE) 173 + continue; 174 + 175 + *no_add_attrs = true; 176 + error("structure variable %qD with %qE attribute has a non-integer field %qE", 177 + *node, name, fld); 178 + break; 179 + } 180 + 181 + if (fld) 182 + break; 183 + 184 + #if BUILDING_GCC_VERSION <= 4007 185 + vals = VEC_alloc(constructor_elt, gc, nelt); 186 + #else 187 + vec_alloc(vals, nelt); 188 + #endif 189 + 190 + for (fld = lst; fld; fld = TREE_CHAIN(fld)) { 191 + tree random_const, fld_t = TREE_TYPE(fld); 192 + 193 + random_const = tree_get_random_const(fld_t); 194 + CONSTRUCTOR_APPEND_ELT(vals, fld, random_const); 195 + } 196 + 197 + /* Initialize the fields with random constants */ 198 + DECL_INITIAL(*node) = build_constructor(type, vals); 199 + break; 200 + } 201 + 202 + /* Initialize the variable with a random constant */ 203 + case INTEGER_TYPE: 204 + DECL_INITIAL(*node) = tree_get_random_const(type); 205 + break; 206 + 207 + case ARRAY_TYPE: { 208 + tree elt_type, array_size, elt_size; 209 + unsigned int i, nelt; 210 + HOST_WIDE_INT array_size_int, elt_size_int; 211 + 212 + elt_type = TREE_TYPE(type); 213 + elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); 214 + array_size = TYPE_SIZE_UNIT(type); 215 + 216 + if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size 217 + || TREE_CODE(array_size) != INTEGER_CST) { 218 + *no_add_attrs = true; 219 + error("array variable %qD with %qE attribute must be a fixed length integer array type", 220 + *node, name); 221 + break; 222 + } 223 + 224 + array_size_int = TREE_INT_CST_LOW(array_size); 225 + elt_size_int = TREE_INT_CST_LOW(elt_size); 226 + nelt = array_size_int / elt_size_int; 227 + 228 + #if BUILDING_GCC_VERSION <= 4007 229 + vals = VEC_alloc(constructor_elt, gc, nelt); 230 + #else 231 + vec_alloc(vals, nelt); 232 + #endif 233 + 234 + for (i = 0; i < nelt; i++) { 235 + tree cst = size_int(i); 236 + tree rand_cst = tree_get_random_const(elt_type); 237 + 238 + CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst); 239 + } 240 + 241 + /* 242 + * Initialize the elements of the array with random 243 + * constants 244 + */ 245 + DECL_INITIAL(*node) = build_constructor(type, vals); 246 + break; 247 + } 248 + } 249 + break; 250 + 251 + case FUNCTION_DECL: 252 + break; 253 + } 254 + 255 + return NULL_TREE; 256 + } 257 + 258 + static struct attribute_spec latent_entropy_attr = { 259 + .name = "latent_entropy", 260 + .min_length = 0, 261 + .max_length = 0, 262 + .decl_required = true, 263 + .type_required = false, 264 + .function_type_required = false, 265 + .handler = handle_latent_entropy_attribute, 266 + #if BUILDING_GCC_VERSION >= 4007 267 + .affects_type_identity = false 268 + #endif 269 + }; 270 + 271 + static void register_attributes(void *event_data __unused, void *data __unused) 272 + { 273 + register_attribute(&latent_entropy_attr); 274 + } 275 + 276 + static bool latent_entropy_gate(void) 277 + { 278 + tree list; 279 + 280 + /* don't bother with noreturn functions for now */ 281 + if (TREE_THIS_VOLATILE(current_function_decl)) 282 + return false; 283 + 284 + /* gcc-4.5 doesn't discover some trivial noreturn functions */ 285 + if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds) == 0) 286 + return false; 287 + 288 + list = DECL_ATTRIBUTES(current_function_decl); 289 + return lookup_attribute("latent_entropy", list) != NULL_TREE; 290 + } 291 + 292 + static tree create_var(tree type, const char *name) 293 + { 294 + tree var; 295 + 296 + var = create_tmp_var(type, name); 297 + add_referenced_var(var); 298 + mark_sym_for_renaming(var); 299 + return var; 300 + } 301 + 302 + /* 303 + * Set up the next operation and its constant operand to use in the latent 304 + * entropy PRNG. When RHS is specified, the request is for perturbing the 305 + * local latent entropy variable, otherwise it is for perturbing the global 306 + * latent entropy variable where the two operands are already given by the 307 + * local and global latent entropy variables themselves. 308 + * 309 + * The operation is one of add/xor/rol when instrumenting the local entropy 310 + * variable and one of add/xor when perturbing the global entropy variable. 311 + * Rotation is not used for the latter case because it would transmit less 312 + * entropy to the global variable than the other two operations. 313 + */ 314 + static enum tree_code get_op(tree *rhs) 315 + { 316 + static enum tree_code op; 317 + unsigned HOST_WIDE_INT random_const; 318 + 319 + random_const = get_random_const(); 320 + 321 + switch (op) { 322 + case BIT_XOR_EXPR: 323 + op = PLUS_EXPR; 324 + break; 325 + 326 + case PLUS_EXPR: 327 + if (rhs) { 328 + op = LROTATE_EXPR; 329 + /* 330 + * This code limits the value of random_const to 331 + * the size of a wide int for the rotation 332 + */ 333 + random_const &= HOST_BITS_PER_WIDE_INT - 1; 334 + break; 335 + } 336 + 337 + case LROTATE_EXPR: 338 + default: 339 + op = BIT_XOR_EXPR; 340 + break; 341 + } 342 + if (rhs) 343 + *rhs = build_int_cstu(unsigned_intDI_type_node, random_const); 344 + return op; 345 + } 346 + 347 + static gimple create_assign(enum tree_code code, tree lhs, tree op1, 348 + tree op2) 349 + { 350 + return gimple_build_assign_with_ops(code, lhs, op1, op2); 351 + } 352 + 353 + static void perturb_local_entropy(basic_block bb, tree local_entropy) 354 + { 355 + gimple_stmt_iterator gsi; 356 + gimple assign; 357 + tree rhs; 358 + enum tree_code op; 359 + 360 + op = get_op(&rhs); 361 + assign = create_assign(op, local_entropy, local_entropy, rhs); 362 + gsi = gsi_after_labels(bb); 363 + gsi_insert_before(&gsi, assign, GSI_NEW_STMT); 364 + update_stmt(assign); 365 + } 366 + 367 + static void __perturb_latent_entropy(gimple_stmt_iterator *gsi, 368 + tree local_entropy) 369 + { 370 + gimple assign; 371 + tree temp; 372 + enum tree_code op; 373 + 374 + /* 1. create temporary copy of latent_entropy */ 375 + temp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); 376 + 377 + /* 2. read... */ 378 + add_referenced_var(latent_entropy_decl); 379 + mark_sym_for_renaming(latent_entropy_decl); 380 + assign = gimple_build_assign(temp, latent_entropy_decl); 381 + gsi_insert_before(gsi, assign, GSI_NEW_STMT); 382 + update_stmt(assign); 383 + 384 + /* 3. ...modify... */ 385 + op = get_op(NULL); 386 + assign = create_assign(op, temp, temp, local_entropy); 387 + gsi_insert_after(gsi, assign, GSI_NEW_STMT); 388 + update_stmt(assign); 389 + 390 + /* 4. ...write latent_entropy */ 391 + assign = gimple_build_assign(latent_entropy_decl, temp); 392 + gsi_insert_after(gsi, assign, GSI_NEW_STMT); 393 + update_stmt(assign); 394 + } 395 + 396 + static bool handle_tail_calls(basic_block bb, tree local_entropy) 397 + { 398 + gimple_stmt_iterator gsi; 399 + 400 + for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { 401 + gcall *call; 402 + gimple stmt = gsi_stmt(gsi); 403 + 404 + if (!is_gimple_call(stmt)) 405 + continue; 406 + 407 + call = as_a_gcall(stmt); 408 + if (!gimple_call_tail_p(call)) 409 + continue; 410 + 411 + __perturb_latent_entropy(&gsi, local_entropy); 412 + return true; 413 + } 414 + 415 + return false; 416 + } 417 + 418 + static void perturb_latent_entropy(tree local_entropy) 419 + { 420 + edge_iterator ei; 421 + edge e, last_bb_e; 422 + basic_block last_bb; 423 + 424 + gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun))); 425 + last_bb_e = single_pred_edge(EXIT_BLOCK_PTR_FOR_FN(cfun)); 426 + 427 + FOR_EACH_EDGE(e, ei, last_bb_e->src->preds) { 428 + if (ENTRY_BLOCK_PTR_FOR_FN(cfun) == e->src) 429 + continue; 430 + if (EXIT_BLOCK_PTR_FOR_FN(cfun) == e->src) 431 + continue; 432 + 433 + handle_tail_calls(e->src, local_entropy); 434 + } 435 + 436 + last_bb = single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)); 437 + if (!handle_tail_calls(last_bb, local_entropy)) { 438 + gimple_stmt_iterator gsi = gsi_last_bb(last_bb); 439 + 440 + __perturb_latent_entropy(&gsi, local_entropy); 441 + } 442 + } 443 + 444 + static void init_local_entropy(basic_block bb, tree local_entropy) 445 + { 446 + gimple assign, call; 447 + tree frame_addr, rand_const, tmp, fndecl, udi_frame_addr; 448 + enum tree_code op; 449 + unsigned HOST_WIDE_INT rand_cst; 450 + gimple_stmt_iterator gsi = gsi_after_labels(bb); 451 + 452 + /* 1. create local_entropy_frameaddr */ 453 + frame_addr = create_var(ptr_type_node, "local_entropy_frameaddr"); 454 + 455 + /* 2. local_entropy_frameaddr = __builtin_frame_address() */ 456 + fndecl = builtin_decl_implicit(BUILT_IN_FRAME_ADDRESS); 457 + call = gimple_build_call(fndecl, 1, integer_zero_node); 458 + gimple_call_set_lhs(call, frame_addr); 459 + gsi_insert_before(&gsi, call, GSI_NEW_STMT); 460 + update_stmt(call); 461 + 462 + udi_frame_addr = fold_convert(unsigned_intDI_type_node, frame_addr); 463 + assign = gimple_build_assign(local_entropy, udi_frame_addr); 464 + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); 465 + update_stmt(assign); 466 + 467 + /* 3. create temporary copy of latent_entropy */ 468 + tmp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); 469 + 470 + /* 4. read the global entropy variable into local entropy */ 471 + add_referenced_var(latent_entropy_decl); 472 + mark_sym_for_renaming(latent_entropy_decl); 473 + assign = gimple_build_assign(tmp, latent_entropy_decl); 474 + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); 475 + update_stmt(assign); 476 + 477 + /* 5. mix local_entropy_frameaddr into local entropy */ 478 + assign = create_assign(BIT_XOR_EXPR, local_entropy, local_entropy, tmp); 479 + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); 480 + update_stmt(assign); 481 + 482 + rand_cst = get_random_const(); 483 + rand_const = build_int_cstu(unsigned_intDI_type_node, rand_cst); 484 + op = get_op(NULL); 485 + assign = create_assign(op, local_entropy, local_entropy, rand_const); 486 + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); 487 + update_stmt(assign); 488 + } 489 + 490 + static bool create_latent_entropy_decl(void) 491 + { 492 + varpool_node_ptr node; 493 + 494 + if (latent_entropy_decl != NULL_TREE) 495 + return true; 496 + 497 + FOR_EACH_VARIABLE(node) { 498 + tree name, var = NODE_DECL(node); 499 + 500 + if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1) 501 + continue; 502 + 503 + name = DECL_NAME(var); 504 + if (strcmp(IDENTIFIER_POINTER(name), "latent_entropy")) 505 + continue; 506 + 507 + latent_entropy_decl = var; 508 + break; 509 + } 510 + 511 + return latent_entropy_decl != NULL_TREE; 512 + } 513 + 514 + static unsigned int latent_entropy_execute(void) 515 + { 516 + basic_block bb; 517 + tree local_entropy; 518 + 519 + if (!create_latent_entropy_decl()) 520 + return 0; 521 + 522 + /* prepare for step 2 below */ 523 + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); 524 + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); 525 + if (!single_pred_p(bb)) { 526 + split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun))); 527 + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); 528 + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); 529 + } 530 + 531 + /* 1. create the local entropy variable */ 532 + local_entropy = create_var(unsigned_intDI_type_node, "local_entropy"); 533 + 534 + /* 2. initialize the local entropy variable */ 535 + init_local_entropy(bb, local_entropy); 536 + 537 + bb = bb->next_bb; 538 + 539 + /* 540 + * 3. instrument each BB with an operation on the 541 + * local entropy variable 542 + */ 543 + while (bb != EXIT_BLOCK_PTR_FOR_FN(cfun)) { 544 + perturb_local_entropy(bb, local_entropy); 545 + bb = bb->next_bb; 546 + }; 547 + 548 + /* 4. mix local entropy into the global entropy variable */ 549 + perturb_latent_entropy(local_entropy); 550 + return 0; 551 + } 552 + 553 + static void latent_entropy_start_unit(void *gcc_data __unused, 554 + void *user_data __unused) 555 + { 556 + tree type, id; 557 + int quals; 558 + 559 + seed = get_random_seed(false); 560 + 561 + if (in_lto_p) 562 + return; 563 + 564 + /* extern volatile u64 latent_entropy */ 565 + gcc_assert(TYPE_PRECISION(long_long_unsigned_type_node) == 64); 566 + quals = TYPE_QUALS(long_long_unsigned_type_node) | TYPE_QUAL_VOLATILE; 567 + type = build_qualified_type(long_long_unsigned_type_node, quals); 568 + id = get_identifier("latent_entropy"); 569 + latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, id, type); 570 + 571 + TREE_STATIC(latent_entropy_decl) = 1; 572 + TREE_PUBLIC(latent_entropy_decl) = 1; 573 + TREE_USED(latent_entropy_decl) = 1; 574 + DECL_PRESERVE_P(latent_entropy_decl) = 1; 575 + TREE_THIS_VOLATILE(latent_entropy_decl) = 1; 576 + DECL_EXTERNAL(latent_entropy_decl) = 1; 577 + DECL_ARTIFICIAL(latent_entropy_decl) = 1; 578 + lang_hooks.decls.pushdecl(latent_entropy_decl); 579 + } 580 + 581 + #define PASS_NAME latent_entropy 582 + #define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg 583 + #define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \ 584 + | TODO_update_ssa 585 + #include "gcc-generate-gimple-pass.h" 586 + 587 + int plugin_init(struct plugin_name_args *plugin_info, 588 + struct plugin_gcc_version *version) 589 + { 590 + bool enabled = true; 591 + const char * const plugin_name = plugin_info->base_name; 592 + const int argc = plugin_info->argc; 593 + const struct plugin_argument * const argv = plugin_info->argv; 594 + int i; 595 + 596 + struct register_pass_info latent_entropy_pass_info; 597 + 598 + latent_entropy_pass_info.pass = make_latent_entropy_pass(); 599 + latent_entropy_pass_info.reference_pass_name = "optimized"; 600 + latent_entropy_pass_info.ref_pass_instance_number = 1; 601 + latent_entropy_pass_info.pos_op = PASS_POS_INSERT_BEFORE; 602 + static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = { 603 + { 604 + .base = &latent_entropy_decl, 605 + .nelt = 1, 606 + .stride = sizeof(latent_entropy_decl), 607 + .cb = &gt_ggc_mx_tree_node, 608 + .pchw = &gt_pch_nx_tree_node 609 + }, 610 + LAST_GGC_ROOT_TAB 611 + }; 612 + 613 + if (!plugin_default_version_check(version, &gcc_version)) { 614 + error(G_("incompatible gcc/plugin versions")); 615 + return 1; 616 + } 617 + 618 + for (i = 0; i < argc; ++i) { 619 + if (!(strcmp(argv[i].key, "disable"))) { 620 + enabled = false; 621 + continue; 622 + } 623 + error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key); 624 + } 625 + 626 + register_callback(plugin_name, PLUGIN_INFO, NULL, 627 + &latent_entropy_plugin_info); 628 + if (enabled) { 629 + register_callback(plugin_name, PLUGIN_START_UNIT, 630 + &latent_entropy_start_unit, NULL); 631 + register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, 632 + NULL, (void *)&gt_ggc_r_gt_latent_entropy); 633 + register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, 634 + &latent_entropy_pass_info); 635 + } 636 + register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, 637 + NULL); 638 + 639 + return 0; 640 + }