diff options
-rw-r--r-- | METADATA | 6 | ||||
-rw-r--r-- | Make.Rules | 21 | ||||
-rw-r--r-- | Makefile | 26 | ||||
-rw-r--r-- | cap/file.go | 10 | ||||
-rw-r--r-- | cap/go.mod | 2 | ||||
-rw-r--r-- | contrib/seccomp/explore.go | 83 | ||||
-rw-r--r-- | contrib/seccomp/go.mod | 2 | ||||
-rw-r--r-- | doc/libpsx.3 | 11 | ||||
-rw-r--r-- | go/.gitignore | 1 | ||||
-rw-r--r-- | go/Makefile | 16 | ||||
-rwxr-xr-x | go/cgo-required.sh | 7 | ||||
-rw-r--r-- | goapps/gowns/go.mod | 2 | ||||
-rw-r--r-- | goapps/setid/go.mod | 4 | ||||
-rw-r--r-- | goapps/web/go.mod | 2 | ||||
-rw-r--r-- | libcap/Makefile | 33 | ||||
-rw-r--r-- | libcap/include/sys/.gitignore | 1 | ||||
l--------- | libcap/include/sys/psx_syscall.h | 1 | ||||
l--------- | libcap/psx_syscall.h | 1 | ||||
-rw-r--r-- | psx/README | 30 | ||||
-rw-r--r-- | psx/psx.c | 17 | ||||
-rw-r--r-- | psx/psx.go | 2 |
21 files changed, 156 insertions, 122 deletions
@@ -5,11 +5,11 @@ third_party { type: GIT value: "https://git.kernel.org/pub/scm/linux/kernel/git/morgan/libcap.git" } - version: "libcap-2.47" + version: "libcap-2.48" license_type: NOTICE last_upgrade_date { year: 2021 - month: 1 - day: 25 + month: 2 + day: 5 } } @@ -1,7 +1,7 @@ # Common version number defines for libcap LIBTITLE=libcap VERSION=2 -MINOR=47 +MINOR=48 # ## Optional prefixes: @@ -103,16 +103,21 @@ PAM_CAP ?= $(shell if [ -f /usr/include/security/pam_modules.h ]; then echo $(SH PTHREADS ?= yes ifeq ($(PTHREADS),yes) -GO := go -GOLANG := $(shell if [ -n "$(shell $(GO) version 2>/dev/null)" ]; then echo yes ; else echo no ; fi) +GO ?= go +GOLANG ?= $(shell if [ -n "$(shell $(GO) version 2>/dev/null)" ]; then echo yes ; else echo no ; fi) ifeq ($(GOLANG),yes) -GOROOT := $(shell $(GO) env GOROOT) -GOCGO := $(shell if [ "$(shell $(GO) env CGO_ENABLED)" = 1 ]; then echo yes ; else echo no ; fi) -GOOSARCH := $(shell $(GO) env GOHOSTOS)_$(shell $(GO) env GOHOSTARCH) +GOROOT ?= $(shell $(GO) env GOROOT) +GOCGO ?= $(shell if [ "$(shell $(GO) env CGO_ENABLED)" = 1 ]; then echo yes ; else echo no ; fi) +GOOSARCH ?= $(shell $(GO) env GOHOSTOS)_$(shell $(GO) env GOHOSTARCH) +CGO_REQUIRED=$(shell $(topdir)/go/cgo-required.sh $(GO)) +ifeq ($(CGO_REQUIRED),1) +# Strictly speaking go1.15 doesn't need this, but 1.16 is when the +# real golang support arrives for non-cgo support, so drop the last +# vestige of legacy workarounds then. +CGO_LDFLAGS_ALLOW := -Wl,-?-wrap[=,][^-.@][^,]* +endif CGO_CFLAGS := -I$(topdir)/libcap/include CGO_LDFLAGS := -L$(topdir)/libcap -CGO_LDFLAGS_ALLOW := -Wl,-?-wrap[=,][^-.@][^,]* -CGO_REQUIRED=$(shell $(topdir)/go/cgo-required.sh) endif endif @@ -42,32 +42,32 @@ release: distclean cd .. && ln -s libcap libcap-$(VERSION).$(MINOR) && tar cvf libcap-$(VERSION).$(MINOR).tar --exclude patches libcap-$(VERSION).$(MINOR)/* && rm libcap-$(VERSION).$(MINOR) test: all - make -C libcap $@ - make -C tests $@ + $(MAKE) -C libcap $@ + $(MAKE) -C tests $@ ifneq ($(PAM_CAP),no) $(MAKE) -C pam_cap $@ endif ifeq ($(GOLANG),yes) - make -C go $@ + $(MAKE) -C go $@ endif - make -C progs $@ + $(MAKE) -C progs $@ sudotest: all - make -C tests $@ + $(MAKE) -C tests $@ ifneq ($(PAM_CAP),no) $(MAKE) -C pam_cap $@ endif ifeq ($(GOLANG),yes) - make -C go $@ + $(MAKE) -C go $@ endif - make -C progs $@ + $(MAKE) -C progs $@ distcheck: ./distcheck.sh - make DYNAMIC=yes clean all test sudotest - make CC=/usr/local/musl/bin/musl-gcc clean all test sudotest - make clean all test sudotest - make distclean + $(MAKE) DYNAMIC=yes clean all test sudotest + $(MAKE) CC=/usr/local/musl/bin/musl-gcc clean all test sudotest + $(MAKE) clean all test sudotest + $(MAKE) distclean morgangodoc: @echo "Now the release is made, you want to remember to run:" @@ -84,7 +84,7 @@ morganrelease: distcheck git tag -u D41A6DF2 -s v$(GOMAJOR).$(VERSION).$(MINOR) -m "This is the version tag for the 'libcap' Go base directory associated with libcap-$(VERSION).$(MINOR)." git tag -u D41A6DF2 -s psx/v$(GOMAJOR).$(VERSION).$(MINOR) -m "This is the version tag for the 'psx' Go package associated with libcap-$(VERSION).$(MINOR)." git tag -u D41A6DF2 -s cap/v$(GOMAJOR).$(VERSION).$(MINOR) -m "This is the version tag for the 'cap' Go package associated with libcap-$(VERSION).$(MINOR)." - make release + $(MAKE) release @echo "sign the tar file using korg key" cd .. && gpg -sba -u E2CCF3F4 libcap-$(VERSION).$(MINOR).tar - make morgangodoc + $(MAKE) morgangodoc diff --git a/cap/file.go b/cap/file.go index a3695b0..6658f1b 100644 --- a/cap/file.go +++ b/cap/file.go @@ -170,7 +170,7 @@ func (c *Set) GetNSOwner() (int, error) { // use file capabilities to become capable inside a namespace to be // administered by that UID. If capability aware code within that // namespace writes file capabilities without explicitly setting such -// a UID, the kernel will fixup the capabilities to be specific to +// a UID, the kernel will fix-up the capabilities to be specific to // that owner. In this way, the kernel prevents filesystem // capabilities from leaking out of that restricted namespace. func (c *Set) SetNSOwner(uid int) { @@ -228,8 +228,8 @@ func (c *Set) packFileCap() ([]byte, error) { // // Note, Linux does not store the full Effective Value Flag in the // metadata for the file. Only a single Effective bit is stored in -// this metadata. This single bit is non-zero if the Permitted vector -// has any overlapping bits with the Effective or Inheritable vector +// this metadata. This single bit is non-zero if the Effective vector +// has any overlapping bits with the Permitted or Inheritable vector // of c. This may appear suboptimal, but the reasoning behind it is // sound. Namely, the purpose of the Effective bit it to support // capabability unaware binaries that will only work if they magically @@ -237,10 +237,10 @@ func (c *Set) packFileCap() ([]byte, error) { // referred to simply as the 'legacy' bit). Without *full* support for // capability manipulation, as it is provided in this "../libcap/cap" // package, this was the only way for Go programs to make use of -// capabilities. +// file capabilities. // // The preferred way a binary will actually manipulate its -// file-acquired capabilities is to carefully and deliberately using +// file-acquired capabilities is to carefully and deliberately use // this package (or libcap, assisted by libpsx, for threaded C/C++ // family code). func (c *Set) SetFd(file *os.File) error { @@ -2,4 +2,4 @@ module kernel.org/pub/linux/libs/security/libcap/cap go 1.11 -require kernel.org/pub/linux/libs/security/libcap/psx v0.2.47 +require kernel.org/pub/linux/libs/security/libcap/psx v0.2.48 diff --git a/contrib/seccomp/explore.go b/contrib/seccomp/explore.go index b8249e0..37fe97b 100644 --- a/contrib/seccomp/explore.go +++ b/contrib/seccomp/explore.go @@ -45,32 +45,32 @@ var ( ) const ( - PR_SET_NO_NEW_PRIVS = 38 + prSetNoNewPrivs = 38 - SYS_SECCOMP = 317 // x86_64 syscall number - SECCOMP_SET_MODE_FILTER = 1 // uses user-supplied filter. - SECCOMP_FILTER_FLAG_TSYNC = (1 << 0) // mirror filtering on all threads. - SECCOMP_RET_ERRNO = 0x00050000 // returns an errno - SECCOMP_RET_DATA = 0x0000ffff // mask for RET data payload (ex. errno) - SECCOMP_RET_KILL_PROCESS = 0x80000000 // kill the whole process immediately - SECCOMP_RET_TRAP = 0x00030000 // disallow and force a SIGSYS - SECCOMP_RET_ALLOW = 0x7fff0000 + sysSeccomp = 317 // x86_64 syscall number + seccompSetModeFilter = 1 // uses user-supplied filter. + seccompFilterFlagTsync = (1 << 0) // mirror filtering on all threads. + seccompRetErrno = 0x00050000 // returns an errno + seccompRetData = 0x0000ffff // mask for RET data payload (ex. errno) + seccompRetKillProcess = 0x80000000 // kill the whole process immediately + seccompRetTrap = 0x00030000 // disallow and force a SIGSYS + seccompRetAllow = 0x7fff0000 - BPF_LD = 0x00 - BPF_JMP = 0x05 - BPF_RET = 0x06 + bpfLd = 0x00 + bpfJmp = 0x05 + bpfRet = 0x06 - BPF_W = 0x00 + bpfW = 0x00 - BPF_ABS = 0x20 - BPF_JEQ = 0x10 + bpfAbs = 0x20 + bpfJeq = 0x10 - BPF_K = 0x00 + bpfK = 0x00 - AUDIT_ARCH_X86_64 = 3221225534 // HACK: I don't understand this value - ARCH_NR = AUDIT_ARCH_X86_64 + auditArchX86_64 = 3221225534 // HACK: I don't understand this value + archNr = auditArchX86_64 - syscall_nr = 0 + syscallNr = 0 ) // SockFilter is a single filter block. @@ -95,66 +95,67 @@ type SockFProg struct { Filter *SockFilter } +// SockFilterSlice is a subprogram filter. type SockFilterSlice []SockFilter -func BPF_STMT(code uint16, k uint32) SockFilter { +func bpfStmt(code uint16, k uint32) SockFilter { return SockFilter{code, 0, 0, k} } -func BPF_JUMP(code uint16, k uint32, jt uint8, jf uint8) SockFilter { +func bpfJump(code uint16, k uint32, jt uint8, jf uint8) SockFilter { return SockFilter{code, jt, jf, k} } -func ValidateArchitecture() []SockFilter { +func validateArchitecture() []SockFilter { return []SockFilter{ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 4), // HACK: I don't understand this 4. - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS), + bpfStmt(bpfLd+bpfW+bpfAbs, 4), // HACK: I don't understand this 4. + bpfJump(bpfJmp+bpfJeq+bpfK, archNr, 1, 0), + bpfStmt(bpfRet+bpfK, seccompRetKillProcess), } } func ExamineSyscall() []SockFilter { return []SockFilter{ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr), + bpfStmt(bpfLd+bpfW+bpfAbs, syscallNr), } } func AllowSyscall(syscallNum uint32) []SockFilter { return []SockFilter{ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1), - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), + bpfJump(bpfJmp+bpfJeq+bpfK, syscallNum, 0, 1), + bpfStmt(bpfRet+bpfK, seccompRetAllow), } } func DisallowSyscall(syscallNum, errno uint32) []SockFilter { return []SockFilter{ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1), - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(errno&SECCOMP_RET_DATA)), + bpfJump(bpfJmp+bpfJeq+bpfK, syscallNum, 0, 1), + bpfStmt(bpfRet+bpfK, seccompRetErrno|(errno&seccompRetData)), } } func KillProcess() []SockFilter { return []SockFilter{ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS), + bpfStmt(bpfRet+bpfK, seccompRetKillProcess), } } func NotifyProcessAndDie() []SockFilter { return []SockFilter{ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), + bpfStmt(bpfRet+bpfK, seccompRetTrap), } } func TrapOnSyscall(syscallNum uint32) []SockFilter { return []SockFilter{ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1), - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), + bpfJump(bpfJmp+bpfJeq+bpfK, syscallNum, 0, 1), + bpfStmt(bpfRet+bpfK, seccompRetTrap), } } func AllGood() []SockFilter { return []SockFilter{ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), + bpfStmt(bpfRet+bpfK, seccompRetAllow), } } @@ -178,10 +179,10 @@ func prctl(option, arg1, arg2, arg3, arg4, arg5 uintptr) error { return nil } -// seccomp_set_mode_filter is our wrapper for performing our seccomp system call. +// SeccompSetModeFilter is our wrapper for performing our seccomp system call. //go:uintptrescapes -func seccomp_set_mode_filter(prog *SockFProg) error { - if _, _, e := syscall.RawSyscall(SYS_SECCOMP, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, uintptr(unsafe.Pointer(prog))); e != 0 { +func SeccompSetModeFilter(prog *SockFProg) error { + if _, _, e := syscall.RawSyscall(sysSeccomp, seccompSetModeFilter, seccompFilterFlagTsync, uintptr(unsafe.Pointer(prog))); e != 0 { return e } return nil @@ -220,12 +221,12 @@ func applyPolicy(prog *SockFProg) { } // This is required to load a filter without privilege. - if err := prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0); err != nil { + if err := prctl(prSetNoNewPrivs, 1, 0, 0, 0, 0); err != nil { log.Fatalf("Prctl(PR_SET_NO_NEW_PRIVS): %v", err) } fmt.Println("Applying syscall policy...") - if err := seccomp_set_mode_filter(prog); err != nil { + if err := SeccompSetModeFilter(prog); err != nil { log.Fatalf("seccomp_set_mode_filter: %v", err) } fmt.Println("...Policy applied") @@ -240,7 +241,7 @@ func main() { } var filter []SockFilter - filter = append(filter, ValidateArchitecture()...) + filter = append(filter, validateArchitecture()...) // Grab the system call number. filter = append(filter, ExamineSyscall()...) diff --git a/contrib/seccomp/go.mod b/contrib/seccomp/go.mod index d9efa2e..86e40c6 100644 --- a/contrib/seccomp/go.mod +++ b/contrib/seccomp/go.mod @@ -2,4 +2,4 @@ module explore go 1.14 -require kernel.org/pub/linux/libs/security/libcap/psx v0.2.47 +require kernel.org/pub/linux/libs/security/libcap/psx v0.2.48 diff --git a/doc/libpsx.3 b/doc/libpsx.3 index a3535a6..61baa88 100644 --- a/doc/libpsx.3 +++ b/doc/libpsx.3 @@ -1,4 +1,4 @@ -.TH LIBPSX 3 "2020-10-13" "" "Linux Programmer's Manual" +.TH LIBPSX 3 "2021-01-31" "" "Linux Programmer's Manual" .SH NAME psx_syscall3, psx_syscall6 \- POSIX semantics for system calls .SH SYNOPSIS @@ -36,7 +36,9 @@ signal. Whereas the mechanism uses signo=33 (which is hidden by glibc below a redefined SIGRTMIN), .B libpsx -usurps SIGRTMAX for this process. +inserts itself in the SIGSYS handler stack. It goes to great length to +be the first such handler but acts as a pass-through for other SIGSYS +uses. .PP A linker trick of .I wrapping @@ -73,7 +75,10 @@ threads of the process. .SH CONFORMING TO The needs of .BR libcap (3) -for POSIX semantics of capability manipulation. +for POSIX semantics of capability manipulation. You can read more +about why this is needed here: +.TP +https://sites.google.com/site/fullycapable/who-ordered-libpsx .SH "REPORTING BUGS" Please report bugs via: .TP diff --git a/go/.gitignore b/go/.gitignore index 30ae0b6..c0a9737 100644 --- a/go/.gitignore +++ b/go/.gitignore @@ -3,6 +3,7 @@ compare-cap try-launching try-launching-cgo psx-signals +psx-signals-cgo b210613 mknames web diff --git a/go/Makefile b/go/Makefile index b8745f1..757844a 100644 --- a/go/Makefile +++ b/go/Makefile @@ -76,12 +76,11 @@ ifeq ($(CGO_REQUIRED),0) GO111MODULE=off CGO_ENABLED="1" CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@-cgo $< endif -# Bug reported issues: -# https://bugzilla.kernel.org/show_bug.cgi?id=210533 (cgo - fixed) -# https://github.com/golang/go/issues/43149 (nocgo - not fixed yet) -# When the latter is fixed we can replace CGO_ENABLED=1 with ="$(CGO_REQUIRED)" -psx-signals: psx-signals.go $(PSXGOPACKAGE) - GO111MODULE=off CGO_ENABLED=1 CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" GOPATH=$(GOPATH) $(GO) build $< +psx-signals: psx-signals.go $(PSXGOPACKAGE) + GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" GOPATH=$(GOPATH) $(GO) build $< +ifeq ($(CGO_REQUIRED),0) + GO111MODULE=off CGO_ENABLED="1" CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" GOPATH=$(GOPATH) $(GO) build -o $@-cgo $< +endif b210613: b210613.go $(CAPGOPACKAGE) GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" GOPATH=$(GOPATH) $(GO) build $< @@ -91,6 +90,9 @@ test: all GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH="$(GOPATH)" $(GO) test $(IMPORTDIR)/cap LD_LIBRARY_PATH=../libcap ./compare-cap ./psx-signals +ifeq ($(CGO_REQUIRED),0) + ./psx-signals-cgo +endif ./setid --caps=false ./gowns -- -c "echo gowns runs" @@ -122,5 +124,5 @@ clean: rm -f web setid gowns rm -f compare-cap try-launching try-launching-cgo rm -f $(topdir)/cap/*~ $(topdir)/psx/*~ - rm -f psx-signals b210613 + rm -f b210613 psx-signals psx-signals-cgo rm -fr pkg src diff --git a/go/cgo-required.sh b/go/cgo-required.sh index 7551138..f9afa52 100755 --- a/go/cgo-required.sh +++ b/go/cgo-required.sh @@ -4,8 +4,13 @@ # available to the working go runtime or not. If it isn't we always # have to use libcap/psx to get POSIX semantics for syscalls that # change security state. +if [ -n "$1" ]; then + export GO="${1}" +else + export GO=go +fi -if [ -z "$(go doc syscall 2>/dev/null|grep AllThreadsSyscall)" ]; then +if [ -z "$(${GO} doc syscall 2>/dev/null|grep AllThreadsSyscall)" ]; then echo "1" else echo "0" diff --git a/goapps/gowns/go.mod b/goapps/gowns/go.mod index 3863fbb..bc534af 100644 --- a/goapps/gowns/go.mod +++ b/goapps/gowns/go.mod @@ -2,4 +2,4 @@ module gowns go 1.15 -require kernel.org/pub/linux/libs/security/libcap/cap v0.2.47 +require kernel.org/pub/linux/libs/security/libcap/cap v0.2.48 diff --git a/goapps/setid/go.mod b/goapps/setid/go.mod index b227144..cd2282d 100644 --- a/goapps/setid/go.mod +++ b/goapps/setid/go.mod @@ -3,6 +3,6 @@ module setid go 1.11 require ( - kernel.org/pub/linux/libs/security/libcap/cap v0.2.47 - kernel.org/pub/linux/libs/security/libcap/psx v0.2.47 + kernel.org/pub/linux/libs/security/libcap/cap v0.2.48 + kernel.org/pub/linux/libs/security/libcap/psx v0.2.48 ) diff --git a/goapps/web/go.mod b/goapps/web/go.mod index a2dac7d..f7ae28b 100644 --- a/goapps/web/go.mod +++ b/goapps/web/go.mod @@ -2,4 +2,4 @@ module web go 1.11 -require kernel.org/pub/linux/libs/security/libcap/cap v0.2.47 +require kernel.org/pub/linux/libs/security/libcap/cap v0.2.48 diff --git a/libcap/Makefile b/libcap/Makefile index 230be39..9563d88 100644 --- a/libcap/Makefile +++ b/libcap/Makefile @@ -28,18 +28,18 @@ MINPSXLIBNAME=$(MAJPSXLIBNAME).$(MINOR) all: pcs $(STACAPLIBNAME) ifeq ($(SHARED),yes) - make $(CAPLIBNAME) + $(MAKE) $(CAPLIBNAME) endif ifeq ($(PTHREADS),yes) - make $(STAPSXLIBNAME) + $(MAKE) $(STAPSXLIBNAME) ifeq ($(SHARED),yes) - make $(PSXLIBNAME) + $(MAKE) $(PSXLIBNAME) endif endif pcs: libcap.pc ifeq ($(PTHREADS),yes) - make libpsx.pc + $(MAKE) libpsx.pc endif ifeq ($(BUILD_GPERF),yes) @@ -88,8 +88,8 @@ $(STACAPLIBNAME): $(CAPOBJS) $(AR) rcs $@ $^ $(RANLIB) $@ -$(STAPSXLIBNAME): $(PSXOBJS) - $(AR) rcs $@ $^ +$(STAPSXLIBNAME): $(PSXOBJS) include/sys/psx_syscall.h + $(AR) rcs $@ $(PSXOBJS) $(RANLIB) $@ ifeq ($(SHARED),yes) @@ -98,8 +98,8 @@ $(CAPLIBNAME) $(MAJCAPLIBNAME) $(MINCAPLIBNAME): $(CAPOBJS) ln -sf $(MINCAPLIBNAME) $(MAJCAPLIBNAME) ln -sf $(MAJCAPLIBNAME) $(CAPLIBNAME) -$(PSXLIBNAME) $(MAJPSXLIBNAME) $(MINPSXLIBNAME): $(PSXOBJS) - $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(MAJPSXLIBNAME) -o $(MINPSXLIBNAME) $^ $(PSXLINKFLAGS) +$(PSXLIBNAME) $(MAJPSXLIBNAME) $(MINPSXLIBNAME): $(PSXOBJS) include/sys/psx_syscall.h + $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(MAJPSXLIBNAME) -o $(MINPSXLIBNAME) $(PSXOBJS) $(PSXLINKFLAGS) ln -sf $(MINPSXLIBNAME) $(MAJPSXLIBNAME) ln -sf $(MAJPSXLIBNAME) $(PSXLIBNAME) endif @@ -118,27 +118,27 @@ test: cap_test install: install-static ifeq ($(SHARED),yes) - make install-shared + $(MAKE) install-shared endif install-static: install-static-cap ifeq ($(PTHREADS),yes) - make install-static-psx + $(MAKE) install-static-psx endif install-shared: install-shared-cap ifeq ($(PTHREADS),yes) - make install-shared-psx + $(MAKE) install-shared-psx endif install-cap: install-static-cap ifeq ($(SHARED),yes) - make install-shared-cap + $(MAKE) install-shared-cap endif install-psx: install-static-psx ifeq ($(SHARED),yes) - make install-shared-psx + $(MAKE) install-shared-psx endif install-static-cap: install-common-cap $(STACAPLIBNAME) @@ -167,7 +167,11 @@ install-common-cap: install-common libcap.pc install -m 0644 include/sys/capability.h $(FAKEROOT)$(INCDIR)/sys install -m 0644 libcap.pc $(FAKEROOT)$(PKGCONFIGDIR)/libcap.pc -install-common-psx: install-common libpsx.pc +include/sys/psx_syscall.h: ../psx/psx_syscall.h + rm -f $@ + ln -s ../../../psx/psx_syscall.h $@ + +install-common-psx: install-common libpsx.pc include/sys/psx_syscall.h install -m 0644 include/sys/psx_syscall.h $(FAKEROOT)$(INCDIR)/sys install -m 0644 libpsx.pc $(FAKEROOT)$(PKGCONFIGDIR)/libpsx.pc @@ -181,4 +185,5 @@ clean: rm -f $(CAPOBJS) $(CAPLIBNAME)* $(STACAPLIBNAME) libcap.pc rm -f $(PSXOBJS) $(PSXLIBNAME)* $(STAPSXLIBNAME) libpsx.pc rm -f cap_names.h cap_names.list.h _makenames $(GPERF_OUTPUT) cap_test + rm -f include/sys/psx_syscall.h cd include/sys && $(LOCALCLEAN) diff --git a/libcap/include/sys/.gitignore b/libcap/include/sys/.gitignore new file mode 100644 index 0000000..595fc39 --- /dev/null +++ b/libcap/include/sys/.gitignore @@ -0,0 +1 @@ +psx_syscall.h diff --git a/libcap/include/sys/psx_syscall.h b/libcap/include/sys/psx_syscall.h deleted file mode 120000 index ebac5fe..0000000 --- a/libcap/include/sys/psx_syscall.h +++ /dev/null @@ -1 +0,0 @@ -../../../psx/psx_syscall.h
\ No newline at end of file diff --git a/libcap/psx_syscall.h b/libcap/psx_syscall.h deleted file mode 120000 index dc748bb..0000000 --- a/libcap/psx_syscall.h +++ /dev/null @@ -1 +0,0 @@ -include/sys/psx_syscall.h
\ No newline at end of file @@ -1,20 +1,28 @@ -Package psx provides a CGo backed API for invoking system calls in a -way that each system call is mirrored on all pthreads of the combined -Go/CGo runtime. Since the Go runtime treats all pthreads as -interchangeable, a feature like this is needed to meaningfully change -process privilege (including dropping privilege) in a Go program -running on Linux. This package is required by: +Package "psx" provides an API for invoking system calls in a way that +each system call is mirrored on all OS threads of the combined Go/CGo +runtime. Since the Go runtime treats OS threads as interchangeable, a +feature like this is needed to meaningfully change process privilege +(including dropping privilege) in a Go program running on Linux. This +package is required by: "kernel.org/pub/linux/libs/security/libcap/cap" -The functionality is implemented by a C library: libpsx, which is -distributed with the libcap. The official release announcement site -for libcap and libpsx is: +When compiled CGO_ENABLED=0, the functionality requires go1.16+ to +build. That release of Go introduced syscall.AllThreadsSyscall*() +APIs. When compiled this way, the "psx" package functions +psx.Syscall3() and psx.Syscall6() are aliased to +syscall.AllThreadsSyscall() and syscall.AllThreadsSyscall6() +respectively. + +When compiled CGO_ENABLED=1, the functionality is implemented by C +code, [lib]psx, which is distributed with libcap. + +The official release announcement site for libcap and libpsx is: https://sites.google.com/site/fullycapable/ -Like libcap/libpsx itself, the psx package is distributed with a "you -choose" License. Specifically: BSD three clause, or GPL2. See the +Like libcap/libpsx itself, the "psx" package is distributed with a +"you choose" License. Specifically: BSD three clause, or GPL2. See the LICENSE file. Andrew G. Morgan <morgan@kernel.org> @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019,20 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 2019-21 Andrew G Morgan <morgan@kernel.org> * * This file contains a collection of routines that perform thread * synchronization to ensure that a whole process is running as a @@ -30,12 +30,12 @@ #include "psx_syscall.h" /* - * psx_load_syscalls() is weakly defined so we can have it overridden - * by libpsx if it is linked. Specifically, when libcap calls - * psx_load_sycalls it will override their defaut values. As can be - * seen here this present function is a no-op. However, if libpsx is - * linked, the one present in that library (not being weak) will - * replace this one. + * psx_load_syscalls() can be weakly defined in dependent libraries to + * provide a mechanism for a library to optionally leverage this psx + * mechanism. Specifically, when libcap calls psx_load_sycalls() it + * provides a weakly declared default that maps its system calls to + * the regular system call functions. However, when linked with psx, + * this function here overrides the syscalls to be the psx ones. */ void psx_load_syscalls(long int (**syscall_fn)(long int, long int, long int, long int), @@ -96,7 +96,8 @@ static struct psx_tracker_s { /* * psx_action_key is used for thread local storage of the thread's - * registration. */ + * registration. + */ pthread_key_t psx_action_key; /* @@ -7,6 +7,8 @@ import ( "syscall" ) +// Syscall3 and Syscall6 are aliases for syscall.AllThreadsSyscall* +// when compiled CGO_ENABLED=0. var ( Syscall3 = syscall.AllThreadsSyscall Syscall6 = syscall.AllThreadsSyscall6 |