package main import ( "fmt" "io" "io/ioutil" "os" "path/filepath" "time" "git.thisco.de/vbatts/fuzz-walker/walker" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) var ( dirs = []string{"/sys", "/proc"} fuzzes = map[string]walker.FuzzFunc{ "chmod": chmodFuzz, "read": readFuzz, "writeBytes": writeBytesFuzz, "writeNum": writeNumFuzz, } fuzzTimeout = 500 * time.Millisecond ) func main() { app := cli.NewApp() app.Name = "fuzz-walker" app.Usage = "a walker to poke and prod at /proc and /sys" app.Action = func(c *cli.Context) error { hasError := false for _, dir := range dirs { err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.Mode().IsRegular() { return nil } for fname, fuzz := range fuzzes { if err := fuzz(path, info, fuzzTimeout); err != nil { logrus.Warnf("%s: %q fuzz failed with: %v", path, fname, err) } } return nil }) if err != nil { logrus.Warnf("%s: %v", dir, err) hasError = true } } if hasError { return fmt.Errorf("errors reported") } return nil } app.Run(os.Args) } func readFuzz(path string, info os.FileInfo, timeout time.Duration) error { c1 := make(chan error, 1) go func() { fd, err := os.Open(path) if err != nil { c1 <- err } defer fd.Close() _, err = io.Copy(ioutil.Discard, fd) c1 <- err }() select { case err := <-c1: return err case <-time.After(timeout): return fmt.Errorf("timeout reached") } return nil } func writeNumFuzz(path string, info os.FileInfo, timeout time.Duration) error { return nil } func writeBytesFuzz(path string, info os.FileInfo, timeout time.Duration) error { return nil } func chmodFuzz(path string, info os.FileInfo, timeout time.Duration) error { return nil } // maybe have an ioctl fuzzer