From cdcc8b96dd9215a47ce5ce1074567a1be93eda5f Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Wed, 23 Mar 2022 13:50:36 +0000 Subject: all: collect raw coverage Raw coverage might be important when e.g. analysing the origins of out-of-place coverage in coverage reports or understanding why the fuzzer could not reach deeper code. If "raw_cover" is set to true, syzkaller will remember unsorted and unduplicated coverage (PCs) for each its corpus program. --- pkg/instance/instance.go | 14 ++++++++++---- pkg/ipc/ipc.go | 22 +++++++++++++++------- pkg/mgrconfig/config.go | 5 +++++ pkg/rpctype/rpctype.go | 10 ++++++---- 4 files changed, 36 insertions(+), 15 deletions(-) (limited to 'pkg') diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index 665281a47..c225f9696 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -452,6 +452,7 @@ type FuzzerCmdArgs struct { Test bool Runtest bool Slowdown int + RawCover bool } func FuzzerCmd(args *FuzzerCmdArgs) string { @@ -470,11 +471,16 @@ func FuzzerCmd(args *FuzzerCmdArgs) string { if args.Verbosity != 0 { verbosityArg = fmt.Sprintf(" -vv=%v", args.Verbosity) } - optionalArg := "" + flags := []tool.Flag{} if args.Slowdown > 0 { - optionalArg = " " + tool.OptionalFlags([]tool.Flag{ - {Name: "slowdown", Value: fmt.Sprint(args.Slowdown)}, - }) + flags = append(flags, tool.Flag{Name: "slowdown", Value: fmt.Sprint(args.Slowdown)}) + } + if args.RawCover { + flags = append(flags, tool.Flag{Name: "raw_cover", Value: "true"}) + } + optionalArg := "" + if len(flags) > 0 { + optionalArg += " " + tool.OptionalFlags(flags) } return fmt.Sprintf("%v -executor=%v -name=%v -arch=%v%v -manager=%v -sandbox=%v"+ " -procs=%v -cover=%v -debug=%v -test=%v%v%v%v", diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index 5bf4738ca..6b25d4af4 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -289,7 +289,7 @@ func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInf return } - info, err0 = env.parseOutput(p) + info, err0 = env.parseOutput(p, opts) if info != nil && env.config.Flags&FlagSignal == 0 { addFallbackSignal(p, info) } @@ -323,7 +323,7 @@ func addFallbackSignal(p *prog.Prog, info *ProgInfo) { } } -func (env *Env) parseOutput(p *prog.Prog) (*ProgInfo, error) { +func (env *Env) parseOutput(p *prog.Prog, opts *ExecOpts) (*ProgInfo, error) { out := env.out ncmd, ok := readUint32(&out) if !ok { @@ -372,19 +372,27 @@ func (env *Env) parseOutput(p *prog.Prog) (*ProgInfo, error) { if len(extraParts) == 0 { return info, nil } - info.Extra = convertExtra(extraParts) + info.Extra = convertExtra(extraParts, opts.Flags&FlagDedupCover > 0) return info, nil } -func convertExtra(extraParts []CallInfo) CallInfo { +func convertExtra(extraParts []CallInfo, dedupCover bool) CallInfo { var extra CallInfo - extraCover := make(cover.Cover) + if dedupCover { + extraCover := make(cover.Cover) + for _, part := range extraParts { + extraCover.Merge(part.Cover) + } + extra.Cover = extraCover.Serialize() + } else { + for _, part := range extraParts { + extra.Cover = append(extra.Cover, part.Cover...) + } + } extraSignal := make(signal.Signal) for _, part := range extraParts { - extraCover.Merge(part.Cover) extraSignal.Merge(signal.FromRaw(part.Signal, 0)) } - extra.Cover = extraCover.Serialize() extra.Signal = make([]uint32, len(extraSignal)) i := 0 for s := range extraSignal { diff --git a/pkg/mgrconfig/config.go b/pkg/mgrconfig/config.go index 5d4a9f8f5..c13e6f452 100644 --- a/pkg/mgrconfig/config.go +++ b/pkg/mgrconfig/config.go @@ -132,6 +132,11 @@ type Config struct { // eg. "0xffffffff81000000:0x10\n" CovFilter covFilterCfg `json:"cover_filter,omitempty"` + // For each prog in the corpus, remember the raw array of PCs obtained from the kernel. + // It can be useful for debugging syzkaller descriptions and syzkaller itself. + // Disabled by default as it slows down fuzzing. + RawCover bool `json:"raw_cover"` + // Reproduce, localize and minimize crashers (default: true). Reproduce bool `json:"reproduce"` diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go index cb2f43e76..f1d889a20 100644 --- a/pkg/rpctype/rpctype.go +++ b/pkg/rpctype/rpctype.go @@ -14,10 +14,12 @@ import ( ) type Input struct { - Call string - Prog []byte - Signal signal.Serial - Cover []uint32 + Call string + Prog []byte + Signal signal.Serial + Cover []uint32 + CallID int // seq number of call in the prog to which the item is related (-1 for extra) + RawCover []uint32 } type Candidate struct { -- cgit mrf-deployment