mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-14 08:19:04 +00:00
pkg/csource: add option to trace syscall results
This will be needed for testing of generated programs.
This commit is contained in:
parent
9d92841b4e
commit
b25fc7b831
@ -21,6 +21,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if SYZ_TRACE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if SYZ_EXECUTOR && !GOOS_linux
|
||||
#include <unistd.h>
|
||||
NORETURN void doexit(int status)
|
||||
@ -395,6 +399,9 @@ static void loop()
|
||||
#if SYZ_REPRO
|
||||
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
|
||||
}
|
||||
#endif
|
||||
#if SYZ_TRACE
|
||||
printf("### start\n");
|
||||
#endif
|
||||
int call, thread;
|
||||
#if SYZ_COLLIDE
|
||||
@ -470,7 +477,11 @@ static void loop()
|
||||
fail("pipe failed");
|
||||
#endif
|
||||
int iter;
|
||||
#if SYZ_REPEAT_TIMES
|
||||
for (iter = 0; iter < [[REPEAT_TIMES]]; iter++) {
|
||||
#else
|
||||
for (iter = 0;; iter++) {
|
||||
#endif
|
||||
#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
|
||||
// Create a new private work dir for this test (removed at the end of the loop).
|
||||
char cwdbuf[32];
|
||||
|
@ -95,6 +95,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) {
|
||||
if opts.Repeat {
|
||||
defines = append(defines, "SYZ_REPEAT")
|
||||
}
|
||||
if opts.RepeatTimes > 1 {
|
||||
defines = append(defines, "SYZ_REPEAT_TIMES")
|
||||
}
|
||||
if opts.Procs > 1 {
|
||||
defines = append(defines, "SYZ_PROCS")
|
||||
}
|
||||
@ -122,6 +125,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) {
|
||||
if opts.Repro {
|
||||
defines = append(defines, "SYZ_REPRO")
|
||||
}
|
||||
if opts.Trace {
|
||||
defines = append(defines, "SYZ_TRACE")
|
||||
}
|
||||
for _, c := range p.Calls {
|
||||
defines = append(defines, "__NR_"+c.Meta.CallName)
|
||||
}
|
||||
|
@ -27,13 +27,13 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
calls: make(map[string]uint64),
|
||||
}
|
||||
|
||||
calls, vars, err := ctx.generateProgCalls(ctx.p)
|
||||
calls, vars, err := ctx.generateProgCalls(ctx.p, opts.Trace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mmapProg := p.Target.GenerateUberMmapProg()
|
||||
mmapCalls, _, err := ctx.generateProgCalls(mmapProg)
|
||||
mmapCalls, _, err := ctx.generateProgCalls(mmapProg, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -60,6 +60,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
}
|
||||
replacements := map[string]string{
|
||||
"PROCS": fmt.Sprint(opts.Procs),
|
||||
"REPEAT_TIMES": fmt.Sprint(opts.RepeatTimes),
|
||||
"NUM_CALLS": fmt.Sprint(len(p.Calls)),
|
||||
"MMAP_DATA": strings.Join(mmapCalls, ""),
|
||||
"SYSCALL_DEFINES": ctx.generateSyscallDefines(),
|
||||
@ -94,17 +95,20 @@ func (ctx *context) generateSyscalls(calls []string, hasVars bool) string {
|
||||
opts := ctx.opts
|
||||
buf := new(bytes.Buffer)
|
||||
if !opts.Threaded && !opts.Collide {
|
||||
if hasVars {
|
||||
if hasVars || opts.Trace {
|
||||
fmt.Fprintf(buf, "\tlong res = 0;\n")
|
||||
}
|
||||
if opts.Repro {
|
||||
fmt.Fprintf(buf, "\tif (write(1, \"executing program\\n\", sizeof(\"executing program\\n\") - 1)) {}\n")
|
||||
}
|
||||
if opts.Trace {
|
||||
fmt.Fprintf(buf, "\tprintf(\"### start\\n\");\n")
|
||||
}
|
||||
for _, c := range calls {
|
||||
fmt.Fprintf(buf, "%s", c)
|
||||
}
|
||||
} else {
|
||||
if hasVars {
|
||||
if hasVars || opts.Trace {
|
||||
fmt.Fprintf(buf, "\tlong res;")
|
||||
}
|
||||
fmt.Fprintf(buf, "\tswitch (call) {\n")
|
||||
@ -145,7 +149,7 @@ func (ctx *context) generateSyscallDefines() string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (ctx *context) generateProgCalls(p *prog.Prog) ([]string, []uint64, error) {
|
||||
func (ctx *context) generateProgCalls(p *prog.Prog, trace bool) ([]string, []uint64, error) {
|
||||
exec := make([]byte, prog.ExecBufferSize)
|
||||
progSize, err := p.SerializeForExec(exec)
|
||||
if err != nil {
|
||||
@ -155,11 +159,11 @@ func (ctx *context) generateProgCalls(p *prog.Prog) ([]string, []uint64, error)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
calls, vars := ctx.generateCalls(decoded)
|
||||
calls, vars := ctx.generateCalls(decoded, trace)
|
||||
return calls, vars, nil
|
||||
}
|
||||
|
||||
func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) {
|
||||
func (ctx *context) generateCalls(p prog.ExecProg, trace bool) ([]string, []uint64) {
|
||||
var calls []string
|
||||
csumSeq := 0
|
||||
for ci, call := range p.Calls {
|
||||
@ -185,7 +189,7 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) {
|
||||
if emitCall {
|
||||
native := ctx.sysTarget.SyscallNumbers && !strings.HasPrefix(callName, "syz_")
|
||||
fmt.Fprintf(w, "\t")
|
||||
if resCopyout || argCopyout {
|
||||
if resCopyout || argCopyout || trace {
|
||||
fmt.Fprintf(w, "res = ")
|
||||
}
|
||||
if native {
|
||||
@ -219,6 +223,9 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) {
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, ");\n")
|
||||
if trace {
|
||||
fmt.Fprintf(w, "\tprintf(\"### call=%v errno=%%d\\n\", res == -1 ? errno : 0);\n", ci)
|
||||
}
|
||||
}
|
||||
|
||||
// Copyout.
|
||||
|
@ -15,6 +15,10 @@ var commonHeader = `
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if SYZ_TRACE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if SYZ_EXECUTOR && !GOOS_linux
|
||||
#include <unistd.h>
|
||||
NORETURN void doexit(int status)
|
||||
@ -3612,6 +3616,9 @@ static void loop()
|
||||
#if SYZ_REPRO
|
||||
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
|
||||
}
|
||||
#endif
|
||||
#if SYZ_TRACE
|
||||
printf("### start\n");
|
||||
#endif
|
||||
int call, thread;
|
||||
#if SYZ_COLLIDE
|
||||
@ -3684,7 +3691,11 @@ static void loop()
|
||||
fail("pipe failed");
|
||||
#endif
|
||||
int iter;
|
||||
#if SYZ_REPEAT_TIMES
|
||||
for (iter = 0; iter < [[REPEAT_TIMES]]; iter++) {
|
||||
#else
|
||||
for (iter = 0;; iter++) {
|
||||
#endif
|
||||
#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
|
||||
char cwdbuf[32];
|
||||
sprintf(cwdbuf, "./%d", iter);
|
||||
|
@ -15,11 +15,12 @@ import (
|
||||
// Options control various aspects of source generation.
|
||||
// Dashboard also provides serialized Options along with syzkaller reproducers.
|
||||
type Options struct {
|
||||
Threaded bool `json:"threaded,omitempty"`
|
||||
Collide bool `json:"collide,omitempty"`
|
||||
Repeat bool `json:"repeat,omitempty"`
|
||||
Procs int `json:"procs"`
|
||||
Sandbox string `json:"sandbox"`
|
||||
Threaded bool `json:"threaded,omitempty"`
|
||||
Collide bool `json:"collide,omitempty"`
|
||||
Repeat bool `json:"repeat,omitempty"`
|
||||
RepeatTimes int `json:"repeat_times,omitempty"` // if non-0, repeat that many times
|
||||
Procs int `json:"procs"`
|
||||
Sandbox string `json:"sandbox"`
|
||||
|
||||
Fault bool `json:"fault,omitempty"` // inject fault into FaultCall/FaultNth
|
||||
FaultCall int `json:"fault_call,omitempty"`
|
||||
@ -34,8 +35,9 @@ type Options struct {
|
||||
HandleSegv bool `json:"segv,omitempty"`
|
||||
|
||||
// Generate code for use with repro package to prints log messages,
|
||||
// which allows to distinguish between a hang and an absent crash.
|
||||
// which allows to detect hangs.
|
||||
Repro bool `json:"repro,omitempty"`
|
||||
Trace bool `json:"trace,omitempty"`
|
||||
}
|
||||
|
||||
// Check checks if the opts combination is valid or not.
|
||||
@ -101,6 +103,9 @@ func (opts Options) Check(OS string) error {
|
||||
if opts.ResetNet && !opts.Repeat {
|
||||
return errors.New("ResetNet without Repeat")
|
||||
}
|
||||
if !opts.Repeat && opts.RepeatTimes != 0 && opts.RepeatTimes != 1 {
|
||||
return errors.New("RepeatTimes without Repeat")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,11 @@ func enumerateField(OS string, opt Options, field int) []Options {
|
||||
fld.SetInt(procs)
|
||||
opts = append(opts, opt)
|
||||
}
|
||||
} else if fldName == "RepeatTimes" {
|
||||
for _, times := range []int64{0, 10} {
|
||||
fld.SetInt(times)
|
||||
opts = append(opts, opt)
|
||||
}
|
||||
} else if fldName == "FaultCall" {
|
||||
opts = append(opts, opt)
|
||||
} else if fldName == "FaultNth" {
|
||||
|
@ -21,7 +21,7 @@ var (
|
||||
flagBuild = flag.Bool("build", false, "also build the generated program")
|
||||
flagThreaded = flag.Bool("threaded", false, "create threaded program")
|
||||
flagCollide = flag.Bool("collide", false, "create collide program")
|
||||
flagRepeat = flag.Bool("repeat", false, "repeat program infinitely or not")
|
||||
flagRepeat = flag.Int("repeat", 1, "repeat program that many times (<=0 - infinitely)")
|
||||
flagProcs = flag.Int("procs", 1, "number of parallel processes")
|
||||
flagSandbox = flag.String("sandbox", "", "sandbox to use (none, setuid, namespace)")
|
||||
flagProg = flag.String("prog", "", "file with program to convert (required)")
|
||||
@ -33,6 +33,7 @@ var (
|
||||
flagNetdev = flag.Bool("netdev", false, "setup various net devices")
|
||||
flagResetNet = flag.Bool("resetnet", false, "reset net namespace after each test")
|
||||
flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV")
|
||||
flagTrace = flag.Bool("trace", false, "trace syscall results")
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -59,7 +60,8 @@ func main() {
|
||||
opts := csource.Options{
|
||||
Threaded: *flagThreaded,
|
||||
Collide: *flagCollide,
|
||||
Repeat: *flagRepeat,
|
||||
Repeat: *flagRepeat != 1,
|
||||
RepeatTimes: *flagRepeat,
|
||||
Procs: *flagProcs,
|
||||
Sandbox: *flagSandbox,
|
||||
Fault: *flagFaultCall >= 0,
|
||||
@ -72,6 +74,7 @@ func main() {
|
||||
ResetNet: *flagResetNet,
|
||||
HandleSegv: *flagHandleSegv,
|
||||
Repro: false,
|
||||
Trace: *flagTrace,
|
||||
}
|
||||
src, err := csource.Write(p, opts)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user