Skip to content

Commit

Permalink
pkg/prog: explain why syscalls are transitively disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
dvyukov committed Apr 6, 2018
1 parent 4daf857 commit 2a9c3ed
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 46 deletions.
12 changes: 3 additions & 9 deletions pkg/host/host_test.go
Expand Up @@ -31,15 +31,9 @@ func TestLog(t *testing.T) {
for c, reason := range disabled {
t.Logf("%v: %v", c.Name, reason)
}
trans := target.TransitivelyEnabledCalls(supp)
_, disabled = target.TransitivelyEnabledCalls(supp)
t.Logf("\n\ntransitively unsupported:")
for _, c := range target.Syscalls {
s, ok := trans[c]
if ok && !s {
t.Fatalf("map contains false value")
}
if !s && supp[c] {
t.Logf("%v", c.Name)
}
for c, reason := range disabled {
t.Logf("%v: %v", c.Name, reason)
}
}
36 changes: 26 additions & 10 deletions prog/decl_test.go
Expand Up @@ -5,6 +5,7 @@ package prog

import (
"runtime"
"strings"
"testing"
)

Expand Down Expand Up @@ -32,20 +33,26 @@ func TestTransitivelyEnabledCalls(t *testing.T) {
for _, c := range target.Syscalls {
calls[c] = true
}
if trans := target.TransitivelyEnabledCalls(calls); len(calls) != len(trans) {
for c := range calls {
if !trans[c] {
t.Logf("disabled %v", c.Name)
}
if trans, disabled := target.TransitivelyEnabledCalls(calls); len(disabled) != 0 {
for c, reason := range disabled {
t.Logf("disabled %v: %v", c.Name, reason)
}
t.Fatalf("can't create some resource")
} else if len(trans) != len(calls) {
t.Fatalf("transitive syscalls are not full")
} else {
for c, ok := range trans {
if !ok {
t.Fatalf("syscalls %v is false in transitive map", c.Name)
}
}
}
delete(calls, target.SyscallMap["epoll_create"])
if trans := target.TransitivelyEnabledCalls(calls); len(calls) != len(trans) {
if trans, disabled := target.TransitivelyEnabledCalls(calls); len(disabled) != 0 || len(trans) != len(calls) {
t.Fatalf("still must be able to create epoll fd with epoll_create1")
}
delete(calls, target.SyscallMap["epoll_create1"])
trans := target.TransitivelyEnabledCalls(calls)
trans, disabled := target.TransitivelyEnabledCalls(calls)
if len(calls)-6 != len(trans) ||
trans[target.SyscallMap["epoll_ctl$EPOLL_CTL_ADD"]] ||
trans[target.SyscallMap["epoll_ctl$EPOLL_CTL_MOD"]] ||
Expand All @@ -55,6 +62,14 @@ func TestTransitivelyEnabledCalls(t *testing.T) {
trans[target.SyscallMap["kcmp$KCMP_EPOLL_TFD"]] {
t.Fatalf("epoll fd is not disabled")
}
if len(disabled) != 6 {
t.Fatalf("disabled %v syscalls, want 6", len(disabled))
}
for c, reason := range disabled {
if !strings.Contains(reason, "no syscalls can create resource fd_epoll, enable some syscalls that can create it [epoll_create epoll_create1]") {
t.Fatalf("%v: wrong disable reason: %v", c.Name, reason)
}
}
}

func TestClockGettime(t *testing.T) {
Expand All @@ -69,8 +84,9 @@ func TestClockGettime(t *testing.T) {
}
// Removal of clock_gettime should disable all calls that accept timespec/timeval.
delete(calls, target.SyscallMap["clock_gettime"])
trans := target.TransitivelyEnabledCalls(calls)
if len(trans)+10 > len(calls) {
t.Fatalf("clock_gettime did not disable enough calls: before %v, after %v", len(calls), len(trans))
trans, disabled := target.TransitivelyEnabledCalls(calls)
if len(trans)+10 > len(calls) || len(trans)+len(disabled) != len(calls) || len(trans) == 0 {
t.Fatalf("clock_gettime did not disable enough calls: before %v, after %v, disabled %v",
len(calls), len(trans), len(disabled))
}
}
23 changes: 16 additions & 7 deletions prog/resources.go
Expand Up @@ -85,8 +85,9 @@ func (c *Syscall) inputResources() []*ResourceType {
return resources
}

func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*Syscall]bool {
func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) (map[*Syscall]bool, map[*Syscall]string) {
supported := make(map[*Syscall]bool)
disabled := make(map[*Syscall]string)
for c := range enabled {
supported[c] = true
}
Expand All @@ -106,7 +107,8 @@ func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*S
n := len(supported)
haveGettime := supported[target.SyscallMap["clock_gettime"]]
for c := range supported {
canCreate := true
cantCreate := ""
var resourceCtors []*Syscall
for _, res := range inputResources[c] {
noctors := true
for _, ctor := range ctors[res.Desc.Name] {
Expand All @@ -116,26 +118,33 @@ func (target *Target) TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*S
}
}
if noctors {
canCreate = false
cantCreate = res.Desc.Name
resourceCtors = ctors[res.Desc.Name]
break
}
}
// We need to support structs as resources,
// but for now we just special-case timespec/timeval.
if canCreate && !haveGettime {
if cantCreate == "" && !haveGettime {
ForeachType(c, func(typ Type) {
if a, ok := typ.(*StructType); ok && a.Dir() != DirOut && (a.Name() == "timespec" || a.Name() == "timeval") {
canCreate = false
cantCreate = a.Name()
resourceCtors = []*Syscall{target.SyscallMap["clock_gettime"]}
}
})
}
if !canCreate {
if cantCreate != "" {
delete(supported, c)
var ctorNames []string
for _, ctor := range resourceCtors {
ctorNames = append(ctorNames, ctor.Name)
}
disabled[c] = fmt.Sprintf("no syscalls can create resource %v, enable some syscalls that can create it %v", cantCreate, ctorNames)
}
}
if n == len(supported) {
break
}
}
return supported
return supported, disabled
}
9 changes: 3 additions & 6 deletions syz-fuzzer/fuzzer.go
Expand Up @@ -404,12 +404,9 @@ func buildCallList(target *prog.Target, enabledCalls, sandbox string) map[*prog.
}
}

trans := target.TransitivelyEnabledCalls(calls)
for c := range calls {
if !trans[c] {
Logf(1, "transitively unsupported: %v", c.Name)
delete(calls, c)
}
calls, disabled := target.TransitivelyEnabledCalls(calls)
for c, reason := range disabled {
Logf(1, "transitively unsupported: %v: %v", c.Name, reason)
}
return calls
}
Expand Down
2 changes: 1 addition & 1 deletion syz-fuzzer/testing.go
Expand Up @@ -36,7 +36,7 @@ func testImage(hostAddr string, target *prog.Target, sandbox string) {
if err != nil {
Fatalf("failed to detect supported syscalls: %v", err)
}
calls = target.TransitivelyEnabledCalls(calls)
calls, _ = target.TransitivelyEnabledCalls(calls)
Logf(0, "enabled syscalls: %v", len(calls))
if calls[target.SyscallMap["syz_emit_ethernet"]] ||
calls[target.SyscallMap["syz_extract_tcp_res"]] {
Expand Down
10 changes: 4 additions & 6 deletions tools/syz-mutate/mutate.go
Expand Up @@ -45,12 +45,10 @@ func main() {
for id := range syscallsIDs {
syscalls[target.Syscalls[id]] = true
}
trans := target.TransitivelyEnabledCalls(syscalls)
for c := range syscalls {
if !trans[c] {
fmt.Fprintf(os.Stderr, "disabling %v\n", c.Name)
delete(syscalls, c)
}
var disabled map[*prog.Syscall]string
syscalls, disabled = target.TransitivelyEnabledCalls(syscalls)
for c, reason := range disabled {
fmt.Fprintf(os.Stderr, "disabling %v: %v\n", c.Name, reason)
}
}
seed := time.Now().UnixNano()
Expand Down
11 changes: 4 additions & 7 deletions tools/syz-stress/stress.go
Expand Up @@ -148,14 +148,11 @@ func buildCallList(target *prog.Target) map[*prog.Syscall]bool {
}
}
for c, reason := range disabled {
Logf(0, "disabling unsupported syscall: %v: %v", c.Name, reason)
Logf(0, "unsupported syscall: %v: %v", c.Name, reason)
}
trans := target.TransitivelyEnabledCalls(calls)
for c := range calls {
if !trans[c] {
Logf(0, "disabling transitively unsupported syscall: %v", c.Name)
delete(calls, c)
}
calls, disabled = target.TransitivelyEnabledCalls(calls)
for c, reason := range disabled {
Logf(0, "transitively unsupported: %v: %v", c.Name, reason)
}
return calls
}

0 comments on commit 2a9c3ed

Please sign in to comment.