From 1a3bad9041ac075f3e2ae7f20528203704e87b28 Mon Sep 17 00:00:00 2001 From: Veronica Radu Date: Mon, 7 Oct 2019 15:35:15 +0200 Subject: prog: mutate length of output buffers Update #480 --- executor/defs.h | 2 +- executor/syscalls.h | 2 ++ prog/mutation.go | 32 +++++++++++++++++++++++------ prog/mutation_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++------ sys/test/gen/64.go | 8 +++++++- sys/test/test.txt | 2 ++ 6 files changed, 88 insertions(+), 14 deletions(-) diff --git a/executor/defs.h b/executor/defs.h index 1c615d86c..a80b5cdf4 100644 --- a/executor/defs.h +++ b/executor/defs.h @@ -175,7 +175,7 @@ #if GOARCH_64 #define GOARCH "64" -#define SYZ_REVISION "71d8f9a8f2ed06129920bb9f60aef16fb9ca749b" +#define SYZ_REVISION "d3a892553e6e706b3c4f1a086bdd22a2578120c1" #define SYZ_EXECUTOR_USES_FORK_SERVER 0 #define SYZ_EXECUTOR_USES_SHMEM 0 #define SYZ_PAGE_SIZE 4096 diff --git a/executor/syscalls.h b/executor/syscalls.h index 946283fc0..57cbc46db 100644 --- a/executor/syscalls.h +++ b/executor/syscalls.h @@ -16503,11 +16503,13 @@ const call_t syscalls[] = { {"minimize$0", 0}, {"mutate$array", 0}, {"mutate$array2", 0}, + {"mutate$buffer", 0}, {"mutate$flags", 0}, {"mutate$flags2", 0}, {"mutate$flags3", 0}, {"mutate$integer", 0}, {"mutate$integer2", 0}, + {"mutate$rangedbuffer", 0}, {"mutate$union", 0}, {"mutate0", 0}, {"mutate1", 0}, diff --git a/prog/mutation.go b/prog/mutation.go index 8e59880a5..3f5129f4d 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -306,19 +306,22 @@ func (t *ProcType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*C } func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) { + minLen, maxLen := uint64(0), maxBlobLen + if t.Kind == BufferBlobRange { + minLen, maxLen = t.RangeBegin, t.RangeEnd + } a := arg.(*DataArg) + if t.Dir() == DirOut { + mutateBufferSize(r, a, minLen, maxLen) + return + } switch t.Kind { case BufferBlobRand, BufferBlobRange: data := append([]byte{}, a.Data()...) - minLen, maxLen := uint64(0), maxBlobLen - if t.Kind == BufferBlobRange { - minLen, maxLen = t.RangeBegin, t.RangeEnd - } a.data = mutateData(r, data, minLen, maxLen) case BufferString: data := append([]byte{}, a.Data()...) if r.bin() { - minLen, maxLen := uint64(0), maxBlobLen if t.TypeSize != 0 { minLen, maxLen = t.TypeSize, t.TypeSize } @@ -337,6 +340,18 @@ func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls [] return } +func mutateBufferSize(r *randGen, arg *DataArg, minLen, maxLen uint64) { + for oldSize := arg.Size(); oldSize == arg.Size(); { + arg.size += uint64(r.Intn(33)) - 16 + if arg.size < minLen { + arg.size = minLen + } + if arg.size > maxLen { + arg.size = maxLen + } + } +} + func (t *ArrayType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) { // TODO: swap elements of the array a := arg.(*GroupArg) @@ -464,7 +479,9 @@ func (ma *mutationArgs) collectArg(arg Arg, ctx *ArgCtx) { return } - if typ.Dir() == DirOut || !typ.Varlen() && typ.Size() == 0 { + _, isArrayTyp := typ.(*ArrayType) + _, isBufferTyp := typ.(*BufferType) + if !isBufferTyp && !isArrayTyp && typ.Dir() == DirOut || !typ.Varlen() && typ.Size() == 0 { return } @@ -577,6 +594,9 @@ func (t *LenType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) ( } func (t *BufferType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) { + if t.Dir() == DirOut && !t.Varlen() { + return dontMutate, false + } return 0.8 * maxPriority, false } diff --git a/prog/mutation_test.go b/prog/mutation_test.go index 6d19300b4..76812df2a 100644 --- a/prog/mutation_test.go +++ b/prog/mutation_test.go @@ -33,7 +33,7 @@ func TestMutationFlags(t *testing.T) { `r0 = mutate$flags3(&(0x7f0000000000)="2e2f66696c653000", 0xaaaaaaaaaaaaaaaa)`, }, } - runMutationTests(t, tests) + runMutationTests(t, tests, true) } func TestChooseCall(t *testing.T) { @@ -79,7 +79,7 @@ test$array0(&(0x7f0000001000)={0x1, [@f0=0x2, @f1=0x3], 0x4}) mutate$integer(0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1)`, }, } - runMutationTests(t, tests) + runMutationTests(t, tests, true) } func TestMutateArgument(t *testing.T) { @@ -358,10 +358,45 @@ mutate7(&(0x7f0000000000)='123', 0x2) mutate8(0x2) `, ` mutate8(0xffffffffffffffff) +`}, + // Increase buffer length + {` +mutate$buffer(&(0x7f0000000000)=""/100) +`, ` +mutate$buffer(&(0x7f0000000000)=""/200) +`}, + // Decrease buffer length + {` +mutate$buffer(&(0x7f0000000000)=""/800) +`, ` +mutate$buffer(&(0x7f0000000000)=""/4) +`}, + // Mutate a ranged buffer + {` +mutate$rangedbuffer(&(0x7f00000000c0)=""/10) +`, ` +mutate$rangedbuffer(&(0x7f00000000c0)=""/7) `}, } - runMutationTests(t, tests) + runMutationTests(t, tests, true) +} + +func TestNegativeMutations(t *testing.T) { + tests := [][2]string{ + // Mutate buffer size outside the range limits + {` +mutate$rangedbuffer(&(0x7f00000000c0)=""/7) +`, ` +mutate$rangedbuffer(&(0x7f00000000c0)=""/4) +`}, + {` +mutate$rangedbuffer(&(0x7f00000000c0)=""/7) +`, ` +mutate$rangedbuffer(&(0x7f00000000c0)=""/11) +`}, + } + runMutationTests(t, tests, false) } func BenchmarkMutate(b *testing.B) { @@ -405,7 +440,7 @@ func linuxAmd64ChoiceTable(target *Target) *ChoiceTable { return linuxCT } -func runMutationTests(t *testing.T, tests [][2]string) { +func runMutationTests(t *testing.T, tests [][2]string, valid bool) { target := initTargetTest(t, "test", "64") for ti, test := range tests { test := test @@ -416,16 +451,25 @@ func runMutationTests(t *testing.T, tests [][2]string) { t.Fatalf("failed to deserialize the program: %v", err) } want := goal.Serialize() - for i := 0; i < 1e5; i++ { + iters := int(1e5) + if !valid { + iters /= 10 + } + for i := 0; i < iters; i++ { p1 := p.Clone() p1.Mutate(rs, len(goal.Calls), ct, nil) data1 := p1.Serialize() if bytes.Equal(want, data1) { + if !valid { + t.Fatalf("failed on iter %v", i) + } t.Logf("success on iter %v", i) return } } - t.Fatalf("failed to achieve goal, original:%s\ngoal:%s", test[0], test[1]) + if valid { + t.Fatalf("failed to achieve goal, original:%s\ngoal:%s", test[0], test[1]) + } }) } } diff --git a/sys/test/gen/64.go b/sys/test/gen/64.go index f0c1afaea..886f8d3a1 100644 --- a/sys/test/gen/64.go +++ b/sys/test/gen/64.go @@ -649,6 +649,9 @@ var syscalls_64 = []*Syscall{ {Name: "mutate$array2", CallName: "mutate", MissingArgs: 8, Args: []Type{ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "vec", TypeSize: 8}, Type: &ArrayType{TypeCommon: TypeCommon{TypeName: "array", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "syz_struct1"}}}}, }}, + {Name: "mutate$buffer", CallName: "mutate", MissingArgs: 8, Args: []Type{ + &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "p", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "array", ArgDir: 1, IsVarlen: true}}}, + }}, {Name: "mutate$flags", CallName: "mutate", MissingArgs: 5, Args: []Type{ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "filename", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "filename", IsVarlen: true}, Kind: 3}}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int64", FldName: "i1", TypeSize: 8}}}, @@ -681,6 +684,9 @@ var syscalls_64 = []*Syscall{ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "i3", TypeSize: 2}}, Kind: 2, RangeEnd: 8}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "i4", TypeSize: 1}}, Kind: 2, RangeEnd: 8}, }}, + {Name: "mutate$rangedbuffer", CallName: "mutate", MissingArgs: 8, Args: []Type{ + &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "p", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "array", ArgDir: 1, IsVarlen: true}, Kind: 1, RangeBegin: 5, RangeEnd: 10}}, + }}, {Name: "mutate$union", CallName: "mutate", MissingArgs: 8, Args: []Type{ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "p", TypeSize: 8}, Type: &UnionType{Key: StructKey{Name: "syz_union0"}}}, }}, @@ -1083,4 +1089,4 @@ var consts_64 = []ConstValue{ {Name: "SYS_unsupported"}, } -const revision_64 = "71d8f9a8f2ed06129920bb9f60aef16fb9ca749b" +const revision_64 = "d3a892553e6e706b3c4f1a086bdd22a2578120c1" diff --git a/sys/test/test.txt b/sys/test/test.txt index bb2b4547a..e071ad305 100644 --- a/sys/test/test.txt +++ b/sys/test/test.txt @@ -743,6 +743,8 @@ mutate$flags3(filename ptr[in, filename], flags flags[open_flags2]) mutate$array(i1 int64, i2 int64[0x0:0x1fffffff], vec ptr[in, array[int32[0:1]]]) mutate$array2(vec ptr[in, array[syz_struct1]]) mutate$union(p ptr[in, syz_union0]) +mutate$buffer(p buffer[out]) +mutate$rangedbuffer(p ptr[out, array[int8, 5:10]]) open_flags = 0xabababababababab, 0xcdcdcdcdcdcdcdcd open_flags2 = 0xaaaaaaaaaaaaaaaa, 0xaaaaaaaabbbbbbbb, 0xbbbbbbbbbbbbbbbb, 0xbbbbbbbbcccccccc, 0xcccccccccccccccc, 0xccccccccdddddddd, 0xdddddddddddddddd, 0xddddddddeeeeeeee, 0xeeeeeeeeeeeeeeee, 0xeeeeeeeeffffffff, 0xffffffffffffffff -- cgit mrf-deployment