package main import ( "fmt" "os" "path/filepath" "time" "git.thisco.de/vbatts/fuzz-walker/walker" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) // This list is populated in the beforefunc of the application var walkerPlugins []walker.Fuzzer func main() { app := cli.NewApp() app.Name = "fuzz-walker" app.Usage = "a walker to poke and prod at /proc and /sys" app.Before = func(c *cli.Context) error { matches, err := filepath.Glob(c.String("plugins")) if err != nil { return err } for _, match := range matches { ff, err := walker.LoadPlugin(match) if err != nil { return err } walkerPlugins = append(walkerPlugins, ff) } return nil } app.Flags = []cli.Flag{ cli.StringFlag{ Name: "plugins", Usage: "pattern to glob walker plugins", Value: "*.so", }, cli.DurationFlag{ Name: "timeout", Usage: "timeout in milliseconds for each fuzz function", Value: 500, }, cli.StringSliceFlag{ Name: "paths", Usage: "system paths to poke at with fuzzer plugins", Value: &cli.StringSlice{ "/proc", "/sys", }, }, } app.Action = func(c *cli.Context) error { hasError := false for _, dir := range c.StringSlice("paths") { err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } for _, wp := range walkerPlugins { c1 := make(chan error, 1) go func() { c1 <- wp.Func(path, info, c.Duration("timeout")*time.Millisecond) }() select { case err := <-c1: if err != nil { logrus.Warnf("%s: %q fuzz failed with: %v", path, wp.Name(), err) } case <-time.After(c.Duration("timeout") * time.Millisecond): logrus.Warnf("%s: %q fuzz timed out", path, wp.Name()) } } 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) }