github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/sys/linux/init_alg_test.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  //go:build linux
     5  
     6  package linux
     7  
     8  import (
     9  	"flag"
    10  	"fmt"
    11  	"math/rand"
    12  	"strings"
    13  	"syscall"
    14  	"testing"
    15  	"unsafe"
    16  )
    17  
    18  // AF_ALG tests won't generally pass and intended for manual testing.
    19  // First, they require fresh kernel with _all_ crypto algorithms enabled.
    20  // Second, they require the newest hardware with all of SSE/AVX.
    21  // Finally, they still won't pass because some algorithms are arch-dependent.
    22  var flagRunAlgTests = flag.Bool("algtests", false, "run AF_ALG tests")
    23  
    24  func algTest(t *testing.T) {
    25  	if !*flagRunAlgTests {
    26  		t.Skip()
    27  	}
    28  	t.Parallel()
    29  }
    30  
    31  // TestAlgDescriptions checks that there are no duplicate names and that
    32  // templates mentioned in complete algorithms are also present as standalone templates.
    33  func TestAlgDescriptions(t *testing.T) {
    34  	algTest(t)
    35  	allall := make(map[string]bool)
    36  	for typ, algList := range allAlgs {
    37  		algs := make(map[string]bool)
    38  		templates := make(map[string]bool)
    39  		for _, alg := range algList {
    40  			allall[alg.name] = true
    41  			if algs[alg.name] {
    42  				t.Errorf("duplicate: %v", alg.name)
    43  			}
    44  			algs[alg.name] = true
    45  			if len(alg.args) > 0 {
    46  				templates[alg.name] = true
    47  			}
    48  		}
    49  		for _, alg := range algList {
    50  			if len(alg.args) > 0 || strings.HasPrefix(alg.name, "__") {
    51  				continue
    52  			}
    53  			brace := strings.IndexByte(alg.name, '(')
    54  			if brace == -1 {
    55  				continue
    56  			}
    57  			templ := alg.name[:brace]
    58  			if !templates[templ] {
    59  				t.Errorf("template %v is missing for type %v", templ, typ)
    60  			}
    61  			templates[templ] = true
    62  		}
    63  	}
    64  }
    65  
    66  // TestSingleAlg tests creation of all algorithms (not templates).
    67  func TestSingleAlg(t *testing.T) {
    68  	algTest(t)
    69  	for _, typ := range allTypes {
    70  		for _, alg := range allAlgs[typ.typ] {
    71  			if len(alg.args) != 0 {
    72  				continue
    73  			}
    74  			ok, skip := testAlg(t, typ.name, alg.name)
    75  			if skip {
    76  				t.Errorf("SKIP\t%10v\t%v", typ.name, alg.name)
    77  				continue
    78  			}
    79  			if !ok {
    80  				t.Errorf("FAIL\t%10v\t%v", typ.name, alg.name)
    81  				continue
    82  			}
    83  		}
    84  	}
    85  }
    86  
    87  // TestTemplateAlg1 tests creation of all templates with 1 argument.
    88  func TestTemplateAlg1(t *testing.T) {
    89  	algTest(t)
    90  	for _, typ := range allTypes {
    91  		for _, alg := range allAlgs[typ.typ] {
    92  			if len(alg.args) != 1 {
    93  				continue
    94  			}
    95  			var works []int
    96  		nextType:
    97  			for typ1, algs1 := range allAlgs {
    98  				var selection []algDesc
    99  				for _, x := range rand.Perm(len(algs1)) {
   100  					if len(algs1[x].args) != 0 {
   101  						continue
   102  					}
   103  					selection = append(selection, algs1[x])
   104  					if len(selection) == 10 {
   105  						break
   106  					}
   107  				}
   108  				for _, alg1 := range selection {
   109  					name := fmt.Sprintf("%v(%v)", alg.name, alg1.name)
   110  					ok, _ := testAlg(t, typ.name, name)
   111  					if ok {
   112  						works = append(works, typ1)
   113  						continue nextType
   114  					}
   115  				}
   116  			}
   117  			if len(works) == 1 && works[0] == alg.args[0] {
   118  				continue
   119  			}
   120  			t.Errorf("FAIL\t%10v\t%v\tclaimed %v works with %v",
   121  				typ.name, alg.name, alg.args[0], works)
   122  		}
   123  	}
   124  }
   125  
   126  // TestTemplateAlg2 tests creation of all templates with 2 argument.
   127  func TestTemplateAlg2(t *testing.T) {
   128  	algTest(t)
   129  	// Can't afford to test all permutations of 2 algorithms,
   130  	// 20 algorithm pairs for each type pair and use them.
   131  	selections := make(map[int][]int)
   132  	for typ1, algs1 := range allAlgs {
   133  		for typ2, algs2 := range allAlgs {
   134  			var pairs []int
   135  			for i1, alg1 := range algs1 {
   136  				if len(alg1.args) != 0 {
   137  					continue
   138  				}
   139  				for i2, alg2 := range algs2 {
   140  					if len(alg2.args) != 0 {
   141  						continue
   142  					}
   143  					pairs = append(pairs, i1*1000+i2)
   144  				}
   145  			}
   146  			var selection []int
   147  			for _, x := range rand.Perm(len(pairs)) {
   148  				selection = append(selection, pairs[x])
   149  				if len(selection) > 20 {
   150  					break
   151  				}
   152  			}
   153  			selections[typ1*1000+typ2] = selection
   154  		}
   155  	}
   156  	for _, typ := range allTypes {
   157  		for _, alg := range allAlgs[typ.typ] {
   158  			if len(alg.args) != 2 {
   159  				continue
   160  			}
   161  			for typ1, algs1 := range allAlgs {
   162  				for typ2, algs2 := range allAlgs {
   163  					selection := selections[typ1*1000+typ2]
   164  					for _, x := range selection {
   165  						alg1 := algs1[x/1000]
   166  						alg2 := algs2[x%1000]
   167  						name := fmt.Sprintf("%v(%v,%v)",
   168  							alg.name, alg1.name, alg2.name)
   169  						if ok, _ := testAlg(t, typ.name, name); ok {
   170  							t.Logf("%10v\t%v\tclaimed %v works with %v/%v (%v)",
   171  								typ.name, alg.name, alg.args, typ1, typ2, name)
   172  							break
   173  						}
   174  					}
   175  				}
   176  			}
   177  		}
   178  	}
   179  }
   180  
   181  type sockaddrAlg struct {
   182  	family uint16
   183  	typ    [14]byte
   184  	feat   uint32
   185  	mask   uint32
   186  	name   [64]byte
   187  }
   188  
   189  func testAlg(t *testing.T, typ, name string) (ok, skip bool) {
   190  	const AF_ALG = 0x26
   191  	addr := &sockaddrAlg{
   192  		family: AF_ALG,
   193  		feat:   0,
   194  		mask:   0,
   195  	}
   196  	if len(typ) >= int(unsafe.Sizeof(addr.typ)) ||
   197  		len(name) >= int(unsafe.Sizeof(addr.name)) {
   198  		return false, true
   199  	}
   200  	for i := 0; i < len(typ); i++ {
   201  		addr.typ[i] = typ[i]
   202  	}
   203  	for i := 0; i < len(name); i++ {
   204  		addr.name[i] = name[i]
   205  	}
   206  	sock, err := syscall.Socket(AF_ALG, syscall.SOCK_SEQPACKET, 0)
   207  	if err != nil {
   208  		t.Fatalf("failed to create AF_ALG socket: %v", err)
   209  	}
   210  	defer syscall.Close(sock)
   211  	_, _, errno := syscall.Syscall(syscall.SYS_BIND, uintptr(sock),
   212  		uintptr(unsafe.Pointer(addr)), unsafe.Sizeof(*addr))
   213  	if errno != 0 {
   214  		return false, false
   215  	}
   216  	return true, false
   217  }
   218  
   219  func TestAlgDups(t *testing.T) {
   220  	dups := make(map[string]bool)
   221  	for _, algs := range allAlgs {
   222  		for _, alg := range algs {
   223  			key := fmt.Sprintf("%v(%v)", alg.name, alg.args)
   224  			if dups[key] {
   225  				t.Errorf("duplicate alg: %+v", alg)
   226  			}
   227  			dups[key] = true
   228  		}
   229  	}
   230  }