diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2022-01-23 16:35:23 -0800 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2022-01-23 16:35:23 -0800 |
commit | bbabfb4cf4280825b5aeb96bf5354d654efa246e (patch) | |
tree | 81646850df82b7b68717d6cf53dca86fe482b3b0 | |
parent | f25a1b7e69f7b33e6afb58b3e38f3450b7d2d9a0 (diff) | |
download | libcap-bbabfb4cf4280825b5aeb96bf5354d654efa246e.tar.gz |
Add a test case for a deadlock.
The CGO_ENABLED=0 failure mode is discussed in:
https://github.com/golang/go/issues/50113
At the present time, this only passes when the psx package is compiled
CGO_ENABLED=1. The problem being that a blocking read cannot be
interrupted by the CGO_ENABLED=0 build of package "psx". It does not
deadlock when compiled CGO_ENABLED=1 because the psx signal wakes the
reading thread up back into user space.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | go/.gitignore | 2 | ||||
-rw-r--r-- | go/Makefile | 20 | ||||
-rw-r--r-- | go/psx-fd.go | 25 |
3 files changed, 44 insertions, 3 deletions
diff --git a/go/.gitignore b/go/.gitignore index 9a88b0d..eca62ba 100644 --- a/go/.gitignore +++ b/go/.gitignore @@ -2,6 +2,8 @@ good-names.go compare-cap try-launching try-launching-cgo +psx-fd +psx-fd-cgo psx-signals psx-signals-cgo b210613 diff --git a/go/Makefile b/go/Makefile index fb7d6ec..4aface4 100644 --- a/go/Makefile +++ b/go/Makefile @@ -83,6 +83,18 @@ ifeq ($(CGO_REQUIRED),0) CC="$(CC)" CGO_ENABLED="1" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@-cgo $< endif +# This is a test case developed from the deadlock investigation, +# https://github.com/golang/go/issues/50113 . Note the psx-fd.go code +# works when compiled CGO_ENABLED=1, but deadlocks when compiled +# CGO_ENABLED=0. At the time of writing, this is true for go1.16+. +psx-fd: psx-fd.go PSXGOPACKAGE + CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< + +ifeq ($(CGO_REQUIRED),0) +psx-fd-cgo: psx-fd.go PSXGOPACKAGE + CC="$(CC)" CGO_ENABLED="1" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< +endif + psx-signals: psx-signals.go PSXGOPACKAGE CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< @@ -110,16 +122,18 @@ mismatch-cgo: mismatch.go CAPGOPACKAGE CC="$(CC)" CGO_ENABLED="1" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< endif -test: setid gowns captree $(TESTS) +test: setid gowns captree psx-fd $(TESTS) CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) test -mod=vendor $(IMPORTDIR)/psx CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) test -mod=vendor $(IMPORTDIR)/cap LD_LIBRARY_PATH=../libcap ./compare-cap ./psx-signals ./mismatch || exit 0 ; exit 1 + timeout 5 ./psx-fd || echo "this is a known Go bug" ifeq ($(CGO_REQUIRED),0) - $(MAKE) psx-signals-cgo mismatch-cgo + $(MAKE) psx-signals-cgo mismatch-cgo psx-fd-cgo ./psx-signals-cgo ./mismatch-cgo || exit 0 ; exit 1 + ./psx-fd-cgo endif ./setid --caps=false ./gowns -- -c "echo gowns runs" @@ -167,5 +181,5 @@ clean: rm -f compare-cap try-launching try-launching-cgo rm -f $(topdir)/cap/*~ $(topdir)/psx/*~ rm -f b210613 b215283 b215283-cgo psx-signals psx-signals-cgo - rm -f mismatch mismatch-cgo + rm -f mismatch mismatch-cgo psx-fd psx-fd-cgo rm -fr vendor CAPGOPACKAGE PSXGOPACKAGE go.sum diff --git a/go/psx-fd.go b/go/psx-fd.go new file mode 100644 index 0000000..7aa3a76 --- /dev/null +++ b/go/psx-fd.go @@ -0,0 +1,25 @@ +package main + +import ( + "log" + "os" + "syscall" + "time" + + "kernel.org/pub/linux/libs/security/libcap/psx" +) + +const prSetKeepCaps = 8 + +func main() { + r, w, err := os.Pipe() + if err != nil { + log.Fatalf("failed to obtain pipe: %v", err) + } + data := make([]byte, 2+r.Fd()) + go r.Read(data) + time.Sleep(500 * time.Millisecond) + psx.Syscall3(syscall.SYS_PRCTL, prSetKeepCaps, 1, 0) + w.Close() + r.Close() +} |