diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-07-08 17:35:15 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-07-08 22:52:24 +0200 |
| commit | 1c667063a8d344ba09336ad43c69a2de5487f056 (patch) | |
| tree | 2db9e4c2917f18cc770ad2ea850eb19fc2cef0d3 /prog | |
| parent | 306ca0571c5d906ce76df97bd1ea54f4e0e50240 (diff) | |
prog: don't generate filenames that escape sandbox
All files that fuzzer works with must be in the working dir.
Using "/" is known to cause problems when fuzzer
removes files there or mounts something.
Diffstat (limited to 'prog')
| -rw-r--r-- | prog/hints.go | 7 | ||||
| -rw-r--r-- | prog/prog_test.go | 34 | ||||
| -rw-r--r-- | prog/rand.go | 6 | ||||
| -rw-r--r-- | prog/validation.go | 11 |
4 files changed, 56 insertions, 2 deletions
diff --git a/prog/hints.go b/prog/hints.go index 3d519d694..778655105 100644 --- a/prog/hints.go +++ b/prog/hints.go @@ -84,7 +84,7 @@ func generateHints(compMap CompMap, arg Arg, exec func()) { if typ == nil || typ.Dir() == DirOut { return } - switch typ.(type) { + switch t := typ.(type) { case *ProcType: // Random proc will not pass validation. // We can mutate it, but only if the resulting value is within the legal range. @@ -92,6 +92,11 @@ func generateHints(compMap CompMap, arg Arg, exec func()) { case *CsumType: // Csum will not pass validation and is always computed. return + case *BufferType: + if t.Kind == BufferFilename { + // This can generate escaping paths and is probably not too useful anyway. + return + } } switch a := arg.(type) { diff --git a/prog/prog_test.go b/prog/prog_test.go index e83310b32..5d4c2dac3 100644 --- a/prog/prog_test.go +++ b/prog/prog_test.go @@ -5,6 +5,7 @@ package prog import ( "bytes" + "encoding/hex" "fmt" "math/rand" "strings" @@ -210,3 +211,36 @@ func TestSpecialStructs(t *testing.T) { } }) } + +func TestEscapingPaths(t *testing.T) { + paths := map[string]bool{ + "/": true, + "/\x00": true, + "/file/..": true, + "/file/../..": true, + "./..": true, + "..": true, + "file/../../file": true, + "../file": true, + "./file/../../file/file": true, + "": false, + ".": false, + "file": false, + "./file": false, + "./file/..": false, + } + target, err := GetTarget("test", "64") + if err != nil { + t.Fatal(err) + } + for path, escaping := range paths { + text := fmt.Sprintf("mutate5(&(0x7f0000000000)=\"%s\", 0x0)", hex.EncodeToString([]byte(path))) + _, err := target.Deserialize([]byte(text)) + if !escaping && err != nil { + t.Errorf("path %q is detected as escaping (%v)", path, err) + } + if escaping && (err == nil || !strings.Contains(err.Error(), "sandbox escaping file")) { + t.Errorf("path %q is not detected as escaping (%v)", path, err) + } + } +} diff --git a/prog/rand.go b/prog/rand.go index a47e64b79..a1b83d11a 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -8,6 +8,7 @@ import ( "fmt" "math" "math/rand" + "path/filepath" "strings" "github.com/google/syzkaller/pkg/ifuzz" @@ -168,7 +169,7 @@ func (r *randGen) filename(s *state, typ *BufferType) string { return fn } -var specialFiles = []string{"", "/", "."} +var specialFiles = []string{"", "."} func (r *randGen) filenameImpl(s *state) string { if r.oneOf(100) { @@ -186,6 +187,9 @@ func (r *randGen) filenameImpl(s *state) string { if len(dir) > 0 && dir[len(dir)-1] == 0 { dir = dir[:len(dir)-1] } + if r.oneOf(10) && filepath.Clean(dir)[0] != '.' { + dir += "/.." + } } for i := 0; ; i++ { f := fmt.Sprintf("%v/file%v", dir, i) diff --git a/prog/validation.go b/prog/validation.go index 73b18c7e1..b38afc874 100644 --- a/prog/validation.go +++ b/prog/validation.go @@ -5,6 +5,7 @@ package prog import ( "fmt" + "path/filepath" ) var debug = false // enabled in tests @@ -163,6 +164,16 @@ func (arg *DataArg) validate(ctx *validCtx) error { return fmt.Errorf("string arg '%v' has size %v, which should be %v", typ.Name(), arg.Size(), typ.TypeSize) } + case BufferFilename: + file := string(arg.data) + for len(file) != 0 && file[len(file)-1] == 0 { + file = file[:len(file)-1] + } + file = filepath.Clean(file) + if len(file) > 0 && file[0] == '/' || + len(file) > 1 && file[0] == '.' && file[1] == '.' { + return fmt.Errorf("sandbox escaping file name %q", string(arg.data)) + } } return nil } |
