mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-24 03:49:45 +00:00
commit
1e06f3e00f
@ -13,8 +13,6 @@
|
||||
#include <unistd.h>
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_COLLIDE)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
|
||||
|
@ -14,8 +14,6 @@ var commonHeader = `
|
||||
#include <unistd.h>
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_COLLIDE)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
|
||||
|
@ -219,7 +219,7 @@ func generateTestFunc(w io.Writer, opts Options, calls []string, name string) {
|
||||
}
|
||||
fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", len(calls))
|
||||
fmt.Fprintf(w, "\t\tpthread_create(&th[i], 0, thr, (void*)i);\n")
|
||||
fmt.Fprintf(w, "\t\tusleep(10000);\n")
|
||||
fmt.Fprintf(w, "\t\tusleep(rand()%%10000);\n")
|
||||
fmt.Fprintf(w, "\t}\n")
|
||||
if opts.Collide {
|
||||
fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", len(calls))
|
||||
@ -228,7 +228,7 @@ func generateTestFunc(w io.Writer, opts Options, calls []string, name string) {
|
||||
fmt.Fprintf(w, "\t\t\tusleep(rand()%%10000);\n")
|
||||
fmt.Fprintf(w, "\t}\n")
|
||||
}
|
||||
fmt.Fprintf(w, "\tusleep(100000);\n")
|
||||
fmt.Fprintf(w, "\tusleep(rand()%%100000);\n")
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,9 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, vmPool *vm.Pool, vmIndexes []in
|
||||
}()
|
||||
|
||||
res, err := ctx.repro(entries, crashStart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res != nil {
|
||||
ctx.reproLog(3, "repro crashed as:\n%s", string(ctx.report))
|
||||
res.Stats = ctx.stats
|
||||
@ -171,37 +174,41 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
|
||||
|
||||
res, err := ctx.extractProg(entries)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
res.Opts.Repro = false
|
||||
}()
|
||||
res, err = ctx.minimizeProg(res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res, err = ctx.simplifyProg(res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try extracting C repro without simplifying options first.
|
||||
res, err = ctx.extractC(res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Simplify options and try extracting C repro.
|
||||
if !res.CRepro {
|
||||
res.Opts.Repro = false
|
||||
return res, nil
|
||||
res, err = ctx.simplifyProg(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
res, err = ctx.simplifyC(res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
// Simplify C related options.
|
||||
if res.CRepro {
|
||||
res, err = ctx.simplifyC(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
res.Opts.Repro = false
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -237,7 +244,7 @@ func (ctx *context) extractProg(entries []*prog.LogEntry) (*Result, error) {
|
||||
// Programs are executed in reverse order, usually the last program is the guilty one.
|
||||
res, err := ctx.extractProgSingle(reverseEntries(lastEntries), timeout)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
if res != nil {
|
||||
ctx.reproLog(3, "found reproducer with %d syscalls", len(res.Prog.Calls))
|
||||
@ -247,7 +254,7 @@ func (ctx *context) extractProg(entries []*prog.LogEntry) (*Result, error) {
|
||||
// Execute all programs and bisect the log to find multiple guilty programs.
|
||||
res, err = ctx.extractProgBisect(reverseEntries(entries), timeout)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
if res != nil {
|
||||
ctx.reproLog(3, "found reproducer with %d syscalls", len(res.Prog.Calls))
|
||||
@ -259,9 +266,7 @@ func (ctx *context) extractProg(entries []*prog.LogEntry) (*Result, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ctx *context) extractProgSingle(entries []*prog.LogEntry, duration time.Duration) (*Result, error) {
|
||||
ctx.reproLog(3, "single: executing %d programs separately with timeout %s", len(entries), duration)
|
||||
|
||||
func (ctx *context) createDefaultOps() csource.Options {
|
||||
opts := csource.Options{
|
||||
Threaded: true,
|
||||
Collide: true,
|
||||
@ -272,9 +277,15 @@ func (ctx *context) extractProgSingle(entries []*prog.LogEntry, duration time.Du
|
||||
UseTmpDir: true,
|
||||
HandleSegv: true,
|
||||
WaitRepeat: true,
|
||||
Debug: true,
|
||||
Repro: true,
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (ctx *context) extractProgSingle(entries []*prog.LogEntry, duration time.Duration) (*Result, error) {
|
||||
ctx.reproLog(3, "single: executing %d programs separately with timeout %s", len(entries), duration)
|
||||
|
||||
opts := ctx.createDefaultOps()
|
||||
|
||||
for _, ent := range entries {
|
||||
opts.Fault = ent.Fault
|
||||
@ -305,19 +316,7 @@ func (ctx *context) extractProgSingle(entries []*prog.LogEntry, duration time.Du
|
||||
func (ctx *context) extractProgBisect(entries []*prog.LogEntry, baseDuration time.Duration) (*Result, error) {
|
||||
ctx.reproLog(3, "bisect: bisecting %d programs with base timeout %s", len(entries), baseDuration)
|
||||
|
||||
opts := csource.Options{
|
||||
Threaded: true,
|
||||
Collide: true,
|
||||
Repeat: true,
|
||||
Procs: ctx.cfg.Procs,
|
||||
Sandbox: ctx.cfg.Sandbox,
|
||||
EnableTun: true,
|
||||
UseTmpDir: true,
|
||||
HandleSegv: true,
|
||||
WaitRepeat: true,
|
||||
Debug: true,
|
||||
Repro: true,
|
||||
}
|
||||
opts := ctx.createDefaultOps()
|
||||
|
||||
duration := func(entries int) time.Duration {
|
||||
return baseDuration + time.Duration((entries/4))*time.Second
|
||||
@ -424,60 +423,31 @@ func (ctx *context) simplifyProg(res *Result) (*Result, error) {
|
||||
ctx.stats.SimplifyProgTime = time.Since(start)
|
||||
}()
|
||||
|
||||
opts := res.Opts
|
||||
opts.Collide = false
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
opts.Threaded = false
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.Sandbox == "namespace" {
|
||||
opts = res.Opts
|
||||
opts.Sandbox = "none"
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.Procs > 1 {
|
||||
opts = res.Opts
|
||||
opts.Procs = 1
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.Repeat {
|
||||
opts = res.Opts
|
||||
opts.Repeat = false
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
for _, simplify := range progSimplifies {
|
||||
opts := res.Opts
|
||||
if simplify(&opts) {
|
||||
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
// Simplification successfull, try extracting C repro.
|
||||
res, err := ctx.extractC(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.CRepro {
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Try triggering crash with a C reproducer.
|
||||
func (ctx *context) extractC(res *Result) (*Result, error) {
|
||||
ctx.reproLog(2, "extracting C reproducer")
|
||||
start := time.Now()
|
||||
@ -485,15 +455,15 @@ func (ctx *context) extractC(res *Result) (*Result, error) {
|
||||
ctx.stats.ExtractCTime = time.Since(start)
|
||||
}()
|
||||
|
||||
// Try triggering crash with a C reproducer.
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, res.Opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return nil, err
|
||||
}
|
||||
res.CRepro = crashed
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Try to simplify the C reproducer.
|
||||
func (ctx *context) simplifyC(res *Result) (*Result, error) {
|
||||
ctx.reproLog(2, "simplifying C reproducer")
|
||||
start := time.Now()
|
||||
@ -501,74 +471,18 @@ func (ctx *context) simplifyC(res *Result) (*Result, error) {
|
||||
ctx.stats.SimplifyCTime = time.Since(start)
|
||||
}()
|
||||
|
||||
// Try to simplify the C reproducer.
|
||||
if res.Opts.EnableTun {
|
||||
for _, simplify := range cSimplifies {
|
||||
opts := res.Opts
|
||||
opts.EnableTun = false
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
if simplify(&opts) {
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
}
|
||||
if res.Opts.Sandbox != "" {
|
||||
opts := res.Opts
|
||||
opts.Sandbox = ""
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.UseTmpDir {
|
||||
opts := res.Opts
|
||||
opts.UseTmpDir = false
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.HandleSegv {
|
||||
opts := res.Opts
|
||||
opts.HandleSegv = false
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.WaitRepeat {
|
||||
opts := res.Opts
|
||||
opts.WaitRepeat = false
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
if res.Opts.Debug {
|
||||
opts := res.Opts
|
||||
opts.Debug = false
|
||||
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -818,3 +732,81 @@ func encodeEntries(entries []*prog.LogEntry) []byte {
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
type Simplify func(opts *csource.Options) bool
|
||||
|
||||
var progSimplifies = []Simplify{
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.Collide {
|
||||
return false
|
||||
}
|
||||
opts.Collide = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if opts.Collide || !opts.Threaded {
|
||||
return false
|
||||
}
|
||||
opts.Collide = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.Repeat {
|
||||
return false
|
||||
}
|
||||
opts.Repeat = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if opts.Procs == 1 {
|
||||
return false
|
||||
}
|
||||
opts.Procs = 1
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if opts.Sandbox == "none" {
|
||||
return false
|
||||
}
|
||||
opts.Sandbox = "none"
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
var cSimplifies = append(progSimplifies, []Simplify{
|
||||
func(opts *csource.Options) bool {
|
||||
if opts.Sandbox == "" {
|
||||
return false
|
||||
}
|
||||
opts.Sandbox = ""
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.EnableTun {
|
||||
return false
|
||||
}
|
||||
opts.EnableTun = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.UseTmpDir {
|
||||
return false
|
||||
}
|
||||
opts.UseTmpDir = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.HandleSegv {
|
||||
return false
|
||||
}
|
||||
opts.HandleSegv = false
|
||||
return true
|
||||
},
|
||||
func(opts *csource.Options) bool {
|
||||
if !opts.WaitRepeat {
|
||||
return false
|
||||
}
|
||||
opts.WaitRepeat = false
|
||||
return true
|
||||
},
|
||||
}...)
|
||||
|
Loading…
Reference in New Issue
Block a user