github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-usbgen/usbgen.go (about)

     1  // Copyright 2019 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  package main
     5  
     6  import (
     7  	"encoding/hex"
     8  	"flag"
     9  	"fmt"
    10  	"os"
    11  	"regexp"
    12  	"sort"
    13  
    14  	"github.com/google/syzkaller/pkg/osutil"
    15  	"github.com/google/syzkaller/pkg/tool"
    16  )
    17  
    18  func main() {
    19  	flag.Parse()
    20  	args := flag.Args()
    21  	if len(args) != 2 {
    22  		usage()
    23  	}
    24  
    25  	syslog, err := os.ReadFile(args[0])
    26  	if err != nil {
    27  		tool.Failf("failed to read file %v: %v", args[0], err)
    28  	}
    29  
    30  	usbIds := extractIds(syslog, "USBID", 34)
    31  	hidIds := extractIds(syslog, "HIDID", 24)
    32  
    33  	output := []byte(`// Code generated by tools/syz-usbgen. DO NOT EDIT.
    34  // See docs/linux/external_fuzzing_usb.md
    35  
    36  package linux
    37  
    38  `)
    39  	output = append(output, generateIdsVar(usbIds, "usbIds")...)
    40  	output = append(output, []byte("\n")...)
    41  	output = append(output, generateIdsVar(hidIds, "hidIds")...)
    42  
    43  	if err := osutil.WriteFile(args[1], output); err != nil {
    44  		tool.Failf("failed to output file %v: %v", args[1], err)
    45  	}
    46  }
    47  
    48  func extractIds(syslog []byte, prefix string, size int) []string {
    49  	re := fmt.Sprintf("%s: [0-9a-f]{%d}", prefix, size)
    50  	r := regexp.MustCompile(re)
    51  	matches := r.FindAll(syslog, -1)
    52  	uniqueMatches := make(map[string]bool)
    53  	for _, match := range matches {
    54  		uniqueMatches[string(match)] = true
    55  	}
    56  	sortedMatches := make([]string, 0)
    57  	for match := range uniqueMatches {
    58  		match = match[len(prefix+": "):]
    59  		match = match[:size]
    60  		sortedMatches = append(sortedMatches, match)
    61  	}
    62  	sort.Strings(sortedMatches)
    63  	return sortedMatches
    64  }
    65  
    66  func generateIdsVar(ids []string, name string) []byte {
    67  	output := []byte(fmt.Sprintf("var %s = ", name))
    68  	for i, id := range ids {
    69  		decodedID, err := hex.DecodeString(id)
    70  		if err != nil {
    71  			tool.Failf("failed to decode hex string %v: %v", id, err)
    72  		}
    73  		prefix := "\t"
    74  		suffix := " +"
    75  		if i == 0 {
    76  			prefix = ""
    77  		}
    78  		if i == len(ids)-1 {
    79  			suffix = ""
    80  		}
    81  		outputID := fmt.Sprintf("%v%#v%v\n", prefix, string(decodedID), suffix)
    82  		output = append(output, []byte(outputID)...)
    83  	}
    84  
    85  	if len(ids) == 0 {
    86  		output = append(output, []byte("\"\"")...)
    87  	}
    88  
    89  	fmt.Printf("%v %s ids written\n", len(ids), name)
    90  
    91  	return output
    92  }
    93  
    94  func usage() {
    95  	fmt.Fprintf(os.Stderr, "usage:\n")
    96  	fmt.Fprintf(os.Stderr, "  syz-usbgen syslog.txt sys/linux/init_vusb_ids.go\n")
    97  	os.Exit(1)
    98  }