diff --git a/Makefile b/Makefile index eb942b3..a40527c 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ SOURCE_FILES := \ $(wildcard walker/*.go) \ $(wildcard walker/walkers/*/*.go) PLUGINS := \ - plugin-readFuzz.so + $(patsubst walker/walkers/%,plugin-%.so,$(wildcard walker/walkers/*)) default: fuzz-walker $(PLUGINS) @@ -16,4 +16,4 @@ plugin-%.so: $(GO) build -o $@ -buildmode=plugin ./walker/walkers/$*/ clean: - rm -f fuzz-walker *.so + rm -f fuzz-walker *.so *~ diff --git a/main.go b/main.go index fa5f50e..338dbc5 100644 --- a/main.go +++ b/main.go @@ -11,52 +11,67 @@ import ( "github.com/urfave/cli" ) -var ( - dirs = []string{"/sys", "/proc"} - fuzzTimeout = 500 * time.Millisecond - walkerPlugins []walker.Fuzzer -) - -func appInit(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 -} +// 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 = appInit + 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", - Value: "*.so", 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 dirs { + for _, dir := range c.StringSlice("paths") { 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 _, wp := range walkerPlugins { - if err := wp.Func(path, info, fuzzTimeout); err != nil { - logrus.Warnf("%s: %q fuzz failed with: %v", path, wp.Name(), err) + 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 @@ -74,17 +89,3 @@ func main() { app.Run(os.Args) } - -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 diff --git a/walker/walkers/chmodFuzz/plugin.go b/walker/walkers/chmodFuzz/plugin.go new file mode 100644 index 0000000..41430b0 --- /dev/null +++ b/walker/walkers/chmodFuzz/plugin.go @@ -0,0 +1,23 @@ +package main + +import ( + "os" + "time" + + "git.thisco.de/vbatts/fuzz-walker/walker" +) + +// NewFuzzer creates the fuzzer for this plugin +func NewFuzzer() (walker.Fuzzer, error) { + return &myFuzzer{}, nil +} + +type myFuzzer struct{} + +func (mf myFuzzer) Name() string { + return "chmodFuzz" +} + +func (mf myFuzzer) Func(path string, info os.FileInfo, timeout time.Duration) error { + return nil +} diff --git a/walker/walkers/ioctlFuzz/plugin.go b/walker/walkers/ioctlFuzz/plugin.go new file mode 100644 index 0000000..57803b5 --- /dev/null +++ b/walker/walkers/ioctlFuzz/plugin.go @@ -0,0 +1,28 @@ +package main + +import ( + "os" + "time" + + "git.thisco.de/vbatts/fuzz-walker/walker" +) + +// NewFuzzer creates the fuzzer for this plugin +func NewFuzzer() (walker.Fuzzer, error) { + return &myFuzzer{}, nil +} + +type myFuzzer struct{} + +func (mf myFuzzer) Name() string { + return "ioctlFuzz" +} + +func (mf myFuzzer) Func(path string, info os.FileInfo, timeout time.Duration) error { + // check whether it is a device file + //if !info.Mode().IsRegular() { + // return nil + //} + + return nil +} diff --git a/walker/walkers/readFuzz/readFuzz.go b/walker/walkers/readFuzz/plugin.go similarity index 55% rename from walker/walkers/readFuzz/readFuzz.go rename to walker/walkers/readFuzz/plugin.go index e5b0943..f3b2f8e 100644 --- a/walker/walkers/readFuzz/readFuzz.go +++ b/walker/walkers/readFuzz/plugin.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "io" "io/ioutil" "os" @@ -10,6 +9,7 @@ import ( "git.thisco.de/vbatts/fuzz-walker/walker" ) +// NewFuzzer creates the fuzzer for this plugin func NewFuzzer() (walker.Fuzzer, error) { return &myFuzzer{}, nil } @@ -21,22 +21,16 @@ func (mf myFuzzer) Name() string { } func (mf myFuzzer) Func(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") + if !info.Mode().IsRegular() { + return nil } - return nil + + fd, err := os.Open(path) + if err != nil { + return err + } + defer fd.Close() + + _, err = io.Copy(ioutil.Discard, fd) + return err } diff --git a/walker/walkers/writeBytesFuzz/plugin.go b/walker/walkers/writeBytesFuzz/plugin.go new file mode 100644 index 0000000..37aaf22 --- /dev/null +++ b/walker/walkers/writeBytesFuzz/plugin.go @@ -0,0 +1,32 @@ +package main + +import ( + "os" + "time" + + "git.thisco.de/vbatts/fuzz-walker/walker" +) + +// NewFuzzer creates the fuzzer for this plugin +func NewFuzzer() (walker.Fuzzer, error) { + return &myFuzzer{}, nil +} + +type myFuzzer struct{} + +func (mf myFuzzer) Name() string { + return "writeBytesFuzz" +} + +func (mf myFuzzer) Func(path string, info os.FileInfo, timeout time.Duration) error { + if !info.Mode().IsRegular() { + return nil + } + fd, err := os.Open(path) + if err != nil { + return err + } + defer fd.Close() + + return nil +} diff --git a/walker/walkers/writeNumFuzz/plugin.go b/walker/walkers/writeNumFuzz/plugin.go new file mode 100644 index 0000000..9539aa1 --- /dev/null +++ b/walker/walkers/writeNumFuzz/plugin.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "time" + + "git.thisco.de/vbatts/fuzz-walker/walker" +) + +// NewFuzzer creates the fuzzer for this plugin +func NewFuzzer() (walker.Fuzzer, error) { + return &myFuzzer{}, nil +} + +type myFuzzer struct{} + +func (mf myFuzzer) Name() string { + return "writeNumFuzz" +} + +func (mf myFuzzer) Func(path string, info os.FileInfo, timeout time.Duration) error { + if !info.Mode().IsRegular() { + return nil + } + fd, err := os.Open(path) + if err != nil { + return err + } + defer fd.Close() + return nil +}