github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-query-subsystems/query_subsystems.go (about) 1 // Copyright 2023 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 // syz-query-subsystems generates and saves the subsystem lists in the format syzkaller understands. 5 // An example how to generate the linux subsystem list (for the upstream kernel). 6 // `./syz-query-subsystems -os linux -kernel ~/linux -syzkaller ~/syzkaller -name linux`. 7 8 package main 9 10 import ( 11 "flag" 12 "fmt" 13 "path/filepath" 14 "regexp" 15 "strings" 16 17 "github.com/google/syzkaller/pkg/osutil" 18 "github.com/google/syzkaller/pkg/subsystem" 19 "github.com/google/syzkaller/pkg/subsystem/linux" 20 "github.com/google/syzkaller/pkg/tool" 21 "github.com/google/syzkaller/pkg/vcs" 22 ) 23 24 var ( 25 flagOS = flag.String("os", "", "target OS type") 26 flagKernelRepo = flag.String("kernel", "", "path to the OS kernel source directory") 27 flagSyzkallerRepo = flag.String("syzkaller", "", "path to the syzkaller repo") 28 flagName = flag.String("name", "", "the name under which the list should be saved") 29 flagFilter = flag.String("filter", "", "comma-separated list of subsystems to keep") 30 flagEmails = flag.Bool("emails", true, "save lists and maintainer fields") 31 ) 32 33 var nameRe = regexp.MustCompile(`^[a-z]\w*$`) 34 35 func main() { 36 defer tool.Init()() 37 // Validate the input. 38 if strings.ToLower(*flagOS) != "linux" { 39 tool.Failf("only Linux is supported at the moment") 40 } 41 if !osutil.IsExist(*flagKernelRepo) { 42 tool.Failf("the specified kernel repo does not exist") 43 } 44 if !osutil.IsExist(*flagSyzkallerRepo) { 45 tool.Failf("the specified syzkaller repo does not exist") 46 } 47 if !nameRe.MatchString(*flagName) { 48 tool.Failf("the name is not acceptable") 49 } 50 // Query the subsystems. 51 list, err := linux.ListFromRepo(*flagKernelRepo) 52 if err != nil { 53 tool.Failf("failed to query subsystems: %v", err) 54 } 55 list = postProcessList(list) 56 // Save the list. 57 folder := filepath.Join(*flagSyzkallerRepo, "pkg", "subsystem", "lists") 58 if err = osutil.MkdirAll(folder); err != nil { 59 tool.Failf("failed to create %s: %v", folder, err) 60 } 61 commitInfo := determineCommitInfo(*flagKernelRepo) 62 code, err := generateSubsystemsFile(*flagName, list, commitInfo) 63 if err != nil { 64 tool.Failf("failed to generate code: %s", err) 65 } 66 err = osutil.WriteFile(filepath.Join(folder, *flagName+".go"), code) 67 if err != nil { 68 tool.Failf("failed to save the code: %s", err) 69 } 70 } 71 72 func postProcessList(list []*subsystem.Subsystem) []*subsystem.Subsystem { 73 if *flagFilter != "" { 74 list = subsystem.FilterList(list, prepareFilter()) 75 } 76 if !*flagEmails { 77 for _, item := range list { 78 item.Lists = nil 79 item.Maintainers = nil 80 } 81 } 82 return list 83 } 84 85 func prepareFilter() func(*subsystem.Subsystem) bool { 86 keep := map[string]bool{} 87 for _, name := range strings.Split(*flagFilter, ",") { 88 name = strings.TrimSpace(name) 89 if name != "" { 90 keep[name] = true 91 } 92 } 93 return func(s *subsystem.Subsystem) bool { 94 return keep[s.Name] 95 } 96 } 97 98 func determineCommitInfo(dir string) string { 99 // Best effort only. 100 repo, err := vcs.NewRepo(*flagOS, "", dir, vcs.OptPrecious, vcs.OptDontSandbox) 101 if err != nil { 102 return fmt.Sprintf("failed to open repo: %v", err) 103 } 104 commit, err := repo.HeadCommit() 105 if err != nil { 106 return fmt.Sprintf("failed to get HEAD commit: %v", err) 107 } 108 return fmt.Sprintf(`Commit %s, "%.32s"`, commit.Hash, commit.Title) 109 }