aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-04-18 12:37:07 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-04-30 09:36:03 +0000
commita80ca54def962002ad5ebed54459dc1667de4385 (patch)
tree2cf4d78ad9c4800f7bda9e7a42a013cfcd393d14
parent67a25df5ff7f0d2a8b09049c3b30ecc79afa3f1e (diff)
syz-manager: check revisions on the host
Move revisions check to the host. Instead of sending host revisions to the VM, let the VM send own revisions to the host. This is a bit complicated by the fact that we still have the image testing procedure that also uses this code. For now keep it intact.
-rw-r--r--pkg/rpctype/rpctype.go13
-rw-r--r--syz-fuzzer/fuzzer.go10
-rw-r--r--syz-fuzzer/testing.go53
-rw-r--r--syz-manager/rpc.go25
-rw-r--r--tools/syz-runtest/runtest.go2
5 files changed, 69 insertions, 34 deletions
diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go
index b0d932714..fa728a494 100644
--- a/pkg/rpctype/rpctype.go
+++ b/pkg/rpctype/rpctype.go
@@ -67,14 +67,17 @@ type ExecTask struct {
}
type ConnectArgs struct {
- Name string
+ Name string
+ GitRevision string
+ SyzRevision string
+ ExecutorArch string
+ ExecutorGitRevision string
+ ExecutorSyzRevision string
}
type ConnectRes struct {
- EnabledCalls []int
- GitRevision string
- TargetRevision string
- AllSandboxes bool
+ EnabledCalls []int
+ AllSandboxes bool
// This is forwarded from CheckArgs, if checking was already done.
Features *host.Features
// Fuzzer reads these files inside of the VM and returns contents in CheckArgs.Files.
diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go
index 13926ba0e..6068f6b62 100644
--- a/syz-fuzzer/fuzzer.go
+++ b/syz-fuzzer/fuzzer.go
@@ -132,7 +132,13 @@ func main() {
log.Logf(1, "connecting to manager...")
a := &rpctype.ConnectArgs{
- Name: *flagName,
+ Name: *flagName,
+ GitRevision: prog.GitRevision,
+ SyzRevision: target.Revision,
+ }
+ a.ExecutorArch, a.ExecutorSyzRevision, a.ExecutorGitRevision, err = executorVersion(executor)
+ if err != nil {
+ log.SyzFatalf("failed to run executor version: %v ", err)
}
r := &rpctype.ConnectRes{}
if err := manager.Call("Manager.Connect", a, r); err != nil {
@@ -144,8 +150,6 @@ func main() {
}
var checkReq *rpctype.CheckArgs
if r.Features == nil {
- checkArgs.gitRevision = r.GitRevision
- checkArgs.targetRevision = r.TargetRevision
checkArgs.enabledCalls = r.EnabledCalls
checkArgs.allSandboxes = r.AllSandboxes
checkArgs.featureFlags = featureFlags
diff --git a/syz-fuzzer/testing.go b/syz-fuzzer/testing.go
index 92c15b5e2..ba019fd56 100644
--- a/syz-fuzzer/testing.go
+++ b/syz-fuzzer/testing.go
@@ -38,6 +38,9 @@ func testImage(hostAddr string, args *checkArgs) {
log.SyzFatalf("BUG: failed to connect to host: %v", err)
}
conn.Close()
+ if err := checkRevisions(args); err != nil {
+ log.SyzFatalf("BUG: %v", err)
+ }
if _, err := checkMachine(args); err != nil {
log.SyzFatalf("BUG: %v", err)
}
@@ -121,9 +124,6 @@ func checkMachine(args *checkArgs) (*rpctype.CheckArgs, error) {
done := make(chan bool)
defer close(done)
go checkMachineHeartbeats(done)
- if err := checkRevisions(args); err != nil {
- return nil, err
- }
features, err := host.Check(args.target)
if err != nil {
return nil, err
@@ -198,35 +198,24 @@ func checkCalls(args *checkArgs, res *rpctype.CheckArgs) error {
func checkRevisions(args *checkArgs) error {
log.Logf(0, "checking revisions...")
- executorArgs := strings.Split(args.ipcConfig.Executor, " ")
- executorArgs = append(executorArgs, "version")
- cmd := osutil.Command(executorArgs[0], executorArgs[1:]...)
- cmd.Stderr = io.Discard
- if _, err := cmd.StdinPipe(); err != nil { // for the case executor is wrapped with ssh
- return err
- }
- out, err := osutil.Run(time.Minute, cmd)
+ arch, syzRev, gitRev, err := executorVersion(args.ipcConfig.Executor)
if err != nil {
- return fmt.Errorf("failed to run executor version: %w", err)
- }
- vers := strings.Split(strings.TrimSpace(string(out)), " ")
- if len(vers) != 4 {
- return fmt.Errorf("executor version returned bad result: %q", string(out))
+ return err
}
- if args.target.Arch != vers[1] {
- return fmt.Errorf("mismatching target/executor arches: %v vs %v", args.target.Arch, vers[1])
+ if args.target.Arch != arch {
+ return fmt.Errorf("mismatching target/executor arches: %v vs %v", args.target.Arch, arch)
}
- if prog.GitRevision != vers[3] {
+ if prog.GitRevision != gitRev {
return fmt.Errorf("mismatching fuzzer/executor git revisions: %v vs %v",
- prog.GitRevision, vers[3])
+ prog.GitRevision, gitRev)
}
if args.gitRevision != prog.GitRevision {
return fmt.Errorf("mismatching manager/fuzzer git revisions: %v vs %v",
args.gitRevision, prog.GitRevision)
}
- if args.target.Revision != vers[2] {
+ if args.target.Revision != syzRev {
return fmt.Errorf("mismatching fuzzer/executor system call descriptions: %v vs %v",
- args.target.Revision, vers[2])
+ args.target.Revision, syzRev)
}
if args.target.Revision != args.targetRevision {
return fmt.Errorf("mismatching fuzzer/manager system call descriptions: %v vs %v",
@@ -235,6 +224,26 @@ func checkRevisions(args *checkArgs) error {
return nil
}
+func executorVersion(bin string) (string, string, string, error) {
+ args := strings.Split(bin, " ")
+ args = append(args, "version")
+ cmd := osutil.Command(args[0], args[1:]...)
+ cmd.Stderr = io.Discard
+ if _, err := cmd.StdinPipe(); err != nil { // for the case executor is wrapped with ssh
+ return "", "", "", err
+ }
+ out, err := osutil.Run(time.Minute, cmd)
+ if err != nil {
+ return "", "", "", fmt.Errorf("failed to run executor version: %w", err)
+ }
+ // Executor returns OS, arch, descriptions hash, git revision.
+ vers := strings.Split(strings.TrimSpace(string(out)), " ")
+ if len(vers) != 4 {
+ return "", "", "", fmt.Errorf("executor version returned bad result: %q", string(out))
+ }
+ return vers[1], vers[2], vers[3], nil
+}
+
func checkSimpleProgram(args *checkArgs, features *host.Features) error {
log.Logf(0, "testing simple program...")
if err := host.Setup(args.target, features, args.featureFlags, args.ipcConfig.Executor); err != nil {
diff --git a/syz-manager/rpc.go b/syz-manager/rpc.go
index 8656dcc2b..96283ee20 100644
--- a/syz-manager/rpc.go
+++ b/syz-manager/rpc.go
@@ -130,13 +130,12 @@ func startRPCServer(mgr *Manager) (*RPCServer, error) {
func (serv *RPCServer) Connect(a *rpctype.ConnectArgs, r *rpctype.ConnectRes) error {
log.Logf(1, "fuzzer %v connected", a.Name)
+ checkRevisions(a, serv.cfg.Target)
serv.statVMRestarts.Add(1)
serv.mu.Lock()
defer serv.mu.Unlock()
r.EnabledCalls = serv.cfg.Syscalls
- r.GitRevision = prog.GitRevision
- r.TargetRevision = serv.cfg.Target.Revision
r.Features = serv.checkFeatures
r.ReadFiles = serv.checker.RequiredFiles()
if !serv.checkDone {
@@ -145,6 +144,28 @@ func (serv *RPCServer) Connect(a *rpctype.ConnectArgs, r *rpctype.ConnectRes) er
return nil
}
+func checkRevisions(a *rpctype.ConnectArgs, target *prog.Target) {
+ if target.Arch != a.ExecutorArch {
+ log.Fatalf("mismatching target/executor arches: %v vs %v", target.Arch, a.ExecutorArch)
+ }
+ if prog.GitRevision != a.GitRevision {
+ log.Fatalf("mismatching manager/fuzzer git revisions: %v vs %v",
+ prog.GitRevision, a.GitRevision)
+ }
+ if prog.GitRevision != a.ExecutorGitRevision {
+ log.Fatalf("mismatching manager/executor git revisions: %v vs %v",
+ prog.GitRevision, a.ExecutorGitRevision)
+ }
+ if target.Revision != a.SyzRevision {
+ log.Fatalf("mismatching manager/fuzzer system call descriptions: %v vs %v",
+ target.Revision, a.SyzRevision)
+ }
+ if target.Revision != a.ExecutorSyzRevision {
+ log.Fatalf("mismatching manager/executor system call descriptions: %v vs %v",
+ target.Revision, a.ExecutorSyzRevision)
+ }
+}
+
func (serv *RPCServer) Check(a *rpctype.CheckArgs, r *rpctype.CheckRes) error {
serv.mu.Lock()
defer serv.mu.Unlock()
diff --git a/tools/syz-runtest/runtest.go b/tools/syz-runtest/runtest.go
index b61dfdad8..3e410630b 100644
--- a/tools/syz-runtest/runtest.go
+++ b/tools/syz-runtest/runtest.go
@@ -221,8 +221,6 @@ func (mgr *Manager) finishRequest(name string, rep *report.Report) error {
}
func (mgr *Manager) Connect(a *rpctype.ConnectArgs, r *rpctype.ConnectRes) error {
- r.GitRevision = prog.GitRevision
- r.TargetRevision = mgr.cfg.Target.Revision
r.AllSandboxes = true
select {
case <-mgr.checkFeaturesReady: