From 2a9c3edcdaf644772298c92be942bfbb7170b35c Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 6 Apr 2018 19:43:06 +0200 Subject: pkg/prog: explain why syscalls are transitively disabled --- prog/decl_test.go | 36 ++++++++++++++++++++++++++---------- prog/resources.go | 23 ++++++++++++++++------- 2 files changed, 42 insertions(+), 17 deletions(-) (limited to 'prog') diff --git a/prog/decl_test.go b/prog/decl_test.go index 72a6435e8..4539be2fb 100644 --- a/prog/decl_test.go +++ b/prog/decl_test.go @@ -5,6 +5,7 @@ package prog import ( "runtime" + "strings" "testing" ) @@ -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"]] || @@ -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) { @@ -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)) } } diff --git a/prog/resources.go b/prog/resources.go index e6ef080cd..33c497d5a 100644 --- a/prog/resources.go +++ b/prog/resources.go @@ -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 } @@ -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] { @@ -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 } -- cgit mrf-deployment