diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-04-25 13:51:51 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-05-02 16:24:59 +0000 |
| commit | 22ee48a2879809608f79cc23c914859fa2335d59 (patch) | |
| tree | aa2b496eb81823999a8b48be011575ee7c650fff /tools | |
| parent | 3c7bb2247f61c5218d4cd58a558dc2496fba53a4 (diff) | |
pkg/vminfo: check enabled syscalls on the host
Move the syscall checking logic to the host.
Diffing sets of disabled syscalls before/after this change
in different configurations (none/setuid sandboxes, amd64/386 arches,
large/small kernel configs) shows only some improvements/bug fixes.
1. socket$inet[6]_icmp are now enabled.
Previously they were disabled due to net.ipv4.ping_group_range sysctl
in the init namespace which prevented creation of ping sockets.
In the new net namespace the sysctl gets default value which allows creation.
2. get_thread_area and set_thread_area are now disabled on amd64.
They are available only in 32-bit mode, but they are present in /proc/kallsyms,
so we enabled them always.
3. socket$bt_{bnep, cmtp, hidp, rfcomm} are now disabled.
They cannot be created in non init net namespace.
bt_sock_create() checks init_net and returns EAFNOSUPPORT immediately.
This is a bug in descriptions we need to fix.
Now we see it due to more precise checks.
4. fstat64/fstatat64/lstat64/stat64 are now enabled in 32-bit mode.
They are not present in /proc/kallsyms as syscalls, so we have not enabled them.
But they are available in 32-bit mode.
5. 78 openat variants + 10 socket variants + mount are now disabled
with setuid sandbox. They are not permitted w/o root permissions,
but we ignored that. This additionally leads to 700 transitively
disabled syscalls.
In all cases checking in the actual executor context/sandbox
looks very positive, esp. for more restrictive sandboxes.
Android sandbox should benefit as well.
The additional benefit is full testability of the new code.
The change includes only a basic test that covers all checks,
and ensures the code does not crash/hang, all generated programs
parse successfully, etc. But it's possible to unit-test
every condition now.
The new version also parallelizes checking across VMs,
checking on a slow emulated qemu drops from 210 seconds
to 140 seconds.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/syz-runtest/empty.go | 6 | ||||
| -rw-r--r-- | tools/syz-runtest/runtest.go | 32 |
2 files changed, 28 insertions, 10 deletions
diff --git a/tools/syz-runtest/empty.go b/tools/syz-runtest/empty.go new file mode 100644 index 000000000..588c0c9e8 --- /dev/null +++ b/tools/syz-runtest/empty.go @@ -0,0 +1,6 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +func main() {} diff --git a/tools/syz-runtest/runtest.go b/tools/syz-runtest/runtest.go index 3e410630b..5849131eb 100644 --- a/tools/syz-runtest/runtest.go +++ b/tools/syz-runtest/runtest.go @@ -1,6 +1,10 @@ // Copyright 2018 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// This is broken for now. + +//go:build ignore + // Runtest runs syzkaller test programs in sys/*/test/*. Start as: // $ syz-runtest -config manager.config // Also see pkg/runtest docs. @@ -24,6 +28,7 @@ import ( "github.com/google/syzkaller/pkg/report" "github.com/google/syzkaller/pkg/rpctype" "github.com/google/syzkaller/pkg/runtest" + "github.com/google/syzkaller/pkg/vminfo" "github.com/google/syzkaller/prog" _ "github.com/google/syzkaller/sys" "github.com/google/syzkaller/vm" @@ -53,6 +58,7 @@ func main() { mgr := &Manager{ cfg: cfg, vmPool: vmPool, + checker: vminfo.New(cfg), reporter: reporter, debug: *flagDebug, requests: make(chan *runtest.RunRequest, 2*vmPool.Count()), @@ -62,7 +68,7 @@ func main() { reqMap: make(map[int]*runtest.RunRequest), lastReq: make(map[string]int), } - s, err := rpctype.NewRPCServer(cfg.RPC, "Manager", mgr, true) + s, err := rpctype.NewRPCServer(cfg.RPC, "Manager", mgr, false) if err != nil { log.Fatalf("failed to create rpc server: %v", err) } @@ -93,14 +99,16 @@ func main() { checkResult := <-mgr.checkResultC mgr.checkFeatures = checkResult.Features close(mgr.checkFeaturesReady) - enabledCalls := make(map[string]map[*prog.Syscall]bool) - for sandbox, ids := range checkResult.EnabledCalls { - calls := make(map[*prog.Syscall]bool) - for _, id := range ids { - calls[cfg.Target.Syscalls[id]] = true - } - enabledCalls[sandbox] = calls + calls, _, err := mgr.checker.Check(checkResult.Files, checkResult.CheckProgs) + if err != nil { + log.Fatalf("failed to detect enabled syscalls: %v", err) } + calls, _ = cfg.Target.TransitivelyEnabledCalls(calls) + enabledCalls := make(map[string]map[*prog.Syscall]bool) + // TODO: restore checking/testing of all other sandboxes (we used to test them). + // Note: syz_emit_ethernet/syz_extract_tcp_res were manually disabled for "" ("no") sandbox, + // b/c tun is not setup without sandbox. + enabledCalls[mgr.cfg.Sandbox] = calls for _, feat := range checkResult.Features.Supported() { fmt.Printf("%-24v: %v\n", feat.Name, feat.Reason) } @@ -133,6 +141,7 @@ func main() { type Manager struct { cfg *mgrconfig.Config vmPool *vm.Pool + checker *vminfo.Checker reporter *report.Reporter requests chan *runtest.RunRequest checkFeatures *host.Features @@ -221,16 +230,19 @@ func (mgr *Manager) finishRequest(name string, rep *report.Report) error { } func (mgr *Manager) Connect(a *rpctype.ConnectArgs, r *rpctype.ConnectRes) error { - r.AllSandboxes = true select { case <-mgr.checkFeaturesReady: r.Features = mgr.checkFeatures default: + infoFiles, checkFiles, checkProgs := mgr.checker.RequiredThings() + r.ReadFiles = append(infoFiles, checkFiles...) + r.ReadGlobs = mgr.cfg.Target.RequiredGlobs() + r.CheckProgs = checkProgs } return nil } -func (mgr *Manager) Check(a *rpctype.CheckArgs, r *int) error { +func (mgr *Manager) Check(a *rpctype.CheckArgs, r *rpctype.CheckRes) error { if a.Error != "" { log.Fatalf("machine check: %v", a.Error) } |
