aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/csource/csource.go22
-rw-r--r--pkg/csource/csource_test.go35
-rw-r--r--pkg/csource/generated.go11
-rw-r--r--pkg/csource/options.go89
-rw-r--r--pkg/csource/options_test.go53
-rw-r--r--pkg/instance/execprog.go2
-rw-r--r--pkg/instance/instance.go19
-rw-r--r--pkg/instance/instance_test.go10
-rw-r--r--pkg/ipc/ipc.go17
-rw-r--r--pkg/ipc/ipc_test.go2
-rw-r--r--pkg/ipc/ipcconfig/ipcconfig.go14
-rw-r--r--pkg/mgrconfig/config.go5
12 files changed, 218 insertions, 61 deletions
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index 7d3b133bf..df35b54b8 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -28,6 +28,7 @@ import (
"fmt"
"regexp"
"sort"
+ "strconv"
"strings"
"time"
@@ -58,6 +59,18 @@ type context struct {
calls map[string]uint64 // CallName -> NR
}
+func generateSandboxFunctionSignature(sandboxName string, sandboxArg int) string {
+ if sandboxName == "" {
+ return "loop();"
+ }
+
+ arguments := "();"
+ if sandboxName == "android" {
+ arguments = "(" + strconv.Itoa(sandboxArg) + ");"
+ }
+ return "do_sandbox_" + sandboxName + arguments
+}
+
func (ctx *context) generateSource() ([]byte, error) {
ctx.filterCalls()
calls, vars, err := ctx.generateProgCalls(ctx.p, ctx.opts.Trace)
@@ -94,14 +107,7 @@ func (ctx *context) generateSource() ([]byte, error) {
fmt.Fprintf(varsBuf, "};\n")
}
- sandboxFunc := "loop();"
- if ctx.opts.Sandbox != "" {
- arguments := "();"
- if ctx.opts.Sandbox == "android" {
- arguments = "(0);"
- }
- sandboxFunc = "do_sandbox_" + ctx.opts.Sandbox + arguments
- }
+ sandboxFunc := generateSandboxFunctionSignature(ctx.opts.Sandbox, ctx.opts.SandboxArg)
replacements := map[string]string{
"PROCS": fmt.Sprint(ctx.opts.Procs),
"REPEAT_TIMES": fmt.Sprint(ctx.opts.RepeatTimes),
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index 91bd2cccf..491b84b03 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -18,6 +18,7 @@ import (
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys"
"github.com/google/syzkaller/sys/targets"
+ "github.com/stretchr/testify/assert"
)
func init() {
@@ -227,3 +228,37 @@ syscall(SYS_csource6, 0x20000140ul);
})
}
}
+
+func generateSandboxFunctionSignatureTestCase(t *testing.T, sandbox string, sandboxArg int, expected, message string) {
+ actual := generateSandboxFunctionSignature(sandbox, sandboxArg)
+ assert.Equal(t, actual, expected, message)
+}
+
+func TestGenerateSandboxFunctionSignature(t *testing.T) {
+ // This test-case intentionally omits the following edge cases:
+ // - sandbox name as whitespaces, tabs
+ // - control chars \r, \n and unprintables
+ // - unsuitable chars - punctuation, emojis, '#', '*', etc
+ // - character case mismatching function prototype defined in common_linux.h.
+ // For example 'do_sandbox_android' and 'AnDroid'.
+ // - non english letters, unicode compound characters
+ // and focuses on correct handling of sandboxes supporting and not 'sandbox_arg'
+ // config setting.
+ generateSandboxFunctionSignatureTestCase(t,
+ "", // sandbox name
+ 0, // sandbox arg
+ "loop();", // expected
+ "Empty sandbox name should produce 'loop();'")
+
+ generateSandboxFunctionSignatureTestCase(t,
+ "abrakadabra", // sandbox name
+ 0, // sandbox arg
+ "do_sandbox_abrakadabra();", // expected
+ "Empty sandbox name should produce 'loop();'")
+
+ generateSandboxFunctionSignatureTestCase(t,
+ "android", // sandbox name
+ -1234, // sandbox arg
+ "do_sandbox_android(-1234);", // expected
+ "Android sandbox function requires an argument")
+}
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 82799a0c3..874c8d72d 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -9798,7 +9798,7 @@ static void setfilecon(const char* path, const char* context)
#define SYZ_HAVE_SANDBOX_ANDROID 1
-static int do_sandbox_android(int sandbox_arg)
+static int do_sandbox_android(uint64 sandbox_arg)
{
setup_common();
#if SYZ_EXECUTOR || SYZ_VHCI_INJECTION
@@ -9823,6 +9823,7 @@ static int do_sandbox_android(int sandbox_arg)
size_t num_groups = UNTRUSTED_APP_NUM_GROUPS;
const gid_t* groups = UNTRUSTED_APP_GROUPS;
gid_t gid = UNTRUSTED_APP_GID;
+ debug("executor received sandbox_arg=%llu\n", sandbox_arg);
if (sandbox_arg == 1) {
uid = SYSTEM_UID;
num_groups = SYSTEM_NUM_GROUPS;
@@ -9832,13 +9833,13 @@ static int do_sandbox_android(int sandbox_arg)
debug("fuzzing under SYSTEM account\n");
}
if (chown(".", uid, uid) != 0)
- failmsg("do_sandbox_android: chmod failed", "sandbox_arg=%d", sandbox_arg);
+ failmsg("do_sandbox_android: chmod failed", "sandbox_arg=%llu", sandbox_arg);
if (setgroups(num_groups, groups) != 0)
- failmsg("do_sandbox_android: setgroups failed", "sandbox_arg=%d", sandbox_arg);
+ failmsg("do_sandbox_android: setgroups failed", "sandbox_arg=%llu", sandbox_arg);
if (setresgid(gid, gid, gid) != 0)
- failmsg("do_sandbox_android: setresgid failed", "sandbox_arg=%d", sandbox_arg);
+ failmsg("do_sandbox_android: setresgid failed", "sandbox_arg=%llu", sandbox_arg);
setup_binderfs();
@@ -9850,7 +9851,7 @@ static int do_sandbox_android(int sandbox_arg)
#endif
if (setresuid(uid, uid, uid) != 0)
- failmsg("do_sandbox_android: setresuid failed", "sandbox_arg=%d", sandbox_arg);
+ failmsg("do_sandbox_android: setresuid failed", "sandbox_arg=%llu", sandbox_arg);
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setfilecon(".", SELINUX_LABEL_APP_DATA_FILE);
diff --git a/pkg/csource/options.go b/pkg/csource/options.go
index 3fc549282..b150e79a0 100644
--- a/pkg/csource/options.go
+++ b/pkg/csource/options.go
@@ -24,6 +24,7 @@ type Options struct {
Procs int `json:"procs"`
Slowdown int `json:"slowdown"`
Sandbox string `json:"sandbox"`
+ SandboxArg int `json:"sandbox_arg"`
Leak bool `json:"leak,omitempty"` // do leak checking
@@ -197,35 +198,27 @@ func (opts Options) Serialize() []byte {
return data
}
-func DeserializeOptions(data []byte) (Options, error) {
- opts := Options{
- Slowdown: 1,
- // Before CloseFDs was added, close_fds() was always called, so default to true.
- CloseFDs: true,
- }
- if err := json.Unmarshal(data, &opts); err == nil {
- return opts, nil
- }
- // Support for legacy formats.
- data = bytes.Replace(data, []byte("Sandbox: "), []byte("Sandbox:empty "), -1)
+func deserializeLegacyOptions1(data string, opts *Options) error {
waitRepeat, debug := false, false
- n, err := fmt.Sscanf(string(data),
+ n, err := fmt.Sscanf(data,
"{Threaded:%t Collide:%t Repeat:%t Procs:%d Sandbox:%s"+
" Fault:%t FaultCall:%d FaultNth:%d EnableTun:%t UseTmpDir:%t"+
" HandleSegv:%t WaitRepeat:%t Debug:%t Repro:%t}",
&opts.Threaded, &opts.Collide, &opts.Repeat, &opts.Procs, &opts.Sandbox,
&opts.Fault, &opts.FaultCall, &opts.FaultNth, &opts.NetInjection, &opts.UseTmpDir,
&opts.HandleSegv, &waitRepeat, &debug, &opts.Repro)
+
if err == nil {
if want := 14; n != want {
- return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
+ return fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
}
- if opts.Sandbox == "empty" {
- opts.Sandbox = ""
- }
- return opts, nil
}
- n, err = fmt.Sscanf(string(data),
+ return err
+}
+
+func deserializeLegacyOptions2(data string, opts *Options) error {
+ waitRepeat, debug := false, false
+ n, err := fmt.Sscanf(data,
"{Threaded:%t Collide:%t Repeat:%t Procs:%d Sandbox:%s"+
" Fault:%t FaultCall:%d FaultNth:%d EnableTun:%t UseTmpDir:%t"+
" EnableCgroups:%t HandleSegv:%t WaitRepeat:%t Debug:%t Repro:%t}",
@@ -234,13 +227,67 @@ func DeserializeOptions(data []byte) (Options, error) {
&opts.Cgroups, &opts.HandleSegv, &waitRepeat, &debug, &opts.Repro)
if err == nil {
if want := 15; n != want {
- return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want)
+ return fmt.Errorf("failed to parse repro options 2: got %v fields, want %v", n, want)
}
- if opts.Sandbox == "empty" {
- opts.Sandbox = ""
+ }
+ return err
+}
+
+// Android format.
+func deserializeLegacyOptions3(data string, opts *Options) error {
+ waitRepeat, debug := false, false
+ n, err := fmt.Sscanf(data,
+ "{Threaded:%t Collide:%t Repeat:%t Procs:%d Sandbox:%s SandboxArg:%d"+
+ " Fault:%t FaultCall:%d FaultNth:%d EnableTun:%t UseTmpDir:%t"+
+ " EnableCgroups:%t HandleSegv:%t WaitRepeat:%t Debug:%t Repro:%t}",
+ &opts.Threaded, &opts.Collide, &opts.Repeat, &opts.Procs, &opts.Sandbox, &opts.SandboxArg,
+ &opts.Fault, &opts.FaultCall, &opts.FaultNth, &opts.NetInjection, &opts.UseTmpDir,
+ &opts.Cgroups, &opts.HandleSegv, &waitRepeat, &debug, &opts.Repro)
+ if err == nil {
+ if want := 16; n != want {
+ return fmt.Errorf("failed to parse repro options 3: got %v fields, want %v", n, want)
}
+ }
+ return err
+}
+
+var parsers = []func(string, *Options) error{
+ deserializeLegacyOptions1,
+ deserializeLegacyOptions2,
+ deserializeLegacyOptions3,
+}
+
+// Support for legacy formats.
+func deserializeLegacyFormats(data []byte, opts *Options) error {
+ data = bytes.Replace(data, []byte("Sandbox: "), []byte("Sandbox:empty "), -1)
+ strData := string(data)
+
+ // We can distinguish between legacy formats by the number
+ // of fields. The formats we support have 14, 15 and 16.
+ // Each field can be recognized by ':' char.
+ version := strings.Count(strData, ":")
+ if version < 14 || version > 16 {
+ return fmt.Errorf("unrecognized options format")
+ }
+ index := version - 14
+ err := parsers[index](strData, opts)
+
+ if opts.Sandbox == "empty" {
+ opts.Sandbox = ""
+ }
+ return err
+}
+
+func DeserializeOptions(data []byte) (Options, error) {
+ opts := Options{
+ Slowdown: 1,
+ // Before CloseFDs was added, close_fds() was always called, so default to true.
+ CloseFDs: true,
+ }
+ if err := json.Unmarshal(data, &opts); err == nil {
return opts, nil
}
+ err := deserializeLegacyFormats(data, &opts)
return opts, err
}
diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go
index 5e971a9d1..41d7cdbab 100644
--- a/pkg/csource/options_test.go
+++ b/pkg/csource/options_test.go
@@ -5,6 +5,7 @@ package csource
import (
"fmt"
+ "math"
"reflect"
"testing"
@@ -79,6 +80,32 @@ func TestParseOptionsCanned(t *testing.T) {
FaultNth: 2,
},
},
+ `{"threaded":true,"collide":true,"repeat":true,"procs":10,"sandbox":"android",
+ "sandbox_arg":9,"fault":true,"fault_call":1,"fault_nth":2,"tun":true,"tmpdir":true,"cgroups":true,
+ "netdev":true,"resetnet":true,
+ "segv":true,"waitrepeat":true,"debug":true,"repro":true}`: {
+ Threaded: true,
+ Repeat: true,
+ Procs: 10,
+ Slowdown: 1,
+ Sandbox: "android",
+ SandboxArg: 9,
+ NetInjection: true,
+ NetDevices: true,
+ NetReset: true,
+ Cgroups: true,
+ BinfmtMisc: false,
+ CloseFDs: true,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: true,
+ LegacyOptions: LegacyOptions{
+ Collide: true,
+ Fault: true,
+ FaultCall: 1,
+ FaultNth: 2,
+ },
+ },
"{Threaded:true Collide:true Repeat:true Procs:1 Sandbox:none Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": {
Threaded: true,
Repeat: true,
@@ -139,6 +166,27 @@ func TestParseOptionsCanned(t *testing.T) {
FaultNth: 0,
},
},
+ "{Threaded:false Collide:true Repeat:true Procs:1 Sandbox:namespace SandboxArg:-234 Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true EnableCgroups:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": {
+ Threaded: false,
+ Repeat: true,
+ Procs: 1,
+ Slowdown: 1,
+ Sandbox: "namespace",
+ SandboxArg: -234,
+ NetInjection: true,
+ Cgroups: true,
+ BinfmtMisc: false,
+ CloseFDs: true,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: false,
+ LegacyOptions: LegacyOptions{
+ Collide: true,
+ Fault: false,
+ FaultCall: -1,
+ FaultNth: 0,
+ },
+ },
}
for data, want := range canned {
got, err := DeserializeOptions([]byte(data))
@@ -206,6 +254,11 @@ func enumerateField(OS string, opt Options, field int) []Options {
fld.SetString(sandbox)
opts = append(opts, opt)
}
+ } else if fldName == "SandboxArg" {
+ for _, sandboxArg := range []int64{math.MinInt, math.MaxInt} {
+ fld.SetInt(sandboxArg)
+ opts = append(opts, opt)
+ }
} else if fldName == "Procs" {
for _, procs := range []int64{1, 4} {
fld.SetInt(procs)
diff --git a/pkg/instance/execprog.go b/pkg/instance/execprog.go
index 1fa01b620..3c54342ac 100644
--- a/pkg/instance/execprog.go
+++ b/pkg/instance/execprog.go
@@ -169,7 +169,7 @@ func (inst *ExecProgInstance) RunSyzProgFile(progFile string, duration time.Dura
faultCall = opts.FaultCall
}
command := ExecprogCmd(inst.execprogBin, inst.executorBin, target.OS, target.Arch, opts.Sandbox,
- opts.Repeat, opts.Threaded, opts.Collide, opts.Procs, faultCall, opts.FaultNth,
+ opts.SandboxArg, opts.Repeat, opts.Threaded, opts.Collide, opts.Procs, faultCall, opts.FaultNth,
!inst.OldFlagsCompatMode, inst.mgrCfg.Timeouts.Slowdown, vmProgFile)
return inst.runCommand(command, duration)
}
diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go
index 9f3e46c82..d25eae4c5 100644
--- a/pkg/instance/instance.go
+++ b/pkg/instance/instance.go
@@ -349,7 +349,7 @@ func (inst *inst) testInstance() error {
}
cmd := OldFuzzerCmd(fuzzerBin, executorBin, targets.TestOS, inst.cfg.TargetOS, inst.cfg.TargetArch, fwdAddr,
- inst.cfg.Sandbox, 0, inst.cfg.Cover, true, inst.optionalFlags, inst.cfg.Timeouts.Slowdown)
+ inst.cfg.Sandbox, inst.cfg.SandboxArg, 0, inst.cfg.Cover, true, inst.optionalFlags, inst.cfg.Timeouts.Slowdown)
outc, errc, err := inst.vm.Run(10*time.Minute*inst.cfg.Timeouts.Scale, nil, cmd)
if err != nil {
return fmt.Errorf("failed to run binary in VM: %v", err)
@@ -418,8 +418,9 @@ func (inst *inst) testRepro() ([]byte, error) {
}
type OptionalFuzzerArgs struct {
- Slowdown int
- RawCover bool
+ Slowdown int
+ RawCover bool
+ SandboxArg int
}
type FuzzerCmdArgs struct {
@@ -460,6 +461,7 @@ func FuzzerCmd(args *FuzzerCmdArgs) string {
flags := []tool.Flag{
{Name: "slowdown", Value: fmt.Sprint(args.Optional.Slowdown)},
{Name: "raw_cover", Value: fmt.Sprint(args.Optional.RawCover)},
+ {Name: "sandbox_arg", Value: fmt.Sprint(args.Optional.SandboxArg)},
}
optionalArg = " " + tool.OptionalFlags(flags)
}
@@ -469,19 +471,19 @@ func FuzzerCmd(args *FuzzerCmdArgs) string {
args.Procs, args.Cover, args.Debug, args.Test, runtestArg, verbosityArg, optionalArg)
}
-func OldFuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, procs int,
+func OldFuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, sandboxArg, procs int,
cover, test, optionalFlags bool, slowdown int) string {
var optional *OptionalFuzzerArgs
if optionalFlags {
- optional = &OptionalFuzzerArgs{Slowdown: slowdown}
+ optional = &OptionalFuzzerArgs{Slowdown: slowdown, SandboxArg: sandboxArg}
}
return FuzzerCmd(&FuzzerCmdArgs{Fuzzer: fuzzer, Executor: executor, Name: name,
- OS: OS, Arch: arch, FwdAddr: fwdAddr, Sandbox: sandbox, Procs: procs,
- Verbosity: 0, Cover: cover, Debug: false, Test: test, Runtest: false,
+ OS: OS, Arch: arch, FwdAddr: fwdAddr, Sandbox: sandbox,
+ Procs: procs, Verbosity: 0, Cover: cover, Debug: false, Test: test, Runtest: false,
Optional: optional})
}
-func ExecprogCmd(execprog, executor, OS, arch, sandbox string, repeat, threaded, collide bool,
+func ExecprogCmd(execprog, executor, OS, arch, sandbox string, sandboxArg int, repeat, threaded, collide bool,
procs, faultCall, faultNth int, optionalFlags bool, slowdown int, progFile string) string {
repeatCount := 1
if repeat {
@@ -501,6 +503,7 @@ func ExecprogCmd(execprog, executor, OS, arch, sandbox string, repeat, threaded,
if optionalFlags {
optionalArg += " " + tool.OptionalFlags([]tool.Flag{
{Name: "slowdown", Value: fmt.Sprint(slowdown)},
+ {Name: "sandboxArg", Value: fmt.Sprint(sandboxArg)},
})
}
diff --git a/pkg/instance/instance_test.go b/pkg/instance/instance_test.go
index 2f5c08625..843334ebd 100644
--- a/pkg/instance/instance_test.go
+++ b/pkg/instance/instance_test.go
@@ -16,7 +16,7 @@ import (
func TestFuzzerCmd(t *testing.T) {
// IMPORTANT: if this test fails, do not fix it by changing flags here!
- // Test how an old version of syz-fuzzer parses flags genereated by the current FuzzerCmd.
+ // Test how an old version of syz-fuzzer parses flags generated by the current FuzzerCmd.
// This actually happens in syz-ci when we test a patch for an old bug and use an old syz-fuzzer/execprog.
flags := flag.NewFlagSet("", flag.ContinueOnError)
flagName := flags.String("name", "", "unique name for manager")
@@ -29,11 +29,11 @@ func TestFuzzerCmd(t *testing.T) {
flagTest := flags.Bool("test", false, "enable image testing mode") // used by syz-ci
flagExecutor := flags.String("executor", "./syz-executor", "path to executor binary")
flagSignal := flags.Bool("cover", false, "collect feedback signals (coverage)")
- flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace)")
+ flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
flagDebug := flags.Bool("debug", false, "debug output from executor")
flagV := flags.Int("v", 0, "verbosity")
cmdLine := OldFuzzerCmd(os.Args[0], "/myexecutor", "myname", targets.Linux, targets.I386, "localhost:1234",
- "namespace", 3, true, true, false, 5)
+ "namespace", 23, 3, true, true, false, 5)
args := strings.Split(cmdLine, " ")[1:]
if err := flags.Parse(args); err != nil {
t.Fatal(err)
@@ -96,10 +96,10 @@ func TestExecprogCmd(t *testing.T) {
// sets this flag and never relies on the default value.
flagCollide := flags.Bool("collide", false, "collide syscalls to provoke data races")
flagSignal := flags.Bool("cover", false, "collect feedback signals (coverage)")
- flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace)")
+ flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
flagSlowdown := flags.Int("slowdown", 1, "")
cmdLine := ExecprogCmd(os.Args[0], "/myexecutor", targets.FreeBSD, targets.I386,
- "namespace", true, false, true, 7, 2, 3, true, 10, "myprog")
+ "namespace", 3, true, false, true, 7, 2, 3, true, 10, "myprog")
args := strings.Split(cmdLine, " ")[1:]
if err := tool.ParseFlags(flags, args); err != nil {
t.Fatal(err)
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go
index 839fdcd4c..5537ce0f8 100644
--- a/pkg/ipc/ipc.go
+++ b/pkg/ipc/ipc.go
@@ -70,7 +70,8 @@ type Config struct {
UseForkServer bool // use extended protocol with handshake
// Flags are configuation flags, defined above.
- Flags EnvFlags
+ Flags EnvFlags
+ SandboxArg int
Timeouts targets.Timeouts
}
@@ -504,9 +505,10 @@ const (
)
type handshakeReq struct {
- magic uint64
- flags uint64 // env flags
- pid uint64
+ magic uint64
+ flags uint64 // env flags
+ pid uint64
+ sandboxArg uint64
}
type handshakeReply struct {
@@ -686,9 +688,10 @@ func (c *command) close() {
// handshake sends handshakeReq and waits for handshakeReply.
func (c *command) handshake() error {
req := &handshakeReq{
- magic: inMagic,
- flags: uint64(c.config.Flags),
- pid: uint64(c.pid),
+ magic: inMagic,
+ flags: uint64(c.config.Flags),
+ pid: uint64(c.pid),
+ sandboxArg: uint64(c.config.SandboxArg),
}
reqData := (*[unsafe.Sizeof(*req)]byte)(unsafe.Pointer(req))[:]
if _, err := c.outwp.Write(reqData); err != nil {
diff --git a/pkg/ipc/ipc_test.go b/pkg/ipc/ipc_test.go
index fd89eae9b..3456852c5 100644
--- a/pkg/ipc/ipc_test.go
+++ b/pkg/ipc/ipc_test.go
@@ -103,6 +103,7 @@ func TestExecute(t *testing.T) {
UseShmem: useShmem,
UseForkServer: useForkServer,
Timeouts: timeouts,
+ SandboxArg: 0,
}
env, err := MakeEnv(cfg, 0)
if err != nil {
@@ -144,6 +145,7 @@ func TestParallel(t *testing.T) {
UseShmem: useShmem,
UseForkServer: useForkServer,
Timeouts: timeouts,
+ SandboxArg: 0,
}
const P = 10
errs := make(chan error, P)
diff --git a/pkg/ipc/ipcconfig/ipcconfig.go b/pkg/ipc/ipcconfig/ipcconfig.go
index 5be4d4b39..15e1dfde0 100644
--- a/pkg/ipc/ipcconfig/ipcconfig.go
+++ b/pkg/ipc/ipcconfig/ipcconfig.go
@@ -12,12 +12,13 @@ import (
)
var (
- flagExecutor = flag.String("executor", "./syz-executor", "path to executor binary")
- flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
- flagSignal = flag.Bool("cover", false, "collect feedback signals (coverage)")
- flagSandbox = flag.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
- flagDebug = flag.Bool("debug", false, "debug output from executor")
- flagSlowdown = flag.Int("slowdown", 1, "execution slowdown caused by emulation/instrumentation")
+ flagExecutor = flag.String("executor", "./syz-executor", "path to executor binary")
+ flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
+ flagSignal = flag.Bool("cover", false, "collect feedback signals (coverage)")
+ flagSandbox = flag.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
+ flagSandboxArg = flag.Int("sandbox_arg", 0, "argument for sandbox runner to adjust it via config")
+ flagDebug = flag.Bool("debug", false, "debug output from executor")
+ flagSlowdown = flag.Int("slowdown", 1, "execution slowdown caused by emulation/instrumentation")
)
func Default(target *prog.Target) (*ipc.Config, *ipc.ExecOpts, error) {
@@ -36,6 +37,7 @@ func Default(target *prog.Target) (*ipc.Config, *ipc.ExecOpts, error) {
if err != nil {
return nil, nil, err
}
+ c.SandboxArg = *flagSandboxArg
c.Flags |= sandboxFlags
c.UseShmem = sysTarget.ExecutorUsesShmem
c.UseForkServer = sysTarget.ExecutorUsesForkServer
diff --git a/pkg/mgrconfig/config.go b/pkg/mgrconfig/config.go
index 2c3d19475..9073c482c 100644
--- a/pkg/mgrconfig/config.go
+++ b/pkg/mgrconfig/config.go
@@ -125,6 +125,11 @@ type Config struct {
// "android": emulate permissions of an untrusted Android app (supported only on Linux)
Sandbox string `json:"sandbox"`
+ // This value is passed as an argument to executor and allows to adjust sandbox behavior
+ // via manager config. For example you can switch between system and user accounts based
+ // on this value.
+ SandboxArg int `json:"sandbox_arg"`
+
// Use KCOV coverage (default: true).
Cover bool `json:"cover"`
// Use coverage filter. Supported types of filter: