diff options
Diffstat (limited to 'sys/linux/init_alg_test.go')
| -rw-r--r-- | sys/linux/init_alg_test.go | 215 |
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 +} |
