Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern thmap: Use keyed BLAKE2s for second-level hash and ...
details: https://anonhg.NetBSD.org/src/rev/00b00aca1566
branches: trunk
changeset: 943345:00b00aca1566
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Aug 31 20:22:57 2020 +0000
description:
thmap: Use keyed BLAKE2s for second-level hash and beyond.
This thwarts hash-flooding, but pays the cost only for those keys
that collide under the cheaper murmurhash2.
diffstat:
sys/kern/subr_thmap.c | 59 ++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 49 insertions(+), 10 deletions(-)
diffs (152 lines):
diff -r 69fc7dae5083 -r 00b00aca1566 sys/kern/subr_thmap.c
--- a/sys/kern/subr_thmap.c Mon Aug 31 20:21:30 2020 +0000
+++ b/sys/kern/subr_thmap.c Mon Aug 31 20:22:57 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_thmap.c,v 1.6 2020/05/23 19:52:12 rmind Exp $ */
+/* $NetBSD: subr_thmap.c,v 1.7 2020/08/31 20:22:57 riastradh Exp $ */
/*-
* Copyright (c) 2018 Mindaugas Rasiukevicius <rmind at noxt eu>
@@ -96,6 +96,7 @@
#include <sys/lock.h>
#include <sys/atomic.h>
#include <sys/hash.h>
+#include <sys/cprng.h>
#define THMAP_RCSID(a) __KERNEL_RCSID(0, a)
#else
#include <stdio.h>
@@ -111,7 +112,9 @@
#include "utils.h"
#endif
-THMAP_RCSID("$NetBSD: subr_thmap.c,v 1.6 2020/05/23 19:52:12 rmind Exp $");
+THMAP_RCSID("$NetBSD: subr_thmap.c,v 1.7 2020/08/31 20:22:57 riastradh Exp $");
+
+#include <crypto/blake2/blake2s.h>
/*
* NetBSD kernel wrappers
@@ -135,6 +138,7 @@
* The hash function produces 32-bit values.
*/
+#define HASHVAL_SEEDLEN (16)
#define HASHVAL_BITS (32)
#define HASHVAL_MOD (HASHVAL_BITS - 1)
#define HASHVAL_SHIFT (5)
@@ -201,6 +205,7 @@
} thmap_leaf_t;
typedef struct {
+ const uint8_t * seed; // secret seed
unsigned rslot; // root-level slot index
unsigned level; // current level in the tree
unsigned hashidx; // current hash index (block of bits)
@@ -221,6 +226,7 @@
unsigned flags;
const thmap_ops_t * ops;
thmap_gc_t * gc_list; // C11 _Atomic
+ uint8_t seed[HASHVAL_SEEDLEN];
};
static void stage_mem_gc(thmap_t *, uintptr_t, size_t);
@@ -291,11 +297,41 @@
* HASH VALUE AND KEY OPERATIONS.
*/
-static inline void
-hashval_init(thmap_query_t *query, const void * restrict key, size_t len)
+static inline uint32_t
+hash(const uint8_t seed[static HASHVAL_SEEDLEN], const void *key, size_t len,
+ uint32_t level)
{
- const uint32_t hashval = murmurhash3(key, len, 0);
+ struct blake2s B;
+ uint32_t h;
+
+ if (level == 0)
+ return murmurhash3(key, len, 0);
+ /*
+ * Byte order is not significant here because this is
+ * intentionally secret and independent for each thmap.
+ *
+ * XXX We get 32 bytes of output at a time; we could march
+ * through them sequentially rather than throwing away 28 bytes
+ * and recomputing BLAKE2 each time. But the number of
+ * iterations ought to be geometric in the collision
+ * probability at each level which should be very small anyway.
+ */
+ blake2s_init(&B, sizeof h, seed, HASHVAL_SEEDLEN);
+ blake2s_update(&B, &level, sizeof level);
+ blake2s_update(&B, key, len);
+ blake2s_final(&B, &h);
+
+ return h;
+}
+
+static inline void
+hashval_init(thmap_query_t *query, const uint8_t seed[static HASHVAL_SEEDLEN],
+ const void * restrict key, size_t len)
+{
+ const uint32_t hashval = hash(seed, key, len, 0);
+
+ query->seed = seed;
query->rslot = ((hashval >> ROOT_MSBITS) ^ len) & ROOT_MASK;
query->level = 0;
query->hashval = hashval;
@@ -315,7 +351,7 @@
if (query->hashidx != i) {
/* Generate a hash value for a required range. */
- query->hashval = murmurhash3(key, len, i);
+ query->hashval = hash(query->seed, key, len, i);
query->hashidx = i;
}
return (query->hashval >> shift) & LEVEL_MASK;
@@ -330,7 +366,7 @@
const unsigned shift = offset & HASHVAL_MOD;
const unsigned i = offset >> HASHVAL_SHIFT;
- return (murmurhash3(key, leaf->len, i) >> shift) & LEVEL_MASK;
+ return (hash(thmap->seed, key, leaf->len, i) >> shift) & LEVEL_MASK;
}
static inline unsigned
@@ -627,7 +663,7 @@
thmap_leaf_t *leaf;
unsigned slot;
- hashval_init(&query, key, len);
+ hashval_init(&query, thmap->seed, key, len);
parent = find_edge_node(thmap, &query, key, len, &slot);
if (!parent) {
return NULL;
@@ -664,7 +700,7 @@
if (__predict_false(!leaf)) {
return NULL;
}
- hashval_init(&query, key, len);
+ hashval_init(&query, thmap->seed, key, len);
retry:
/*
* Try to insert into the root first, if its slot is empty.
@@ -780,7 +816,7 @@
unsigned slot;
void *val;
- hashval_init(&query, key, len);
+ hashval_init(&query, thmap->seed, key, len);
parent = find_edge_node_locked(thmap, &query, key, len, &slot);
if (!parent) {
/* Root slot empty: not found. */
@@ -954,6 +990,9 @@
memset(thmap->root, 0, THMAP_ROOT_LEN);
atomic_thread_fence(memory_order_release); /* XXX */
}
+
+ cprng_strong(kern_cprng, thmap->seed, sizeof thmap->seed, 0);
+
return thmap;
}
Home |
Main Index |
Thread Index |
Old Index