aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-12-02 10:57:36 +0100
committerDmitry Vyukov <dvyukov@google.com>2024-12-11 15:22:17 +0000
commit59267911909f7e749367f87d62448d7daa87b1b5 (patch)
tree02bf0a5d9e6012a8b6cb237fed7789f61aca6cc2 /tools
parentc756ba4e975097bf74b952367e2cd1a8db466c69 (diff)
tools/syz-declextract: generate file_operations descriptions
Emit descriptions for special files in /dev, /sys, /proc, and ./. pkg/declextract combines file_operations info produced by the clang tool with the dynamic probing info produced by pkg/ifaceprobe in order to produce complete descriptions for special files.
Diffstat (limited to 'tools')
-rw-r--r--tools/syz-declextract/README.md6
-rw-r--r--tools/syz-declextract/declextract.go45
-rw-r--r--tools/syz-declextract/declextract_test.go12
-rw-r--r--tools/syz-declextract/testdata/file_operations.c.probe15
-rw-r--r--tools/syz-declextract/testdata/file_operations.c.txt16
-rw-r--r--tools/syz-declextract/testdata/manual.txt6
6 files changed, 96 insertions, 4 deletions
diff --git a/tools/syz-declextract/README.md b/tools/syz-declextract/README.md
index cab397192..934059810 100644
--- a/tools/syz-declextract/README.md
+++ b/tools/syz-declextract/README.md
@@ -45,3 +45,9 @@ make -j`nproc` syz-declextract
go run tools/syz-declextract -binary=$LLVM_BUILD/bin/syz-declextract -config=manager.cfg
syz-env make extract SOURCEDIR=$KERNEL
```
+
+The tool caches results of static kernel analysis in manager.workdir/declextract.cache,
+and results of the dynamic kernel probing in manager.workdir/interfaces.json.
+These can be examined for debugging purposes, and reused separately by passing
+-cache-extract and -cache-probe flags. Caching greatly saves time if only part
+of the system has changed. If only the Go tool has changed, then both caches can be reused.
diff --git a/tools/syz-declextract/declextract.go b/tools/syz-declextract/declextract.go
index 7bf6d6081..5fe1edf52 100644
--- a/tools/syz-declextract/declextract.go
+++ b/tools/syz-declextract/declextract.go
@@ -6,6 +6,7 @@ package main
import (
"bufio"
"bytes"
+ "encoding/json"
"flag"
"fmt"
"io/fs"
@@ -13,11 +14,13 @@ import (
"path/filepath"
"slices"
"strings"
+ "time"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/clangtool"
"github.com/google/syzkaller/pkg/compiler"
"github.com/google/syzkaller/pkg/declextract"
+ "github.com/google/syzkaller/pkg/ifaceprobe"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/subsystem"
@@ -35,13 +38,19 @@ func main() {
flagBinary = flag.String("binary", "syz-declextract", "path to syz-declextract binary")
flagCacheExtract = flag.Bool("cache-extract", false, "use cached extract results if present"+
" (cached in manager.workdir/declextract.cache)")
+ flagCacheProbe = flag.Bool("cache-probe", false, "use cached probe results if present"+
+ " (cached in manager.workdir/interfaces.json)")
)
defer tool.Init()()
cfg, err := mgrconfig.LoadFile(*flagConfig)
if err != nil {
tool.Fail(err)
}
- if err := run(filepath.FromSlash("sys/linux/auto.txt"), &clangtool.Config{
+ probeInfo, err := probe(cfg, *flagConfig, *flagCacheProbe)
+ if err != nil {
+ tool.Failf("kernel probing failed: %v", err)
+ }
+ if err := run(filepath.FromSlash("sys/linux/auto.txt"), probeInfo, &clangtool.Config{
ToolBin: *flagBinary,
KernelSrc: cfg.KernelSrc,
KernelObj: cfg.KernelObj,
@@ -52,7 +61,7 @@ func main() {
}
}
-func run(autoFile string, cfg *clangtool.Config) error {
+func run(autoFile string, probeInfo *ifaceprobe.Info, cfg *clangtool.Config) error {
syscallRename, err := buildSyscallRenameMap(cfg.KernelSrc)
if err != nil {
return fmt.Errorf("failed to build syscall rename map: %w", err)
@@ -61,7 +70,7 @@ func run(autoFile string, cfg *clangtool.Config) error {
if err != nil {
return err
}
- descriptions, interfaces, err := declextract.Run(out, syscallRename)
+ descriptions, interfaces, err := declextract.Run(out, probeInfo, syscallRename)
if err != nil {
return err
}
@@ -107,6 +116,36 @@ func run(autoFile string, cfg *clangtool.Config) error {
return osutil.WriteFile(autoFile, formatted)
}
+func probe(cfg *mgrconfig.Config, cfgFile string, cache bool) (*ifaceprobe.Info, error) {
+ cacheFile := filepath.Join(cfg.Workdir, "interfaces.json")
+ if cache {
+ info, err := readProbeResult(cacheFile)
+ if err == nil {
+ return info, nil
+ }
+ }
+ _, err := osutil.RunCmd(30*time.Minute, "", filepath.Join(cfg.Syzkaller, "bin", "syz-manager"),
+ "-config", cfgFile, "-mode", "iface-probe")
+ if err != nil {
+ return nil, err
+ }
+ return readProbeResult(cacheFile)
+}
+
+func readProbeResult(file string) (*ifaceprobe.Info, error) {
+ data, err := os.ReadFile(file)
+ if err != nil {
+ return nil, err
+ }
+ dec := json.NewDecoder(bytes.NewReader(data))
+ dec.DisallowUnknownFields()
+ info := new(ifaceprobe.Info)
+ if err := dec.Decode(info); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal interfaces.json: %w", err)
+ }
+ return info, nil
+}
+
func errorHandler() (func(pos ast.Pos, msg string), *bytes.Buffer) {
errors := new(bytes.Buffer)
eh := func(pos ast.Pos, msg string) {
diff --git a/tools/syz-declextract/declextract_test.go b/tools/syz-declextract/declextract_test.go
index b93a6dcbf..e6f8da464 100644
--- a/tools/syz-declextract/declextract_test.go
+++ b/tools/syz-declextract/declextract_test.go
@@ -15,6 +15,7 @@ import (
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/clangtool"
"github.com/google/syzkaller/pkg/compiler"
+ "github.com/google/syzkaller/pkg/ifaceprobe"
"github.com/google/syzkaller/pkg/osutil"
)
@@ -53,8 +54,17 @@ func TestDeclextract(t *testing.T) {
t.Fatal(err)
}
cfg.ToolBin = "this-is-not-supposed-to-run"
+ probeInfo := new(ifaceprobe.Info)
+ probeFile := filepath.Join(cfg.KernelSrc, filepath.Base(file)+".probe")
+ if osutil.IsExist(probeFile) {
+ var err error
+ probeInfo, err = readProbeResult(probeFile)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
autoFile := filepath.Join(cfg.KernelObj, filepath.Base(file)+".txt")
- if err := run(autoFile, cfg); err != nil {
+ if err := run(autoFile, probeInfo, cfg); err != nil {
if *flagUpdate {
osutil.CopyFile(autoFile, file+".txt")
osutil.CopyFile(autoFile+".info", file+".info")
diff --git a/tools/syz-declextract/testdata/file_operations.c.probe b/tools/syz-declextract/testdata/file_operations.c.probe
new file mode 100644
index 000000000..6ff4a213a
--- /dev/null
+++ b/tools/syz-declextract/testdata/file_operations.c.probe
@@ -0,0 +1,15 @@
+{
+ "Files": [
+ {
+ "Name": "/dev/foo",
+ "Cover": [1, 2, 3, 4, 5]
+ }
+ ],
+ "PCs": [
+ {"PC": 1, "Func": "foo_open"},
+ {"PC": 2, "Func": "foo_read"},
+ {"PC": 3, "Func": "foo_write"},
+ {"PC": 4, "Func": "foo_mmap"},
+ {"PC": 5, "Func": "foo_ioctl"}
+ ]
+}
diff --git a/tools/syz-declextract/testdata/file_operations.c.txt b/tools/syz-declextract/testdata/file_operations.c.txt
index f2fb3ed1c..e812350a3 100644
--- a/tools/syz-declextract/testdata/file_operations.c.txt
+++ b/tools/syz-declextract/testdata/file_operations.c.txt
@@ -8,3 +8,19 @@ include <vdso/bits.h>
include <linux/types.h>
include <net/netlink.h>
include <include/uapi/file_operations.h>
+
+resource fd_foo_file_operations[fd]
+openat$auto_foo_file_operations(fd const[AT_FDCWD], file ptr[in, string["/dev/foo"]], flags flags[open_flags], mode const[0]) fd_foo_file_operations
+read$auto_foo_file_operations(fd fd_foo_file_operations, buf ptr[out, array[int8]], len bytesize[buf])
+write$auto_foo_file_operations(fd fd_foo_file_operations, buf ptr[in, array[int8]], len bytesize[buf])
+mmap$auto_foo_file_operations(addr vma, len len[addr], prot flags[mmap_prot], flags flags[mmap_flags], fd fd_foo_file_operations, offset fileoff)
+ioctl$auto_FOO_IOCTL1(fd fd_foo_file_operations, cmd const[FOO_IOCTL1], arg const[0])
+ioctl$auto_FOO_IOCTL2(fd fd_foo_file_operations, cmd const[FOO_IOCTL2], arg ptr[in, int32])
+ioctl$auto_FOO_IOCTL3(fd fd_foo_file_operations, cmd const[FOO_IOCTL3], arg ptr[in, foo_ioctl_arg$auto])
+ioctl$auto_FOO_IOCTL4(fd fd_foo_file_operations, cmd const[FOO_IOCTL4], arg ptr[inout, foo_ioctl_arg$auto])
+ioctl$auto_FOO_IOCTL5(fd fd_foo_file_operations, cmd const[FOO_IOCTL5], arg ptr[inout, foo_ioctl_arg$auto])
+
+foo_ioctl_arg$auto {
+ a int32
+ b int32
+}
diff --git a/tools/syz-declextract/testdata/manual.txt b/tools/syz-declextract/testdata/manual.txt
index 31ab63c9c..51ff3230c 100644
--- a/tools/syz-declextract/testdata/manual.txt
+++ b/tools/syz-declextract/testdata/manual.txt
@@ -21,6 +21,9 @@ use {
f3 nlattr[1, int32]
f4 nlnest[1, int32]
f5 nl_generic_attr
+ f6 flags[open_flags, int32]
+ f7 flags[mmap_prot, int32]
+ f8 flags[mmap_flags, int32]
}
@@ -47,4 +50,7 @@ type nlnest[ATTR, TYPE] nlattr[ATTR, TYPE]
type nl_generic_attr int32
+open_flags = 1, 2
+mmap_prot = 1, 2
+mmap_flags = 1, 2
send_flags = 1, 2