aboutsummaryrefslogtreecommitdiffstats
path: root/sys/linux/init_alg_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'sys/linux/init_alg_test.go')
-rw-r--r--sys/linux/init_alg_test.go215
1 files changed, 215 insertions, 0 deletions
diff --git a/sys/linux/init_alg_test.go b/sys/linux/init_alg_test.go
new file mode 100644
index 000000000..b3622a6c9
--- /dev/null
+++ b/sys/linux/init_alg_test.go
@@ -0,0 +1,215 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build linux
+
+package linux
+
+import (
+ "flag"
+ "fmt"
+ "math/rand"
+ "strings"
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+// AF_ALG tests won't generally pass and intended for manual testing.
+// First, they require fresh kernel with _all_ crypto algorithms enabled.
+// Second, they require the newest hardware with all of SSE/AVX.
+// Finally, they still won't pass because some algorithms are arch-dependent.
+var flagRunAlgTests = flag.Bool("algtests", false, "run AF_ALG tests")
+
+func algTest(t *testing.T) {
+ if !*flagRunAlgTests {
+ t.Skip()
+ }
+ t.Parallel()
+}
+
+// TestAlgDescriptions checks that there are no duplicate names and that
+// templates mentioned in complete algorithms are also present as standalone templates.
+func TestAlgDescriptions(t *testing.T) {
+ algTest(t)
+ allall := make(map[string]bool)
+ for typ, algList := range allAlgs {
+ algs := make(map[string]bool)
+ templates := make(map[string]bool)
+ for _, alg := range algList {
+ allall[alg.name] = true
+ if algs[alg.name] {
+ t.Errorf("duplicate: %v", alg.name)
+ }
+ algs[alg.name] = true
+ if len(alg.args) > 0 {
+ templates[alg.name] = true
+ }
+ }
+ for _, alg := range algList {
+ if len(alg.args) > 0 || strings.HasPrefix(alg.name, "__") {
+ continue
+ }
+ brace := strings.IndexByte(alg.name, '(')
+ if brace == -1 {
+ continue
+ }
+ templ := alg.name[:brace]
+ if !templates[templ] {
+ t.Errorf("template %v is missing for type %v", templ, typ)
+ }
+ templates[templ] = true
+ }
+ }
+}
+
+// TestSingleAlg tests creation of all algorithms (not templates).
+func TestSingleAlg(t *testing.T) {
+ algTest(t)
+ for _, typ := range allTypes {
+ for _, alg := range allAlgs[typ.typ] {
+ if len(alg.args) != 0 {
+ continue
+ }
+ ok, skip := testAlg(t, typ.name, alg.name)
+ if skip {
+ t.Errorf("SKIP\t%10v\t%v", typ.name, alg.name)
+ continue
+ }
+ if !ok {
+ t.Errorf("FAIL\t%10v\t%v", typ.name, alg.name)
+ continue
+ }
+ }
+ }
+}
+
+// TestTemplateAlg1 tests creation of all templates with 1 argument.
+func TestTemplateAlg1(t *testing.T) {
+ algTest(t)
+ for _, typ := range allTypes {
+ for _, alg := range allAlgs[typ.typ] {
+ if len(alg.args) != 1 {
+ continue
+ }
+ var works []int
+ nextType:
+ for typ1, algs1 := range allAlgs {
+ var selection []algDesc
+ for _, x := range rand.Perm(len(algs1)) {
+ if len(algs1[x].args) != 0 {
+ continue
+ }
+ selection = append(selection, algs1[x])
+ if len(selection) == 10 {
+ break
+ }
+ }
+ for _, alg1 := range selection {
+ name := fmt.Sprintf("%v(%v)", alg.name, alg1.name)
+ ok, _ := testAlg(t, typ.name, name)
+ if ok {
+ works = append(works, typ1)
+ continue nextType
+ }
+ }
+ }
+ if len(works) == 1 && works[0] == alg.args[0] {
+ continue
+ }
+ t.Errorf("FAIL\t%10v\t%v\tclaimed %v works with %v",
+ typ.name, alg.name, alg.args[0], works)
+ }
+ }
+}
+
+// TestTemplateAlg2 tests creation of all templates with 2 argument.
+func TestTemplateAlg2(t *testing.T) {
+ algTest(t)
+ // Can't affort to test all permutations of 2 algorithms,
+ // 20 algorithm pairs for each type pair and use them.
+ selections := make(map[int][]int)
+ for typ1, algs1 := range allAlgs {
+ for typ2, algs2 := range allAlgs {
+ var pairs []int
+ for i1, alg1 := range algs1 {
+ if len(alg1.args) != 0 {
+ continue
+ }
+ for i2, alg2 := range algs2 {
+ if len(alg2.args) != 0 {
+ continue
+ }
+ pairs = append(pairs, i1*1000+i2)
+ }
+ }
+ var selection []int
+ for _, x := range rand.Perm(len(pairs)) {
+ selection = append(selection, pairs[x])
+ if len(selection) > 20 {
+ break
+ }
+ }
+ selections[typ1*1000+typ2] = selection
+ }
+ }
+ for _, typ := range allTypes {
+ for _, alg := range allAlgs[typ.typ] {
+ if len(alg.args) != 2 {
+ continue
+ }
+ for typ1, algs1 := range allAlgs {
+ for typ2, algs2 := range allAlgs {
+ selection := selections[typ1*1000+typ2]
+ for _, x := range selection {
+ alg1 := algs1[x/1000]
+ alg2 := algs2[x%1000]
+ name := fmt.Sprintf("%v(%v,%v)",
+ alg.name, alg1.name, alg2.name)
+ if ok, _ := testAlg(t, typ.name, name); ok {
+ t.Logf("%10v\t%v\tclaimed %v works with %v/%v (%v)",
+ typ.name, alg.name, alg.args, typ1, typ2, name)
+ break
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+type sockaddrAlg struct {
+ family uint16
+ typ [14]byte
+ feat uint32
+ mask uint32
+ name [64]byte
+}
+
+func testAlg(t *testing.T, typ, name string) (ok, skip bool) {
+ const AF_ALG = 0x26
+ addr := &sockaddrAlg{
+ family: AF_ALG,
+ }
+ if len(typ) >= int(unsafe.Sizeof(addr.typ)) ||
+ len(name) >= int(unsafe.Sizeof(addr.name)) {
+ return false, true
+ }
+ for i := 0; i < len(typ); i++ {
+ addr.typ[i] = typ[i]
+ }
+ for i := 0; i < len(name); i++ {
+ addr.name[i] = name[i]
+ }
+ sock, err := syscall.Socket(AF_ALG, syscall.SOCK_SEQPACKET, 0)
+ if err != nil {
+ t.Fatalf("failed to create AF_ALG socket: %v", err)
+ }
+ defer syscall.Close(sock)
+ _, _, errno := syscall.Syscall(syscall.SYS_BIND, uintptr(sock),
+ uintptr(unsafe.Pointer(addr)), unsafe.Sizeof(*addr))
+ if errno != 0 {
+ return false, false
+ }
+ return true, false
+}