Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7dcade39 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net_get_random_once'



Hannes Frederic Sowa says:

====================
This series implements support for delaying the initialization of secret
keys, e.g. used for hashing, for as long as possible. This functionality
is implemented by a new macro, net_get_random_bytes.

I already used it to protect the socket hashes, the syncookie secret
(most important) and the tcp_fastopen secrets.

Changelog:
v2) Use static_keys in net_get_random_once to have as minimal impact to
    the fast-path as possible.
v3) added patch "static_key: WARN on usage before jump_label_init was called":
    Patch "x86/jump_label: expect default_nop if static_key gets enabled
    on boot-up" relaxes the checks for using static_key primitives before
    jump_label_init. So tighten them first.
v4) Update changelog on the patch "static_key: WARN on usage before
    jump_label_init was called"

Included patches:
 ipv4: split inet_ehashfn to hash functions per compilation unit
 ipv6: split inet6_ehashfn to hash functions per compilation unit
 static_key: WARN on usage before jump_label_init was called
 x86/jump_label: expect default_nop if static_key gets enabled on boot-up
 net: introduce new macro net_get_random_once
 inet: split syncookie keys for ipv4 and ipv6 and initialize with net_get_random_once
 inet: convert inet_ehash_secret and ipv6_hash_secret to net_get_random_once
 tcp: switch tcp_fastopen key generation to net_get_random_once
 net: switch net_secret key generation to net_get_random_once
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 53481da3 e34c9a69
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -42,15 +42,27 @@ static void __jump_label_transform(struct jump_entry *entry,
				   int init)
{
	union jump_code_union code;
	const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
	const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];

	if (type == JUMP_LABEL_ENABLE) {
		if (init) {
			/*
			 * Jump label is enabled for the first time.
			 * So we expect a default_nop...
			 */
			if (unlikely(memcmp((void *)entry->code, default_nop, 5)
				     != 0))
				bug_at((void *)entry->code, __LINE__);
		} else {
			/*
		 * We are enabling this jump label. If it is not a nop
		 * then something must have gone wrong.
			 * ...otherwise expect an ideal_nop. Otherwise
			 * something went horribly wrong.
			 */
		if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) != 0))
			if (unlikely(memcmp((void *)entry->code, ideal_nop, 5)
				     != 0))
				bug_at((void *)entry->code, __LINE__);
		}

		code.jump = 0xe9;
		code.offset = entry->target -
@@ -63,7 +75,6 @@ static void __jump_label_transform(struct jump_entry *entry,
		 * are converting the default nop to the ideal nop.
		 */
		if (init) {
			const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
			if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0))
				bug_at((void *)entry->code, __LINE__);
		} else {
+10 −0
Original line number Diff line number Diff line
@@ -48,6 +48,13 @@

#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/bug.h>

extern bool static_key_initialized;

#define STATIC_KEY_CHECK_USE() WARN(!static_key_initialized,		      \
				    "%s used before call to jump_label_init", \
				    __func__)

#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)

@@ -128,6 +135,7 @@ struct static_key {

static __always_inline void jump_label_init(void)
{
	static_key_initialized = true;
}

static __always_inline bool static_key_false(struct static_key *key)
@@ -146,11 +154,13 @@ static __always_inline bool static_key_true(struct static_key *key)

static inline void static_key_slow_inc(struct static_key *key)
{
	STATIC_KEY_CHECK_USE();
	atomic_inc(&key->enabled);
}

static inline void static_key_slow_dec(struct static_key *key)
{
	STATIC_KEY_CHECK_USE();
	atomic_dec(&key->enabled);
}

+2 −0
Original line number Diff line number Diff line
@@ -23,12 +23,14 @@ struct static_key_deferred {
};
static inline void static_key_slow_dec_deferred(struct static_key_deferred *key)
{
	STATIC_KEY_CHECK_USE();
	static_key_slow_dec(&key->key);
}
static inline void
jump_label_rate_limit(struct static_key_deferred *key,
		unsigned long rl)
{
	STATIC_KEY_CHECK_USE();
}
#endif	/* HAVE_JUMP_LABEL */
#endif	/* _LINUX_JUMP_LABEL_RATELIMIT_H */
+25 −0
Original line number Diff line number Diff line
@@ -239,6 +239,31 @@ do { \
#define net_random()		prandom_u32()
#define net_srandom(seed)	prandom_seed((__force u32)(seed))

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

#ifdef HAVE_JUMP_LABEL
#define ___NET_RANDOM_STATIC_KEY_INIT ((struct static_key) \
		{ .enabled = ATOMIC_INIT(0), .entries = (void *)1 })
#else /* !HAVE_JUMP_LABEL */
#define ___NET_RANDOM_STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
#endif /* HAVE_JUMP_LABEL */

/* BE CAREFUL: this function is not interrupt safe */
#define net_get_random_once(buf, nbytes)				\
	({								\
		bool ___ret = false;					\
		static bool ___done = false;				\
		static struct static_key ___done_key =			\
			___NET_RANDOM_STATIC_KEY_INIT;			\
		if (!static_key_true(&___done_key))			\
			___ret = __net_get_random_once(buf,		\
						       nbytes,		\
						       &___done,	\
						       &___done_key);	\
		___ret;							\
	})

int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
		   size_t num, size_t len);
int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
+7 −21
Original line number Diff line number Diff line
@@ -28,28 +28,14 @@

struct inet_hashinfo;

static inline unsigned int inet6_ehashfn(struct net *net,
				const struct in6_addr *laddr, const u16 lport,
				const struct in6_addr *faddr, const __be16 fport)
static inline unsigned int __inet6_ehashfn(const u32 lhash,
				    const u16 lport,
				    const u32 fhash,
				    const __be16 fport,
				    const u32 initval)
{
	u32 ports = (((u32)lport) << 16) | (__force u32)fport;

	return jhash_3words((__force u32)laddr->s6_addr32[3],
			    ipv6_addr_jhash(faddr),
			    ports,
			    inet_ehash_secret + net_hash_mix(net));
}

static inline int inet6_sk_ehashfn(const struct sock *sk)
{
	const struct inet_sock *inet = inet_sk(sk);
	const struct in6_addr *laddr = &sk->sk_v6_rcv_saddr;
	const struct in6_addr *faddr = &sk->sk_v6_daddr;
	const __u16 lport = inet->inet_num;
	const __be16 fport = inet->inet_dport;
	struct net *net = sock_net(sk);

	return inet6_ehashfn(net, laddr, lport, faddr, fport);
	const u32 ports = (((u32)lport) << 16) | (__force u32)fport;
	return jhash_3words(lhash, fhash, ports, initval);
}

int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
Loading