diff options
author | Emese Revfy <re.emese@gmail.com> | 2016-06-20 14:42:34 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2016-10-10 17:51:45 -0400 |
commit | 0766f788eb727e2e330d55d30545db65bcf2623f (patch) | |
tree | 0436ae3b005558a4fb827459fe5c602037fe764a | |
parent | 38addce8b600ca335dc86fa3d48c890f1c6fa1f4 (diff) |
latent_entropy: Mark functions with __latent_entropy
The __latent_entropy gcc attribute can be used only on functions and
variables. If it is on a function then the plugin will instrument it for
gathering control-flow entropy. If the attribute is on a variable then
the plugin will initialize it with random contents. The variable must
be an integer, an integer array type or a structure with integer fields.
These specific functions have been selected because they are init
functions (to help gather boot-time entropy), are called at unpredictable
times, or they have variable loops, each of which provide some level of
latent entropy.
Signed-off-by: Emese Revfy <re.emese@gmail.com>
[kees: expanded commit message]
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | block/blk-softirq.c | 2 | ||||
-rw-r--r-- | drivers/char/random.c | 4 | ||||
-rw-r--r-- | fs/namespace.c | 1 | ||||
-rw-r--r-- | include/linux/compiler-gcc.h | 7 | ||||
-rw-r--r-- | include/linux/compiler.h | 4 | ||||
-rw-r--r-- | include/linux/fdtable.h | 2 | ||||
-rw-r--r-- | include/linux/genhd.h | 2 | ||||
-rw-r--r-- | include/linux/init.h | 5 | ||||
-rw-r--r-- | include/linux/random.h | 4 | ||||
-rw-r--r-- | kernel/fork.c | 6 | ||||
-rw-r--r-- | kernel/rcu/tiny.c | 2 | ||||
-rw-r--r-- | kernel/rcu/tree.c | 2 | ||||
-rw-r--r-- | kernel/sched/fair.c | 2 | ||||
-rw-r--r-- | kernel/softirq.c | 4 | ||||
-rw-r--r-- | kernel/time/timer.c | 2 | ||||
-rw-r--r-- | lib/irq_poll.c | 2 | ||||
-rw-r--r-- | lib/random32.c | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 4 |
19 files changed, 37 insertions, 22 deletions
diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 53b1737e978d..489eab825a8a 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c | |||
@@ -18,7 +18,7 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done); | |||
18 | * Softirq action handler - move entries to local list and loop over them | 18 | * Softirq action handler - move entries to local list and loop over them |
19 | * while passing them to the queue registered handler. | 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 | struct list_head *cpu_list, local_list; | 23 | struct list_head *cpu_list, local_list; |
24 | 24 | ||
diff --git a/drivers/char/random.c b/drivers/char/random.c index 3efb3bf0ab83..7274ae89ddb3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -479,8 +479,8 @@ static ssize_t _extract_entropy(struct entropy_store *r, void *buf, | |||
479 | 479 | ||
480 | static void crng_reseed(struct crng_state *crng, struct entropy_store *r); | 480 | static void crng_reseed(struct crng_state *crng, struct entropy_store *r); |
481 | static void push_to_pool(struct work_struct *work); | 481 | static void push_to_pool(struct work_struct *work); |
482 | static __u32 input_pool_data[INPUT_POOL_WORDS]; | 482 | static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy; |
483 | static __u32 blocking_pool_data[OUTPUT_POOL_WORDS]; | 483 | static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy; |
484 | 484 | ||
485 | static struct entropy_store input_pool = { | 485 | static struct entropy_store input_pool = { |
486 | .poolinfo = &poolinfo_table[0], | 486 | .poolinfo = &poolinfo_table[0], |
diff --git a/fs/namespace.c b/fs/namespace.c index 7bb2cda3bfef..4a9568b81138 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2759,6 +2759,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns) | |||
2759 | return new_ns; | 2759 | return new_ns; |
2760 | } | 2760 | } |
2761 | 2761 | ||
2762 | __latent_entropy | ||
2762 | struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, | 2763 | struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, |
2763 | struct user_namespace *user_ns, struct fs_struct *new_fs) | 2764 | struct user_namespace *user_ns, struct fs_struct *new_fs) |
2764 | { | 2765 | { |
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 573c5a18908f..432f5c97e18f 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h | |||
@@ -188,6 +188,13 @@ | |||
188 | #endif /* GCC_VERSION >= 40300 */ | 188 | #endif /* GCC_VERSION >= 40300 */ |
189 | 189 | ||
190 | #if GCC_VERSION >= 40500 | 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 | * Mark a position in code as unreachable. This can be used to | 199 | * Mark a position in code as unreachable. This can be used to |
193 | * suppress control flow warnings after asm blocks that transfer | 200 | * suppress control flow warnings after asm blocks that transfer |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 668569844d37..ceaddaf76ff1 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -406,6 +406,10 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s | |||
406 | # define __attribute_const__ /* unimplemented */ | 406 | # define __attribute_const__ /* unimplemented */ |
407 | #endif | 407 | #endif |
408 | 408 | ||
409 | #ifndef __latent_entropy | ||
410 | # define __latent_entropy | ||
411 | #endif | ||
412 | |||
409 | /* | 413 | /* |
410 | * Tell gcc if a function is cold. The compiler will assume any path | 414 | * Tell gcc if a function is cold. The compiler will assume any path |
411 | * directly leading to the call is unlikely. | 415 | * directly leading to the call is unlikely. |
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 5295535b60c6..9852c7e33466 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h | |||
@@ -105,7 +105,7 @@ struct files_struct *get_files_struct(struct task_struct *); | |||
105 | void put_files_struct(struct files_struct *fs); | 105 | void put_files_struct(struct files_struct *fs); |
106 | void reset_files_struct(struct files_struct *); | 106 | void reset_files_struct(struct files_struct *); |
107 | int unshare_files(struct files_struct **); | 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 | void do_close_on_exec(struct files_struct *); | 109 | void do_close_on_exec(struct files_struct *); |
110 | int iterate_fd(struct files_struct *, unsigned, | 110 | int iterate_fd(struct files_struct *, unsigned, |
111 | int (*)(const void *, struct file *, unsigned), | 111 | int (*)(const void *, struct file *, unsigned), |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 1dbf52f9c24b..e0341af6950e 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -437,7 +437,7 @@ extern void disk_flush_events(struct gendisk *disk, unsigned int mask); | |||
437 | extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask); | 437 | extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask); |
438 | 438 | ||
439 | /* drivers/char/random.c */ | 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 | extern void rand_initialize_disk(struct gendisk *disk); | 441 | extern void rand_initialize_disk(struct gendisk *disk); |
442 | 442 | ||
443 | static inline sector_t get_start_sect(struct block_device *bdev) | 443 | static inline sector_t get_start_sect(struct block_device *bdev) |
diff --git a/include/linux/init.h b/include/linux/init.h index 6935d02474aa..1e5c131d5c9a 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | /* These are for everybody (although not all archs will actually | 40 | /* These are for everybody (although not all archs will actually |
41 | discard it in modules) */ | 41 | discard it in modules) */ |
42 | #define __init __section(.init.text) __cold notrace | 42 | #define __init __section(.init.text) __cold notrace __latent_entropy |
43 | #define __initdata __section(.init.data) | 43 | #define __initdata __section(.init.data) |
44 | #define __initconst __constsection(.init.rodata) | 44 | #define __initconst __constsection(.init.rodata) |
45 | #define __exitdata __section(.exit.data) | 45 | #define __exitdata __section(.exit.data) |
@@ -86,7 +86,8 @@ | |||
86 | #define __exit __section(.exit.text) __exitused __cold notrace | 86 | #define __exit __section(.exit.text) __exitused __cold notrace |
87 | 87 | ||
88 | /* Used for MEMORY_HOTPLUG */ | 88 | /* Used for MEMORY_HOTPLUG */ |
89 | #define __meminit __section(.meminit.text) __cold notrace | 89 | #define __meminit __section(.meminit.text) __cold notrace \ |
90 | __latent_entropy | ||
90 | #define __meminitdata __section(.meminit.data) | 91 | #define __meminitdata __section(.meminit.data) |
91 | #define __meminitconst __constsection(.meminit.rodata) | 92 | #define __meminitconst __constsection(.meminit.rodata) |
92 | #define __memexit __section(.memexit.text) __exitused __cold notrace | 93 | #define __memexit __section(.memexit.text) __exitused __cold notrace |
diff --git a/include/linux/random.h b/include/linux/random.h index a59c74cdb1eb..d80a4388a4fd 100644 --- a/include/linux/random.h +++ b/include/linux/random.h | |||
@@ -30,8 +30,8 @@ static inline void add_latent_entropy(void) {} | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | extern void add_input_randomness(unsigned int type, unsigned int code, | 32 | extern void add_input_randomness(unsigned int type, unsigned int code, |
33 | unsigned int value); | 33 | unsigned int value) __latent_entropy; |
34 | extern void add_interrupt_randomness(int irq, int irq_flags); | 34 | extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy; |
35 | 35 | ||
36 | extern void get_random_bytes(void *buf, int nbytes); | 36 | extern void get_random_bytes(void *buf, int nbytes); |
37 | extern int add_random_ready_callback(struct random_ready_callback *rdy); | 37 | extern int add_random_ready_callback(struct random_ready_callback *rdy); |
diff --git a/kernel/fork.c b/kernel/fork.c index 001b18473a07..05393881ef39 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -404,7 +404,8 @@ free_tsk: | |||
404 | } | 404 | } |
405 | 405 | ||
406 | #ifdef CONFIG_MMU | 406 | #ifdef CONFIG_MMU |
407 | static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | 407 | static __latent_entropy int dup_mmap(struct mm_struct *mm, |
408 | struct mm_struct *oldmm) | ||
408 | { | 409 | { |
409 | struct vm_area_struct *mpnt, *tmp, *prev, **pprev; | 410 | struct vm_area_struct *mpnt, *tmp, *prev, **pprev; |
410 | struct rb_node **rb_link, *rb_parent; | 411 | struct rb_node **rb_link, *rb_parent; |
@@ -1296,7 +1297,8 @@ init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) | |||
1296 | * parts of the process environment (as per the clone | 1297 | * parts of the process environment (as per the clone |
1297 | * flags). The actual kick-off is left to the caller. | 1298 | * flags). The actual kick-off is left to the caller. |
1298 | */ | 1299 | */ |
1299 | static struct task_struct *copy_process(unsigned long clone_flags, | 1300 | static __latent_entropy struct task_struct *copy_process( |
1301 | unsigned long clone_flags, | ||
1300 | unsigned long stack_start, | 1302 | unsigned long stack_start, |
1301 | unsigned long stack_size, | 1303 | unsigned long stack_size, |
1302 | int __user *child_tidptr, | 1304 | int __user *child_tidptr, |
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c index 944b1b491ed8..1898559e6b60 100644 --- a/kernel/rcu/tiny.c +++ b/kernel/rcu/tiny.c | |||
@@ -170,7 +170,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
170 | false)); | 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 | __rcu_process_callbacks(&rcu_sched_ctrlblk); | 175 | __rcu_process_callbacks(&rcu_sched_ctrlblk); |
176 | __rcu_process_callbacks(&rcu_bh_ctrlblk); | 176 | __rcu_process_callbacks(&rcu_bh_ctrlblk); |
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 5d80925e7fc8..e5164deb51e1 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
@@ -3013,7 +3013,7 @@ __rcu_process_callbacks(struct rcu_state *rsp) | |||
3013 | /* | 3013 | /* |
3014 | * Do RCU core processing for the current CPU. | 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 | struct rcu_state *rsp; | 3018 | struct rcu_state *rsp; |
3019 | 3019 | ||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 039de34f1521..004996df2f10 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
@@ -8283,7 +8283,7 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) { } | |||
8283 | * run_rebalance_domains is triggered when needed from the scheduler tick. | 8283 | * run_rebalance_domains is triggered when needed from the scheduler tick. |
8284 | * Also triggered for nohz idle balancing (with nohz_balancing_kick set). | 8284 | * Also triggered for nohz idle balancing (with nohz_balancing_kick set). |
8285 | */ | 8285 | */ |
8286 | static void run_rebalance_domains(struct softirq_action *h) | 8286 | static __latent_entropy void run_rebalance_domains(struct softirq_action *h) |
8287 | { | 8287 | { |
8288 | struct rq *this_rq = this_rq(); | 8288 | struct rq *this_rq = this_rq(); |
8289 | enum cpu_idle_type idle = this_rq->idle_balance ? | 8289 | enum cpu_idle_type idle = this_rq->idle_balance ? |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 17caf4b63342..34033fd09c8c 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -482,7 +482,7 @@ void __tasklet_hi_schedule_first(struct tasklet_struct *t) | |||
482 | } | 482 | } |
483 | EXPORT_SYMBOL(__tasklet_hi_schedule_first); | 483 | EXPORT_SYMBOL(__tasklet_hi_schedule_first); |
484 | 484 | ||
485 | static void tasklet_action(struct softirq_action *a) | 485 | static __latent_entropy void tasklet_action(struct softirq_action *a) |
486 | { | 486 | { |
487 | struct tasklet_struct *list; | 487 | struct tasklet_struct *list; |
488 | 488 | ||
@@ -518,7 +518,7 @@ static void tasklet_action(struct softirq_action *a) | |||
518 | } | 518 | } |
519 | } | 519 | } |
520 | 520 | ||
521 | static void tasklet_hi_action(struct softirq_action *a) | 521 | static __latent_entropy void tasklet_hi_action(struct softirq_action *a) |
522 | { | 522 | { |
523 | struct tasklet_struct *list; | 523 | struct tasklet_struct *list; |
524 | 524 | ||
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 32bf6f75a8fe..2d47980a1bc4 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c | |||
@@ -1633,7 +1633,7 @@ static inline void __run_timers(struct timer_base *base) | |||
1633 | /* | 1633 | /* |
1634 | * This function runs timers and the timer-tq in bottom half context. | 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 | struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); | 1638 | struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); |
1639 | 1639 | ||
diff --git a/lib/irq_poll.c b/lib/irq_poll.c index 836f7db4e548..63be7495dbb2 100644 --- a/lib/irq_poll.c +++ b/lib/irq_poll.c | |||
@@ -74,7 +74,7 @@ void irq_poll_complete(struct irq_poll *iop) | |||
74 | } | 74 | } |
75 | EXPORT_SYMBOL(irq_poll_complete); | 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 | struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll); | 79 | struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll); |
80 | int rearm = 0, budget = irq_poll_budget; | 80 | int rearm = 0, budget = irq_poll_budget; |
diff --git a/lib/random32.c b/lib/random32.c index 69ed593aab07..a30923573676 100644 --- a/lib/random32.c +++ b/lib/random32.c | |||
@@ -47,7 +47,7 @@ static inline void prandom_state_selftest(void) | |||
47 | } | 47 | } |
48 | #endif | 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 | * prandom_u32_state - seeded pseudo-random number generator. | 53 | * prandom_u32_state - seeded pseudo-random number generator. |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 248851d1fc86..901121af4e54 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -92,7 +92,7 @@ int _node_numa_mem_[MAX_NUMNODES]; | |||
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY | 94 | #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY |
95 | volatile u64 latent_entropy; | 95 | volatile u64 latent_entropy __latent_entropy; |
96 | EXPORT_SYMBOL(latent_entropy); | 96 | EXPORT_SYMBOL(latent_entropy); |
97 | #endif | 97 | #endif |
98 | 98 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index ea6312057a71..ee076c2791f9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3855,7 +3855,7 @@ int netif_rx_ni(struct sk_buff *skb) | |||
3855 | } | 3855 | } |
3856 | EXPORT_SYMBOL(netif_rx_ni); | 3856 | EXPORT_SYMBOL(netif_rx_ni); |
3857 | 3857 | ||
3858 | static void net_tx_action(struct softirq_action *h) | 3858 | static __latent_entropy void net_tx_action(struct softirq_action *h) |
3859 | { | 3859 | { |
3860 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); | 3860 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); |
3861 | 3861 | ||
@@ -5187,7 +5187,7 @@ out_unlock: | |||
5187 | return work; | 5187 | return work; |
5188 | } | 5188 | } |
5189 | 5189 | ||
5190 | static void net_rx_action(struct softirq_action *h) | 5190 | static __latent_entropy void net_rx_action(struct softirq_action *h) |
5191 | { | 5191 | { |
5192 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); | 5192 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); |
5193 | unsigned long time_limit = jiffies + 2; | 5193 | unsigned long time_limit = jiffies + 2; |