aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/subsystem
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2022-12-14 18:07:43 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2022-12-16 10:22:43 +0100
commit2083933ab27c27d8d184d31cc8957851a4ec658f (patch)
tree29a11b676e372ffad0de2e6421647ec019fa9be7 /pkg/subsystem
parentb2c3c0981c264c4fd87326295cb55f3fdb8b3c24 (diff)
pkg/subsystem: add basic subsystem extraction code
For now, recognize just the vfs subsystem and support per-repro-call subsystem inference.
Diffstat (limited to 'pkg/subsystem')
-rw-r--r--pkg/subsystem/extract.go52
-rw-r--r--pkg/subsystem/extract_test.go68
2 files changed, 120 insertions, 0 deletions
diff --git a/pkg/subsystem/extract.go b/pkg/subsystem/extract.go
new file mode 100644
index 000000000..caf80636e
--- /dev/null
+++ b/pkg/subsystem/extract.go
@@ -0,0 +1,52 @@
+// Copyright 2022 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 subsystem
+
+import (
+ "regexp"
+
+ "github.com/google/syzkaller/prog"
+ "github.com/google/syzkaller/sys/targets"
+)
+
+type SubsystemExtractor struct {
+ CallToSubsystems func(call string) []string
+}
+
+// Crash contains the subset of Crash fields relevant for subsystem extraction.
+type Crash struct {
+ OS string
+ GuiltyFiles []string
+ SyzRepro string
+}
+
+func (se *SubsystemExtractor) Extract(crash *Crash) []string {
+ retMap := map[string]bool{}
+ // Currently we only have the dumbest possible implementation of subsystem detection.
+ if crash.OS == targets.Linux {
+ for _, guiltyPath := range crash.GuiltyFiles {
+ if vfsPathRegexp.MatchString(guiltyPath) {
+ retMap["vfs"] = true
+ break
+ }
+ }
+ }
+ if se.CallToSubsystems != nil {
+ callSet, _, _ := prog.CallSet([]byte(crash.SyzRepro))
+ for call := range callSet {
+ for _, subsystem := range se.CallToSubsystems(call) {
+ retMap[subsystem] = true
+ }
+ }
+ }
+ retSlice := []string{}
+ for name := range retMap {
+ retSlice = append(retSlice, name)
+ }
+ return retSlice
+}
+
+var (
+ vfsPathRegexp = regexp.MustCompile(`^fs/[^/]+\.c`)
+)
diff --git a/pkg/subsystem/extract_test.go b/pkg/subsystem/extract_test.go
new file mode 100644
index 000000000..936f4fa8e
--- /dev/null
+++ b/pkg/subsystem/extract_test.go
@@ -0,0 +1,68 @@
+// Copyright 2022 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 subsystem
+
+import (
+ "sort"
+ "testing"
+
+ "github.com/google/syzkaller/sys/targets"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSimpleLinuxExtract(t *testing.T) {
+ se := &SubsystemExtractor{}
+
+ ret := se.Extract(&Crash{
+ OS: targets.Linux,
+ GuiltyFiles: []string{
+ "fs/ext4/abc.c",
+ },
+ })
+ assert.Empty(t, ret, "the test should have found 0 subsystems")
+
+ ret = se.Extract(&Crash{
+ OS: targets.Linux,
+ GuiltyFiles: []string{
+ "fs/ext4/abc.c",
+ "fs/def.c",
+ },
+ })
+ assert.Exactly(t, ret, []string{"vfs"}, "the test should have only found vfs")
+}
+
+func TestProgCallRules(t *testing.T) {
+ se := &SubsystemExtractor{
+ CallToSubsystems: func(call string) []string {
+ ret := map[string][]string{
+ // Intentionally add some that are not present in the test below.
+ "test": {"test"},
+ "syz_io_uring_setup": {"io_uring"},
+ "ioctl$TIOCSETD": {"tty_ioctls", "tty"},
+ // Some calls are also omitted to verify that the code works fine this way.
+ }
+ return ret[call]
+ },
+ }
+
+ ret := se.Extract(&Crash{
+ OS: targets.Linux,
+ GuiltyFiles: []string{
+ "mm/page-writeback.c",
+ },
+ // nolint: lll
+ SyzRepro: `# https://syzkaller.appspot.com/bug?id=708185e841adf6ca28fc50b126fdf9825fd8ae43
+# See https://goo.gl/kgGztJ for information about syzkaller reproducers.
+#{"repeat":true,"procs":1,"slowdown":1,"sandbox":"","close_fds":false}
+r0 = syz_io_uring_setup(0x3ee4, &(0x7f0000000240), &(0x7f0000002000/0x2000)=nil, &(0x7f0000ffd000/0x3000)=nil, &(0x7f0000000100)=<r1=>0x0, &(0x7f0000000140)=<r2=>0x0)
+socket$inet_udplite(0x2, 0x2, 0x88)
+r3 = openat$ptmx(0xffffffffffffff9c, &(0x7f0000000040), 0x8a04, 0x0)
+syz_io_uring_submit(r1, r2, &(0x7f0000000000)=@IORING_OP_READ=@pass_buffer={0x16, 0x0, 0x0, @fd_index=0x5, 0x0, 0x0}, 0x0)
+ioctl$TIOCSETD(r3, 0x5423, &(0x7f0000000580)=0x3)
+io_uring_enter(r0, 0x2ff, 0x0, 0x0, 0x0, 0x0)`,
+ })
+ sort.Strings(ret)
+ assert.Exactlyf(t, ret, []string{"io_uring", "tty", "tty_ioctls"},
+ "invalid resulting subsystems: %s", ret)
+}