From 46234253b9363894a254844a6550b4cc5f3edfe8 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 8 Oct 2015 01:20:35 +0200 Subject: net: move net_get_random_once to lib There's no good reason why users outside of networking should not be using this facility, f.e. for initializing their seeds. Therefore, make it accessible from there as get_random_once(). Signed-off-by: Hannes Frederic Sowa Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- lib/Makefile | 3 ++- lib/once.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 lib/once.c (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index 13a7c6ae3fec..8de3b012eac7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -26,7 +26,8 @@ obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ bsearch.o find_bit.o llist.o memweight.o kfifo.o \ - percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o + percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o \ + once.o obj-y += string_helpers.o obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o obj-y += hexdump.o diff --git a/lib/once.c b/lib/once.c new file mode 100644 index 000000000000..2d5a7de17aba --- /dev/null +++ b/lib/once.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +struct __random_once_work { + struct work_struct work; + struct static_key *key; +}; + +static void __random_once_deferred(struct work_struct *w) +{ + struct __random_once_work *work; + + work = container_of(w, struct __random_once_work, work); + BUG_ON(!static_key_enabled(work->key)); + static_key_slow_dec(work->key); + kfree(work); +} + +static void __random_once_disable_jump(struct static_key *key) +{ + struct __random_once_work *w; + + w = kmalloc(sizeof(*w), GFP_ATOMIC); + if (!w) + return; + + INIT_WORK(&w->work, __random_once_deferred); + w->key = key; + schedule_work(&w->work); +} + +bool __get_random_once(void *buf, int nbytes, bool *done, + struct static_key *once_key) +{ + static DEFINE_SPINLOCK(lock); + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + if (*done) { + spin_unlock_irqrestore(&lock, flags); + return false; + } + + get_random_bytes(buf, nbytes); + *done = true; + spin_unlock_irqrestore(&lock, flags); + + __random_once_disable_jump(once_key); + + return true; +} +EXPORT_SYMBOL(__get_random_once); -- cgit v1.2.3