Skip to content

Commit

Permalink
net: move net_get_random_once to lib
Browse files Browse the repository at this point in the history
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 <hannes@stressinduktion.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Hannes Frederic Sowa authored and David S. Miller committed Oct 8, 2015
1 parent 28335a7 commit 4623425
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 67 deletions.
21 changes: 4 additions & 17 deletions include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
#include <linux/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK */
#include <linux/kmemcheck.h>
#include <linux/rcupdate.h>
#include <linux/jump_label.h>
#include <linux/once.h>

#include <uapi/linux/net.h>

struct poll_table_struct;
Expand Down Expand Up @@ -250,22 +251,8 @@ do { \
} while (0)
#endif

bool __net_get_random_once(void *buf, int nbytes, bool *done,
struct static_key *done_key);

#define net_get_random_once(buf, nbytes) \
({ \
bool ___ret = false; \
static bool ___done = false; \
static struct static_key ___once_key = \
STATIC_KEY_INIT_TRUE; \
if (static_key_true(&___once_key)) \
___ret = __net_get_random_once(buf, \
nbytes, \
&___done, \
&___once_key); \
___ret; \
})
#define net_get_random_once(buf, nbytes) \
get_random_once((buf), (nbytes))

int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
size_t num, size_t len);
Expand Down
24 changes: 24 additions & 0 deletions include/linux/once.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef _LINUX_ONCE_H
#define _LINUX_ONCE_H

#include <linux/types.h>
#include <linux/jump_label.h>

bool __get_random_once(void *buf, int nbytes, bool *done,
struct static_key *once_key);

#define get_random_once(buf, nbytes) \
({ \
bool ___ret = false; \
static bool ___done = false; \
static struct static_key ___once_key = \
STATIC_KEY_INIT_TRUE; \
if (static_key_true(&___once_key)) \
___ret = __get_random_once((buf), \
(nbytes), \
&___done, \
&___once_key); \
___ret; \
})

#endif /* _LINUX_ONCE_H */
3 changes: 2 additions & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 54 additions & 0 deletions lib/once.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/once.h>
#include <linux/random.h>

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);
49 changes: 0 additions & 49 deletions net/core/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,52 +348,3 @@ void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
}
}
EXPORT_SYMBOL(inet_proto_csum_replace_by_diff);

struct __net_random_once_work {
struct work_struct work;
struct static_key *key;
};

static void __net_random_once_deferred(struct work_struct *w)
{
struct __net_random_once_work *work =
container_of(w, struct __net_random_once_work, work);
BUG_ON(!static_key_enabled(work->key));
static_key_slow_dec(work->key);
kfree(work);
}

static void __net_random_once_disable_jump(struct static_key *key)
{
struct __net_random_once_work *w;

w = kmalloc(sizeof(*w), GFP_ATOMIC);
if (!w)
return;

INIT_WORK(&w->work, __net_random_once_deferred);
w->key = key;
schedule_work(&w->work);
}

bool __net_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);

__net_random_once_disable_jump(once_key);

return true;
}
EXPORT_SYMBOL(__net_get_random_once);

0 comments on commit 4623425

Please sign in to comment.