Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/syscall_descriptions_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ Call attributes are:
string argument is a fsck-like command that will be called to verify the filesystem.
"remote_cover": wait longer to collect remote coverage for this call.
"kfuzz_test": the call is a kfuzztest target.
"snapshot": the call is enabled by default only in snapshot fuzzing mode,
but "enable_syscalls" and "disable_syscalls" config parameters override this.
It is generally used to mark calls that are not safe to execute in non-snapshot mode
"snapshot": the call is enabled by default only in snapshot fuzzing mode, but can also be enabled in
the non-snasphot mode when listed in "enable_syscalls" with its full name (as opposed to a wildcard match).
It can also always be disabled via "disable_syscalls".
The attribute is generally used to mark calls that are not safe to execute in non-snapshot mode
(can lead to false positives, or lost connections to test machines.
```

Expand Down
32 changes: 25 additions & 7 deletions pkg/mgrconfig/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,11 @@ func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string,
for _, c := range enabled {
n := 0
for _, call := range target.Syscalls {
if MatchSyscall(call.Name, c) {
if !MatchSyscall(call.Name, c) {
continue
}
// Skip snapshot attr check for the calls that match exactly.
if checkMode(call, descriptionsMode, call.Name != c) {
syscalls[call.ID] = true
n++
}
Expand All @@ -438,18 +442,14 @@ func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string,
}
} else {
for _, call := range target.Syscalls {
if call.Attrs.Snapshot && (descriptionsMode&SnapshotDescriptions) == 0 {
if !checkMode(call, descriptionsMode, true) {
continue
}
syscalls[call.ID] = true
}
}

for call := range syscalls {
if target.Syscalls[call].Attrs.Disabled ||
(descriptionsMode&AutoDescriptions) == 0 && target.Syscalls[call].Attrs.Automatic ||
(descriptionsMode&ManualDescriptions) == 0 &&
!target.Syscalls[call].Attrs.Automatic && !target.Syscalls[call].Attrs.AutomaticHelper {
if target.Syscalls[call].Attrs.Disabled {
delete(syscalls, call)
}
}
Expand All @@ -475,6 +475,24 @@ func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string,
return arr, nil
}

func checkMode(syscall *prog.Syscall, descriptionsMode DescriptionsMode,
checkSnapshot bool) bool {
if syscall.Attrs.Automatic &&
(descriptionsMode&AutoDescriptions) == 0 {
return false
}
if !syscall.Attrs.Automatic &&
!syscall.Attrs.AutomaticHelper &&
(descriptionsMode&ManualDescriptions) == 0 {
return false
}
if checkSnapshot && syscall.Attrs.Snapshot &&
(descriptionsMode&SnapshotDescriptions) == 0 {
return false
}
return true
}

func ParseNoMutateSyscalls(target *prog.Target, syscalls []string) (map[int]bool, error) {
var result = make(map[int]bool)

Expand Down
99 changes: 99 additions & 0 deletions pkg/mgrconfig/load_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2026 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 mgrconfig

import (
"testing"

"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseEnabledSyscalls(t *testing.T) {
target, err := prog.GetTarget(targets.TestOS, targets.TestArch64)
require.NoError(t, err)

tests := []struct {
name string
mode DescriptionsMode
enable []string
// TODO: add disable tests as well.
expectEnabled []string
expectDisabled []string
}{
{
name: "wildcard, no snapshot",
mode: ManualDescriptions,
enable: []string{"test"},
expectDisabled: []string{"test$snapshot_only"},
},
{
name: "wildcard, snapshot",
mode: ManualDescriptions | SnapshotDescriptions,
enable: []string{"test"},
expectEnabled: []string{"test$snapshot_only"},
},
{
name: "no wildcard, no snapshot",
mode: ManualDescriptions,
enable: []string{"test$snapshot_only"},
expectEnabled: []string{"test$snapshot_only"},
},
{
name: "no wildcard, snapshot",
mode: ManualDescriptions | SnapshotDescriptions,
enable: []string{"test$snapshot_only"},
expectEnabled: []string{"test$snapshot_only"},
},
{
name: "automatic allowed",
mode: ManualDescriptions | AutoDescriptions,
enable: []string{"test"},
expectEnabled: []string{
"test$automatic",
"test$automatic_helper",
"test$manual",
},
},
{
name: "manual only",
mode: ManualDescriptions,
enable: []string{"test"},
expectEnabled: []string{
"test$automatic_helper",
"test$manual",
},
expectDisabled: []string{
"test$automatic",
},
},
{
name: "auto only",
mode: AutoDescriptions,
enable: []string{"test"},
expectEnabled: []string{
"test$automatic",
"test$automatic_helper",
},
expectDisabled: []string{
"test$manual",
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ids, err := ParseEnabledSyscalls(target, test.enable,
nil, test.mode)
require.NoError(t, err)
for _, enabled := range test.expectEnabled {
assert.Contains(t, ids, target.SyscallMap[enabled].ID)
}
for _, disabled := range test.expectDisabled {
assert.NotContains(t, ids, target.SyscallMap[disabled].ID)
}
})
}
}
5 changes: 5 additions & 0 deletions sys/test/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1002,3 +1002,8 @@ test$consume_common(val common)
test$consume_subtype_of_common(val subtype_of_common)

test$fsck_attr() (fsck["fsck.test -n"])

test$snapshot_only(a0 intptr) (snapshot)
test$automatic(a0 intptr) (automatic)
test$automatic_helper(a0 intptr) (automatic_helper)
test$manual(a0 intptr)
Loading