aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-01-05 14:16:07 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-01-09 20:20:48 +0100
commit94b38efc1d80ae2854d29af44c6d5918a2cb40cd (patch)
tree401943d29621eeb485b016e74e3062178091e12a
parentb5aa8b45061e01c79cf78fe3a634abf5dc6d3f46 (diff)
sys: allow to specify number of pages for vma type
Allows to write vma[4] or vma[5-10] to specify desired number of pages.
-rw-r--r--prog/prog_test.go37
-rw-r--r--prog/rand.go3
-rw-r--r--sys/README.md3
-rw-r--r--sys/decl.go2
-rw-r--r--sys/test.txt4
-rw-r--r--sysgen/sysgen.go11
6 files changed, 56 insertions, 4 deletions
diff --git a/prog/prog_test.go b/prog/prog_test.go
index 72e8868e7..218a76821 100644
--- a/prog/prog_test.go
+++ b/prog/prog_test.go
@@ -8,9 +8,12 @@ import (
"math/rand"
"testing"
"time"
+
+ "github.com/google/syzkaller/sys"
)
func initTest(t *testing.T) (rand.Source, int) {
+ t.Parallel()
iters := 10000
if testing.Short() {
iters = 100
@@ -49,3 +52,37 @@ func TestSerialize(t *testing.T) {
}
}
}
+
+func TestVmaType(t *testing.T) {
+ rs, iters := initTest(t)
+ meta := sys.CallMap["syz_test$vma0"]
+ r := newRand(rs)
+ for i := 0; i < iters; i++ {
+ s := newState(nil)
+ calls := r.generateParticularCall(s, meta)
+ c := calls[len(calls)-1]
+ if c.Meta.Name != "syz_test$vma0" {
+ t.Fatalf("generated wrong call %v", c.Meta.Name)
+ }
+ if len(c.Args) != 6 {
+ t.Fatalf("generated wrong number of args %v", len(c.Args))
+ }
+ check := func(v, l *Arg, min, max uintptr) {
+ if v.Kind != ArgPointer {
+ t.Fatalf("vma has bad type: %v, want %v", v.Kind, ArgPointer)
+ }
+ if l.Kind != ArgPageSize {
+ t.Fatalf("len has bad type: %v, want %v", l.Kind, ArgPageSize)
+ }
+ if v.AddrPagesNum < min || v.AddrPagesNum > max {
+ t.Fatalf("vma has bad number of pages: %v, want [%v-%v]", v.AddrPagesNum, min, max)
+ }
+ if l.AddrPage < min || l.AddrPage > max {
+ t.Fatalf("len has bad number of pages: %v, want [%v-%v]", l.AddrPage, min, max)
+ }
+ }
+ check(c.Args[0], c.Args[1], 1, 1e5)
+ check(c.Args[2], c.Args[3], 5, 5)
+ check(c.Args[4], c.Args[5], 7, 9)
+ }
+}
diff --git a/prog/rand.go b/prog/rand.go
index e56893b66..a8b33ea08 100644
--- a/prog/rand.go
+++ b/prog/rand.go
@@ -596,6 +596,9 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg *Arg, calls []*Call)
}
case *sys.VmaType:
npages := r.randPageCount()
+ if a.RangeBegin != 0 || a.RangeEnd != 0 {
+ npages = uintptr(int(a.RangeBegin) + r.Intn(int(a.RangeEnd-a.RangeBegin+1)))
+ }
arg := r.randPageAddr(s, a, npages, nil, true)
return arg, nil
case *sys.FlagsType:
diff --git a/sys/README.md b/sys/README.md
index 259a1c1f5..6e2ecb75c 100644
--- a/sys/README.md
+++ b/sys/README.md
@@ -54,7 +54,8 @@ rest of the type-options are type-specific:
argname of the object
"bytesize": similar to "len", but always denotes the size in bytes, type-options:
argname of the object
- "vma": a pointer to a set of pages (used as input for mmap/munmap/mremap/madvise)
+ "vma": a pointer to a set of pages (used as input for mmap/munmap/mremap/madvise), type-options:
+ optional number of pages (e.g. vma[7]), or a range of pages (e.g. vma[2-4])
"proc": per process int (see description below), type-options:
underlying type, value range start, how many values per process
```
diff --git a/sys/decl.go b/sys/decl.go
index 63fca61b7..322158b92 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -143,6 +143,8 @@ func (t *BufferType) Align() uintptr {
type VmaType struct {
TypeCommon
+ RangeBegin int64 // in pages
+ RangeEnd int64
}
func (t *VmaType) Size() uintptr {
diff --git a/sys/test.txt b/sys/test.txt
index 2c0c489a1..b48ca8f5f 100644
--- a/sys/test.txt
+++ b/sys/test.txt
@@ -199,6 +199,10 @@ syz_end_var_struct {
f2 flags[syz_end_flags, int64be]
} [packed]
+# Vma type.
+
+syz_test$vma0(v0 vma, l0 len[v0], v1 vma[5], l1 len[v1], v2 vma[7:9], l2 len[v2])
+
# Regression tests.
syz_test$regression0(a0 ptr[inout, syz_regression0_struct])
diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go
index 92258150d..d16841577 100644
--- a/sysgen/sysgen.go
+++ b/sysgen/sysgen.go
@@ -461,10 +461,15 @@ func generateArg(
fmt.Fprintf(out, "&BufferType{%v, Kind: BufferAlgName}", common())
case "vma":
canBeArg = true
- if want := 0; len(a) != want {
- failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
+ begin, end := "0", "0"
+ switch len(a) {
+ case 0:
+ case 1:
+ begin, end = parseRange(a[0], consts)
+ default:
+ failf("wrong number of arguments for %v arg %v, want 0 or 1, got %v", typ, name, len(a))
}
- fmt.Fprintf(out, "&VmaType{%v}", common())
+ fmt.Fprintf(out, "&VmaType{%v, RangeBegin: %v, RangeEnd: %v}", common(), begin, end)
case "len", "bytesize", "bytesize2", "bytesize4", "bytesize8":
canBeArg = true
size := uint64(ptrSize)