aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prog/hints.go7
-rw-r--r--prog/prog_test.go34
-rw-r--r--prog/rand.go6
-rw-r--r--prog/validation.go11
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
}