aboutsummaryrefslogtreecommitdiffstats
path: root/syz-manager
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-11-26 15:25:16 +0100
committerDmitry Vyukov <dvyukov@google.com>2024-11-27 10:28:33 +0000
commit4f0d9df0078216bcadfc7d4a744a160a1d3659be (patch)
tree551a402090bd19e9d98e678dc28a6d2d19d3944b /syz-manager
parent52b38cc1f0ef7be017dc51c45e16a1054254f95f (diff)
pkg/ifaceprobe: add package
Package ifaceprobe implements dynamic component of automatic kernel interface extraction. Currently it discovers all /{dev,sys,proc} files, and collects coverage for open/read/write/mmap/ioctl syscalls on these files. Later this allows to build file path <-> file_operations mapping. I've tried 2 other approaches: 1. Immediately map file to file_operations callbacks similar to tools/fops_probe, and export only that. This required lots of hardcoding of kernel function/file names, did not work well in all cases, and presumably would produce more maintanance in future. 2. Automatically infer what kernel functions are common, and which correspond to file_operations callbacks by first collecting coverage for all files/programs, and then counting how many times wach PC is encountered in combined coverage. Presumably common functions (SYS_read, vfs_read) will be present in most/all traces, while the actual file_operations callback will be present in only one/few traces. This also did not work well and produced lots of bugs where common functions were somehow called in few programs, or common file_operations callbacks were called in too many traces.
Diffstat (limited to 'syz-manager')
-rw-r--r--syz-manager/manager.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index aed721a79..3b6072629 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -30,6 +30,7 @@ import (
"github.com/google/syzkaller/pkg/fuzzer"
"github.com/google/syzkaller/pkg/fuzzer/queue"
"github.com/google/syzkaller/pkg/gce"
+ "github.com/google/syzkaller/pkg/ifaceprobe"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/manager"
"github.com/google/syzkaller/pkg/mgrconfig"
@@ -154,6 +155,20 @@ var (
Description: `run unit tests
Run sys/os/test/* tests in various modes and print results.`,
}
+ ModeIfaceProbe = &Mode{
+ Name: "iface-probe",
+ Description: `run dynamic part of kernel interface auto-extraction
+ When the probe is finished, manager writes the result to workdir/interfaces.json file and exits.`,
+ CheckConfig: func(cfg *mgrconfig.Config) error {
+ if cfg.Snapshot {
+ return fmt.Errorf("snapshot mode is not supported")
+ }
+ if cfg.Sandbox != "none" {
+ return fmt.Errorf("sandbox \"%v\" is not supported (only \"none\")", cfg.Sandbox)
+ }
+ return nil
+ },
+ }
modes = []*Mode{
ModeFuzzing,
@@ -161,6 +176,7 @@ var (
ModeCorpusTriage,
ModeCorpusRun,
ModeRunTests,
+ ModeIfaceProbe,
}
)
@@ -285,6 +301,9 @@ func RunManager(mode *Mode, cfg *mgrconfig.Config) {
Stats: mgr.servStats,
Debug: *flagDebug,
}
+ if mode == ModeIfaceProbe {
+ rpcCfg.CheckGlobs = ifaceprobe.Globs()
+ }
mgr.serv, err = rpcserver.New(rpcCfg)
if err != nil {
log.Fatalf("failed to create rpc server: %v", err)
@@ -1164,6 +1183,17 @@ func (mgr *Manager) MachineChecked(info *flatrpc.InfoRequest, features flatrpc.F
mgr.exit("tests")
}()
return ctx
+ } else if mgr.mode == ModeIfaceProbe {
+ exec := queue.Plain()
+ go func() {
+ res, err := ifaceprobe.Run(vm.ShutdownCtx(), mgr.cfg, exec, info)
+ if err != nil {
+ log.Fatalf("interface probing failed: %v", err)
+ }
+ mgr.saveJSON("interfaces.json", res)
+ mgr.exit("interface probe")
+ }()
+ return exec
}
panic(fmt.Sprintf("unexpected mode %q", mgr.mode.Name))
}