]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: opportunistically rotate map key seed
authorBenjamin Barenblat <bbaren@google.com>
Thu, 3 Sep 2020 20:36:38 +0000 (16:36 -0400)
committerKeith Randall <khr@golang.org>
Thu, 3 Sep 2020 22:08:58 +0000 (22:08 +0000)
When clearing a map, reinitialize the hash seed with random data. This
makes it more difficult for attackers to trigger pathological
performance via repeated hash collisions.

The extra reinitialization causes no statistically significant slowdown:

name                              old time/op  new time/op  delta
GoMapClear/Reflexive/1-12         18.3ns ± 0%  20.0ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/Reflexive/10-12        18.2ns ± 0%  19.8ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/Reflexive/100-12       44.6ns ± 0%  46.1ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/Reflexive/1000-12       592ns ± 0%   592ns ± 0%   ~     (all samples are equal)
GoMapClear/Reflexive/10000-12     3.88µs ± 0%  3.88µs ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/NonReflexive/1-12      62.7ns ± 0%  63.9ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/NonReflexive/10-12     75.0ns ± 0%  76.1ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/NonReflexive/100-12     203ns ± 0%   206ns ± 0%   ~             (p=1.000 n=1+1)
GoMapClear/NonReflexive/1000-12   2.33µs ± 0%  2.33µs ± 0%   ~     (all samples are equal)
GoMapClear/NonReflexive/10000-12  18.1µs ± 0%  18.1µs ± 0%   ~             (p=1.000 n=1+1)

Fixes #25237

Change-Id: I629a79dd7c562ba18bd94159673c3b9b653da643
Reviewed-on: https://go-review.googlesource.com/c/go/+/253020
Reviewed-by: Keith Randall <khr@golang.org>
src/runtime/map.go

index 399c1b071fd703af058d738e80bc8c29a93c0497..22a0241f56e43314332deed240a7612eef69f89f 100644 (file)
@@ -993,6 +993,10 @@ func mapclear(t *maptype, h *hmap) {
        h.noverflow = 0
        h.count = 0
 
+       // Reset the hash seed to make it more difficult for attackers to
+       // repeatedly trigger hash collisions. See issue 25237.
+       h.hash0 = fastrand()
+
        // Keep the mapextra allocation but clear any extra information.
        if h.extra != nil {
                *h.extra = mapextra{}