Projects
Factory:RISC-V:Base
libcap
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
_service:tar_scm:libcap.spec
Changed
@@ -1,16 +1,12 @@ Name: libcap -Version: 2.61 -Release: 4 +Version: 2.66 +Release: 1 Summary: A library for getting and setting POSIX.1e draft 15 capabilities License: GPLv2 URL: https://sites.google.com/site/fullycapable Source0: https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/%{name}-%{version}.tar.gz Patch0: libcap-buildflags.patch -Patch1: Fix-syntax-error-in-DEBUG-protected-setcap.c-code.patch -Patch2: backport-psx-free-allocated-memory-at-exit.patch -Patch3: backport-Avoid-a-deadlock-in-forked-psx-thread-exit.patch -Patch4: backport-getpcaps-catch-PID-parsing-errors.patch BuildRequires: libattr-devel pam-devel perl-interpreter gcc @@ -74,6 +70,9 @@ %{_mandir}/man8/*.gz %changelog +* Mon Jan 30 2023 wangyunjia <yunjia.wang@huawei.com> - 2.66-1 +- update version to 2.66 + * Tue Nov 1 2022 yixiangzhike <yixiangzhike007@163.com> - 2.61-4 - backport upstream patch
View file
_service:tar_scm:Fix-syntax-error-in-DEBUG-protected-setcap.c-code.patch
Deleted
@@ -1,28 +0,0 @@ -From 21d08b03c2a737e4384a07857e0289ad0126b663 Mon Sep 17 00:00:00 2001 -From: "Andrew G. Morgan" <morgan@kernel.org> -Date: Sun, 17 Apr 2022 06:41:23 -0700 -Subject: PATCH Fix syntax error in DEBUG protected setcap.c code. - -Bug reported with fix from yixiangzhike. - -Signed-off-by: Andrew G. Morgan <morgan@kernel.org> ---- - progs/setcap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/progs/setcap.c b/progs/setcap.c -index 02a8a5d..737efcc 100644 ---- a/progs/setcap.c -+++ b/progs/setcap.c -@@ -176,7 +176,7 @@ int main(int argc, char **argv) - { - char *result = cap_to_text(cap_d, NULL); - fprintf(stderr, "caps set to: %s\n", result); -- cap_free(result) -+ cap_free(result); - } - #endif - } --- -2.27.0 -
View file
_service:tar_scm:backport-Avoid-a-deadlock-in-forked-psx-thread-exit.patch
Deleted
@@ -1,60 +0,0 @@ -From 7617af6b0754da00c1094215ee7828d6592f8ade Mon Sep 17 00:00:00 2001 -From: "Andrew G. Morgan" <morgan@kernel.org> -Date: Sun, 10 Apr 2022 15:39:14 -0700 -Subject: PATCH Avoid a deadlock in forked psx thread exit. - -go/captree was seeing lots of libcap_psx_test processes hanging around. -It turns out that the newly added _psx_cleanup() function was deadlocking -because inside a forked processes the psx_tracker.state was _PSX_INFORK -and never _PSX_IDLE. - -This completes the fix for: - - https://bugzilla.kernel.org/show_bug.cgi?id=215551 - -Signed-off-by: Andrew G. Morgan <morgan@kernel.org> ---- - psx/psx.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/psx/psx.c b/psx/psx.c -index 1876978..d9c0485 100644 ---- a/psx/psx.c -+++ b/psx/psx.c -@@ -287,7 +287,9 @@ static void psx_unlock(void) - } - - /* -- * under lock perform a state transition. -+ * under lock perform a state transition. Changing state is generally -+ * done via this function. However, there is a single exception in -+ * _psx_cleanup(). - */ - static void psx_new_state(psx_tracker_state_t was, psx_tracker_state_t is) - { -@@ -351,7 +353,7 @@ static void _psx_forked_child(void) { - * - * We do this because the glibc man page for fork() suggests that - * only a subset of things will work post fork(). Specifically, -- * only a "async-signal-safe functions (see signal- safety(7)) -+ * only a "async-signal-safe functions (see signal-safety(7)) - * until such time as it calls execve(2)" can be relied upon. That - * man page suggests that you can't expect mutexes to work: "not - * async-signal-safe because it uses pthread_mutex_lock(3) -@@ -733,7 +735,12 @@ static void _psx_cleanup(void) { - * never leave this state since this cleanup is only done at - * program exit. - */ -- psx_new_state(_PSX_IDLE, _PSX_EXITING); -+ psx_lock(); -+ while (psx_tracker.state != _PSX_IDLE && psx_tracker.state != _PSX_INFORK) { -+ pthread_cond_wait(&psx_tracker.cond, &psx_tracker.state_mu); -+ } -+ psx_tracker.state = _PSX_EXITING; -+ psx_unlock(); - - for (ref = psx_tracker.root; ref; ref = next) { - next = ref->next; --- -2.27.0 -
View file
_service:tar_scm:backport-getpcaps-catch-PID-parsing-errors.patch
Deleted
@@ -1,52 +0,0 @@ -From fc804acc078ef03e2c5b3a233f118a537f260ccd Mon Sep 17 00:00:00 2001 -From: Jakub Wilk <jwilk@jwilk.net> -Date: Thu, 1 Sep 2022 22:23:19 +0200 -Subject: PATCH getpcaps: catch PID parsing errors. - -Signed-off-by: Jakub Wilk <jwilk@jwilk.net> -Signed-off-by: Andrew G. Morgan <morgan@kernel.org> ---- - progs/getpcaps.c | 19 ++++++++++++++++++- - 1 file changed, 18 insertions(+), 1 deletion(-) - -diff --git a/progs/getpcaps.c b/progs/getpcaps.c -index 8fce0a3..1e914b2 100644 ---- a/progs/getpcaps.c -+++ b/progs/getpcaps.c -@@ -39,7 +39,9 @@ int main(int argc, char **argv) - } - - for ( ++argv; --argc > 0; ++argv ) { -+ long lpid; - int pid; -+ char *endarg; - cap_t cap_d; - - if (!strcmp(argv0, "--help") || !strcmp(argv0, "--usage") || -@@ -62,7 +64,22 @@ int main(int argc, char **argv) - continue; - } - -- pid = atoi(argv0); -+ errno = 0; -+ lpid = strtol(argv0, &endarg, 10); -+ if (*endarg != '\0') { -+ errno = EINVAL; -+ } -+ if (errno == 0) { -+ if (lpid < 0 || pid != (pid_t) pid) -+ errno = EOVERFLOW; -+ } -+ if (errno != 0) { -+ fprintf(stderr, "Cannot parse pid %s (%s)\n", -+ argv0, strerror(errno)); -+ retval = 1; -+ continue; -+ } -+ pid = lpid; - - cap_d = cap_get_pid(pid); - if (cap_d == NULL) { --- -2.27.0 -
View file
_service:tar_scm:backport-psx-free-allocated-memory-at-exit.patch
Deleted
@@ -1,102 +0,0 @@ -From 66a8a1421e4520e9dda0a46704e25bafb989b1ae Mon Sep 17 00:00:00 2001 -From: "Andrew G. Morgan" <morgan@kernel.org> -Date: Sat, 5 Feb 2022 17:26:05 -0800 -Subject: PATCH psx: free allocated memory at exit. - -Kalen Hall reported that Valgrind detected a memory leak associated -with a multi-threaded program linked against libcap and libpsx. - - https://bugzilla.kernel.org/show_bug.cgi?id=215551 - -I've been unable to validate this myself with valgrind (likely holding -it wrong), but did explore psx for allocated memory and via fprintf's -convinced myself that this change should pair all calloc()s with a -corresponding free(). - -Signed-off-by: Andrew G. Morgan <morgan@kernel.org> ---- - psx/psx.c | 44 +++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 43 insertions(+), 1 deletion(-) - -diff --git a/psx/psx.c b/psx/psx.c -index 6b669ae..1876978 100644 ---- a/psx/psx.c -+++ b/psx/psx.c -@@ -29,6 +29,26 @@ - - #include "psx_syscall.h" - -+#ifdef _PSX_DEBUG_MEMORY -+ -+static void *_psx_calloc(const char *file, const int line, -+ size_t nmemb, size_t size) { -+ void *ptr = calloc(nmemb, size); -+ fprintf(stderr, "psx:%d:%s:%d: calloc(%ld, %ld) -> %p\n", gettid(), -+ file, line, (long int)nmemb, (long int)size, ptr); -+ return ptr; -+} -+ -+static void _psx_free(const char *file, const int line, void *ptr) { -+ fprintf(stderr, "psx:%d:%s:%d: free(%p)\n", gettid(), file, line, ptr); -+ return free(ptr); -+} -+ -+#define calloc(a, b) _psx_calloc(__FILE__, __LINE__, a, b) -+#define free(a) _psx_free(__FILE__, __LINE__, a) -+ -+#endif /* def _PSX_DEBUG_MEMORY */ -+ - /* - * psx_load_syscalls() can be weakly defined in dependent libraries to - * provide a mechanism for a library to optionally leverage this psx -@@ -177,6 +197,7 @@ static void psx_posix_syscall_actor(int signum, siginfo_t *info, void *ignore) { - * Some forward declarations for the initialization - * psx_syscall_start() routine. - */ -+static void _psx_cleanup(void); - static void _psx_prepare_fork(void); - static void _psx_fork_completed(void); - static void _psx_forked_child(void); -@@ -240,6 +261,7 @@ static void psx_syscall_start(void) { - - psx_confirm_sigaction(); - psx_do_registration(); /* register the main thread. */ -+ atexit(_psx_cleanup); - - psx_tracker.initialized = 1; - } -@@ -420,7 +442,7 @@ static void _psx_exiting(void *node) { - pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL); - - /* -- * Allow the rest of the psx system carry on as per normal. -+ * Allow the rest of the psx system to carry on as per normal. - */ - psx_new_state(_PSX_EXITING, _PSX_IDLE); - } -@@ -699,2 +721,22 @@ defer: - return ret; - } -+/* -+ * _psx_cleanup its called when the program exits. It is used to free -+ * any memory used by the thread tracker. -+ */ -+static void _psx_cleanup(void) { -+ registered_thread_t *ref, *next; -+ -+ /* -+ * We enter the exiting state. Unlike exiting a single thread we -+ * never leave this state since this cleanup is only done at -+ * program exit. -+ */ -+ psx_new_state(_PSX_IDLE, _PSX_EXITING); -+ -+ for (ref = psx_tracker.root; ref; ref = next) { -+ next = ref->next; -+ psx_do_unregister(ref); -+ } -+} -+ --- -2.27.0 -
View file
_service:tar_scm:libcap-2.61.tar.gz/Make.Rules -> _service:tar_scm:libcap-2.66.tar.gz/Make.Rules
Changed
@@ -1,7 +1,7 @@ # Common version number defines for libcap LIBTITLE=libcap VERSION=2 -MINOR=61 +MINOR=66 # ## Optional prefixes: @@ -92,7 +92,19 @@ BUILD_CFLAGS ?= $(BUILD_COPTS) BUILD_CPPFLAGS += -Dlinux $(WARNINGS) $(DEBUG) $(DEFINES) $(LIBCAP_INCLUDES) BUILD_LDFLAGS ?= $(LDFLAGS) -BUILD_GPERF := $(shell which gperf >/dev/null 2>/dev/null && echo yes) +BUILD_SED ?= sed +BUILD_GREP ?= grep +BUILD_EGREP ?= $(BUILD_GREP) -E +BUILD_FGREP ?= $(BUILD_GREP) -F + +# Plan to eventually redefine BUILD_GPERF to be the actual gperf tool +# alias as per above. Typical distributions are upto a year behind +# HEAD so we'll not do that before 2023-01-01. +ifdef BUILD_GPERF +$(error BUILD_GPERF is now reserved, please use USE_GPERF=yes or no instead) +endif + +USE_GPERF ?= $(shell which gperf >/dev/null 2>/dev/null && echo yes) LIBCAPLIB := -L$(topdir)/libcap -lcap PSXLINKFLAGS := -lpthread -Wl,-wrap,pthread_create @@ -136,7 +148,7 @@ # vestige of legacy workarounds then. CGO_LDFLAGS_ALLOW := CGO_LDFLAGS_ALLOW="-Wl,-?-wrap=,^-.@^,*" endif -CGO_CFLAGS := -I$(topdir)/libcap/include +CGO_CFLAGS := $(LIBCAP_INCLUDES) CGO_LDFLAGS := -L$(topdir)/libcap GO_BUILD_FLAGS := endif
View file
_service:tar_scm:libcap-2.61.tar.gz/Makefile -> _service:tar_scm:libcap-2.66.tar.gz/Makefile
Changed
@@ -35,8 +35,11 @@ distclean: clean $(DISTCLEAN) @echo "CONFIRM Go package cap has right version dependency on cap/psx:" - for x in $$(find . -name go.mod); do grep -F -v "module" $$x | fgrep "kernel.org/pub/linux/libs/security/libcap" > /dev/null || continue ; grep -F "v$(GOMAJOR).$(VERSION).$(MINOR)" $$x > /dev/null && continue ; echo "$$x is not updated. Try running: ./gomods.sh v$(GOMAJOR).$(VERSION).$(MINOR)" ; exit 1 ; done + for x in $$(find . -name go.mod); do $(BUILD_FGREP) -v "module" $$x | $(BUILD_FGREP) "kernel.org/pub/linux/libs/security/libcap" > /dev/null || continue ; $(BUILD_FGREP) "v$(GOMAJOR).$(VERSION).$(MINOR)" $$x > /dev/null && continue ; echo "$$x is not updated. Try running: ./gomods.sh v$(GOMAJOR).$(VERSION).$(MINOR)" ; exit 1 ; done @echo "ALL go.mod files updated" + @echo "Confirm headers export current version" + $(BUILD_FGREP) "#define LIBCAP_MAJOR $(VERSION)" libcap/include/sys/capability.h + $(BUILD_FGREP) "#define LIBCAP_MINOR $(MINOR)" libcap/include/sys/capability.h @echo "Now validate that everything is checked in to a clean tree.." test -z "$$(git status --ignored -s)" @echo "All good!" @@ -47,12 +50,12 @@ ktest: all $(MAKE) -C kdebug test -distcheck: +distcheck: distclean ./distcheck.sh $(MAKE) DYNAMIC=no COPTS="-D_FORTIFY_SOURCE=2 -O1 -g" clean test $(MAKE) DYNAMIC=yes clean all test sudotest $(MAKE) DYNAMIC=no COPTS="-O2 -std=c89" clean all test sudotest - $(MAKE) PAM_CAP=no CC=/usr/local/musl/bin/musl-gcc clean all test sudotest + $(MAKE) PAM_CAP=no CC=musl-gcc clean all test sudotest $(MAKE) CC=clang clean all test sudotest $(MAKE) clean all test sudotest $(MAKE) distclean
View file
_service:tar_scm:libcap-2.61.tar.gz/cap/convenience.go -> _service:tar_scm:libcap-2.66.tar.gz/cap/convenience.go
Changed
@@ -75,6 +75,7 @@ ModeNoPriv ModePure1EInit ModePure1E + ModeHybrid ) // GetMode assesses the current process state and summarizes it as @@ -82,6 +83,9 @@ // declared ModeUncertain. func GetMode() Mode { b := GetSecbits() + if b == 0 { + return ModeHybrid + } if b&securedBasicBits != securedBasicBits { return ModeUncertain } @@ -141,6 +145,10 @@ return err } + if m == ModeHybrid { + return sc.setSecbits(0) + } + if m == ModeNoPriv || m == ModePure1EInit { w.ClearFlag(Inheritable) } else if m != ModePure1E { @@ -199,6 +207,8 @@ return "PURE1E_INIT" case ModePure1E: return "PURE1E" + case ModeHybrid: + return "HYBRID" default: return "UNKNOWN" }
View file
_service:tar_scm:libcap-2.61.tar.gz/cap/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/cap/go.mod
Changed
@@ -2,4 +2,4 @@ go 1.11 -require kernel.org/pub/linux/libs/security/libcap/psx v1.2.61 +require kernel.org/pub/linux/libs/security/libcap/psx v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/cap/launch.go -> _service:tar_scm:libcap-2.66.tar.gz/cap/launch.go
Changed
@@ -181,6 +181,10 @@ // lResult is used to get the result from the doomed launcher thread. type lResult struct { + // tgid holds the thread group id, which is an alias for the + // shared process id of the parent program. + tgid int + // tid holds the tid of the locked launching thread which dies // as the launch completes. tid int @@ -232,13 +236,15 @@ defer close(quit) } - pid := syscall.Getpid() + // Thread group ID is the process ID. + tgid := syscall.Getpid() + // This code waits until we are not scheduled on the parent // thread. We will exit this thread once the child has // launched. runtime.LockOSThread() tid := syscall.Gettid() - if tid == pid { + if tid == tgid { // Force the go runtime to find a new thread to run // on. (It is really awkward to have a process' // PID=TID thread in effectively a zombie state. The @@ -257,6 +263,12 @@ return } + // Provide a way to serialize the caller on the thread + // completing. This should be done by the one locked tid that + // does the ForkExec(). All the other threads have a different + // security context. + defer close(result) + // By never releasing the LockOSThread here, we guarantee that // the runtime will terminate the current OS thread once this // function returns. @@ -266,10 +278,6 @@ // the callbackFn or something else hangs up. singlesc.prctlrcall(prSetName, uintptr(unsafe.Pointer(&lName0)), 0) - // Provide a way to serialize the caller on the thread - // completing. - defer close(result) - var pa *syscall.ProcAttr var err error var needChroot bool @@ -289,12 +297,12 @@ } } + var pid int if attr.callbackFn != nil { if err = attr.callbackFn(pa, data); err != nil { goto abort } if attr.path == "" { - pid = 0 goto abort } } @@ -341,16 +349,30 @@ pid = -1 } result <- lResult{ - tid: tid, - pid: pid, - err: err, + tgid: tgid, + tid: tid, + pid: pid, + err: err, } } +// pollForThreadExit waits for a thread to terminate. Only after the +// thread has safely exited is it safe to resume POSIX semantics +// security state mirroring for the rest of the process threads. +func (v lResult) pollForThreadExit() { + if v.tid == -1 { + return + } + for syscall.Tgkill(v.tgid, v.tid, 0) == nil { + runtime.Gosched() + } + scwSetState(launchActive, launchIdle, v.tid) +} + // Launch performs a callback function and/or new program launch with // a disposable security state. The data object, when not nil, can be // used to communicate with the callback. It can also be used to -// return details from the callback functions execution. +// return details from the callback function's execution. // // If the attr was created with NewLauncher(), this present function // will return the pid of the launched process, or -1 and a non-nil @@ -362,15 +384,15 @@ // callback return value. // // Note, while the disposable security state thread makes some -// oprerations seem more isolated - they are *not securely +// operations seem more isolated - they are *not securely // isolated*. Launching is inherently violating the POSIX semantics // maintained by the rest of the "libcap/cap" package, so think of // launching as a convenience wrapper around fork()ing. // // Advanced user note: if the caller of this function thinks they know // what they are doing by using runtime.LockOSThread() before invoking -// this function, they should understand that the OS Thread invoking -// (*Launcher).Launch() is *not guaranteed* to be the one used for the +// this function, they should understand that the OS thread invoking +// (*Launcher).Launch() is *not* guaranteed to be the one used for the // disposable security state to perform the launch. If said caller // needs to run something on the disposable security state thread, // they should do it via the launch callback function mechanism. (The @@ -391,18 +413,11 @@ result := make(chan lResult) go launch(result, attr, data, nil) - for { - select { - case v, ok := <-result: - if !ok { - return -1, ErrLaunchFailed - } - if v.tid != -1 { - defer scwSetState(launchActive, launchIdle, v.tid) - } - return v.pid, v.err - default: - runtime.Gosched() - } + v, ok := <-result + if !ok { + return -1, ErrLaunchFailed } + <-result // blocks until the launch() goroutine exits + v.pollForThreadExit() + return v.pid, v.err }
View file
_service:tar_scm:libcap-2.61.tar.gz/contrib/seccomp/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/contrib/seccomp/go.mod
Changed
@@ -2,4 +2,4 @@ go 1.14 -require kernel.org/pub/linux/libs/security/libcap/psx v1.2.61 +require kernel.org/pub/linux/libs/security/libcap/psx v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/contrib/sucap/Makefile -> _service:tar_scm:libcap-2.66.tar.gz/contrib/sucap/Makefile
Changed
@@ -1,12 +1,18 @@ topdir=$(shell pwd)/../.. include ../../Make.Rules +# This line is here to link against the in-tree copy of libcap.so +LINKEXTRA=-Wl,-rpath,$(topdir)/libcap +DEPS=../../libcap/libcap.so + all: su -su: su.c - $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DPAM_APP_NAME=\"sucap\" -o $@ $< -lpam -lpam_misc -lcap +su: su.c $(DEPS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DPAM_APP_NAME=\"sucap\" $< -o $@ $(LINKEXTRA) -lpam -lpam_misc $(LIBCAPLIB) # to permit all ambient capabilities, this needs all permitted. - sudo setcap =p ./su + # sudo setcap =p ./su + # to permit all inheritable, as CAP_PURE1E needs, we don't need as much + sudo setcap cap_chown,cap_setgid,cap_setuid,cap_dac_read_search,cap_setpcap=p ./su clean: rm -f su su.o *~
View file
_service:tar_scm:libcap-2.61.tar.gz/contrib/sucap/su.c -> _service:tar_scm:libcap-2.66.tar.gz/contrib/sucap/su.c
Changed
@@ -149,20 +149,26 @@ if (fstat(1, &st) == -1) { fd = open("/dev/null", O_WRONLY); - if (fd == -1) exit(1); + if (fd == -1) goto badfds; if (fd != 1) { - if (dup2(fd, 1) == -1) exit(1); - if (close(fd) == -1) exit(1); + if (dup2(fd, 1) == -1) goto badfds; + if (close(fd) == -1) goto badfds; } } if (fstat(2, &st) == -1) { fd = open("/dev/null", O_WRONLY); - if (fd == -1) exit(1); + if (fd == -1) goto badfds; if (fd != 2) { - if (dup2(fd, 2) == -1) exit(1); - if (close(fd) == -1) exit(1); + if (dup2(fd, 2) == -1) goto badfds; + if (close(fd) == -1) goto badfds; } } + + return; + +badfds: + perror("bad filedes"); + exit(1); } /* @@ -1210,6 +1216,11 @@ } uid = pw->pw_uid; + if (uid == 0) { + D(("user is superuser: %s", user)); + *retval = PAM_CRED_ERR; + return 1; + } *uid_p = uid; shell = x_strdup(pw->pw_shell); @@ -1226,11 +1237,18 @@ *retval = PAM_CRED_ERR; return 1; } - if (pam_misc_setenv(pamh, "HOME", pw->pw_dir, 0) != PAM_SUCCESS) { - D(("failed to set HOME")); - *retval = PAM_CRED_ERR; - return 1; - } + } + + /* bash requires these be set to the target user values */ + if (pam_misc_setenv(pamh, "HOME", pw->pw_dir, 0) != PAM_SUCCESS) { + D(("failed to set HOME")); + *retval = PAM_CRED_ERR; + return 1; + } + if (pam_misc_setenv(pamh, "USER", user, 0) != PAM_SUCCESS) { + D(("failed to set USER")); + *retval = PAM_CRED_ERR; + return 1; } current = cap_get_proc(); @@ -1613,5 +1631,8 @@ } su_exit: + if (status != 0) { + perror(PAM_APP_NAME " failed"); + } exit(status); /* transparent exit */ }
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/Makefile -> _service:tar_scm:libcap-2.66.tar.gz/doc/Makefile
Changed
@@ -8,7 +8,7 @@ MAN1S = capsh.1 MAN3S = cap_init.3 cap_free.3 cap_dup.3 \ cap_clear.3 cap_clear_flag.3 cap_get_flag.3 cap_set_flag.3 \ - cap_fill.3 cap_fill_flag.3 \ + cap_fill.3 cap_fill_flag.3 cap_max_bits.3 \ cap_compare.3 cap_get_proc.3 cap_get_pid.3 cap_set_proc.3 \ cap_get_file.3 cap_get_fd.3 cap_set_file.3 cap_set_fd.3 \ cap_copy_ext.3 cap_size.3 cap_copy_int.3 cap_mode.3 \ @@ -26,7 +26,8 @@ cap_iab_get_proc.3 cap_iab_get_pid.3 cap_iab_set_proc.3 \ cap_iab_to_text.3 cap_iab_from_text.3 cap_iab_get_vector.3 \ cap_iab_set_vector.3 cap_iab_fill.3 \ - psx_syscall.3 psx_syscall3.3 psx_syscall6.3 libpsx.3 + psx_syscall.3 psx_syscall3.3 psx_syscall6.3 psx_set_sensitivity.3 \ + libpsx.3 MAN8S = getcap.8 setcap.8 getpcaps.8 captree.8 MANS = $(MAN1S) $(MAN3S) $(MAN8S) @@ -44,7 +45,7 @@ mkdir -p html for man in $(MANS) ; \ do \ - egrep '^\.so man' $$man > /dev/null || \ + $(BUILD_EGREP) '^\.so man' $$man > /dev/null || \ groff -man -Thtml $$man > html/$$man.html ; \ done
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/cap_clear.3 -> _service:tar_scm:libcap-2.66.tar.gz/doc/cap_clear.3
Changed
@@ -139,11 +139,14 @@ .BR EINVAL , indicating that one of the arguments is invalid. .SH "CONFORMING TO" -These functions are as per the withdrawn POSIX.1e draft specification. -.BR cap_clear_flag () -and +These functions are mostly as per specified in the withdrawn POSIX.1e +draft specification. The following are Linux extensions: +.BR cap_fill (), +.BR cap_fill_flag (), +.BR cap_clear_flag (), .BR cap_compare () -are Linux extensions. +and +.BR cap_max_bits (). .SH "SEE ALSO" .BR libcap (3), .BR cap_copy_ext (3),
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/cap_from_text.3 -> _service:tar_scm:libcap-2.66.tar.gz/doc/cap_from_text.3
Changed
@@ -1,7 +1,7 @@ .\" .\" written by Andrew Main <zefram@dcs.warwick.ac.uk> .\" -.TH CAP_FROM_TEXT 3 "2021-03-06" "" "Linux Programmer's Manual" +.TH CAP_FROM_TEXT 3 "2022-09-22" "" "Linux Programmer's Manual" .SH NAME cap_from_text, cap_to_text, cap_to_name, cap_from_name \- capability state textual representation translation @@ -10,7 +10,7 @@ #include <sys/capability.h> cap_t cap_from_text(const char* buf_p ); -char *cap_to_text(cap_t caps, ssize_t * length_p); +char *cap_to_text(cap_t caps, ssize_t * len_p); int cap_from_name(const char* name , cap_value_t* cap_p); char *cap_to_name(cap_value_t cap); .fi @@ -46,7 +46,7 @@ .PP .BR cap_to_text () converts the capability state in working storage identified by -.I cap_p +.I caps into a nul-terminated human-readable string. This function allocates any memory necessary to contain the string, and returns a pointer to the string. If the pointer @@ -56,7 +56,7 @@ the nul terminator) in the location pointed to by .IR len_p . The capability state in working storage, identified by -.IR cap_p , +.IR caps , is completely represented in the character string. When the capability state in working storage is no longer required, the caller should free any releasable memory by calling
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/cap_get_proc.3 -> _service:tar_scm:libcap-2.66.tar.gz/doc/cap_get_proc.3
Changed
@@ -1,4 +1,4 @@ -.TH CAP_GET_PROC 3 "2021-03-06" "" "Linux Programmer's Manual" +.TH CAP_GET_PROC 3 "2022-04-28" "" "Linux Programmer's Manual" .SH NAME cap_get_proc, cap_set_proc, capgetp, cap_get_bound, cap_drop_bound, \ cap_get_ambient, cap_set_ambient, cap_reset_ambient, \ @@ -65,18 +65,40 @@ unchanged. .PP .BR cap_get_pid () -returns +returns a .IR cap_t , see .BR cap_init (3), -with the process capabilities of the process indicated by +with the process capabilities of the process known to the caller as .IR pid . -(If +If .I pid -is 0, then the calling process's capabilities are returned.) +is 0, then the calling process's capabilities are returned. This information can also be obtained from the .I /proc/<pid>/status -file. +file. (The entries in that file can be translated with the +.BI "capsh \-\-decode=" XXX +command line.) When the caller is operating within a +.RB ( CLONE_NEWPID ) +namespace, the numerical +.I pid +argument is interpreted in the range of that namespace. As such, the +caller's idea of the target +.I pid +may differ from that of the target process when they are operating in +different pid namespaces. See +.BR pid_namespaces (7) +for details. +Further, the returned +.I cap_t +value holds the capabilities that the target +.I pid +thinks it has. If the target is operating in a +.RB ( CLONE_NEWUSER ) +namespace, the system wide privilege of those user namespace +capabilities my be substantially reduced. See +.BR user_namespaces (7) +for details. .PP .BR cap_get_bound () with a @@ -120,16 +142,13 @@ .PP .BR cap_reset_ambient () resets all of the ambient capabilities for the calling process to -their lowered value. To complete successfully, the prevailing -.I effective -capability set must have a raised -.BR CAP_SETPCAP . -Note, the ambient set is intended to operate in a legacy environment -where the application has limited awareness of capabilities in -general. Executing a file with associated filesystem capabilities, the -kernel will implicitly reset the ambient set of the process. Also, -changes to the inheritable set by the program code without explicitly -fixing up the ambient set can also drop ambient bits. +their lowered value. Note, the ambient set is intended to operate in a +legacy environment where the application has limited awareness of +capabilities in general. Executing a file, with associated filesystem +capabilities, the kernel will implicitly reset the ambient set of the +process. Further, changes to the inheritable set by the program code +without explicitly fixing up the ambient set can also drop ambient +bits. .PP .BR cap_get_secbits () returns the securebits of the calling process. These bits affect the @@ -378,7 +397,7 @@ .B capsh tool as follows: .sp -.B sudo /sbin/capsh \-\-user=nobody \-\-mode=NOPRIV \-\-print +.B sudo capsh \-\-user=nobody \-\-mode=NOPRIV \-\-print .sp where .B \-\-print @@ -392,5 +411,8 @@ .BR cap_from_text (3), .BR cap_get_file (3), .BR cap_init (3), +.BR namespaces (7), +.BR pid_namespaces (7), +.BR user_namespaces (7), .BR psx_syscall (3), .BR capabilities (7).
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/capsh.1 -> _service:tar_scm:libcap-2.66.tar.gz/doc/capsh.1
Changed
@@ -329,6 +329,12 @@ .B \-\-noamb Drops all ambient capabilities from the running process. .TP +.B \-\-noenv +Suppresses overriding of the HOME and USER environment variables when +a subsequent +.B \-\-user +argument is processed. +.TP .B \-\-quiet This argument is ignored unless it is the first one. If present, it suppresses the capsh runtime check to confirm the running libcap is
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/captree.8 -> _service:tar_scm:libcap-2.66.tar.gz/doc/captree.8
Changed
@@ -1,15 +1,15 @@ .\" Hey, EMACS: -*- nroff -*- -.TH CAPTREE 8 "2021-09-02" +.TH CAPTREE 8 "2022-04-11" .\" Please adjust this date whenever revising the manpage. .SH NAME -captree \- display process tree capabilities +captree \- display tree of process capabilities .SH SYNOPSIS -.BR captree " optional args " -.IR pid|glob-name ... +.BR captree " OPTIONS " +.RI ( pid | glob-name ") ..." .SH DESCRIPTION .B captree displays the capabilities on the mentioned processes indicated by -.IR pid or glob-name +.IR pid " or " glob-name value(s) given on the command line. If no .I pid etc values are supplied, @@ -34,7 +34,8 @@ values): .TP .B \-\-help -Displays usage information and exits. +Displays usage information and exits. Note, modern Go runtimes exit +with status 0 in this case, but older runtimes exit with status 2. .TP .BR \-\-verbose Displays capability sets and IAB tuples even when they are empty, or @@ -51,7 +52,11 @@ defaults to true when running via a TTY. The \fB--color\fI=false\fR argument will suppress this color. Piping the output into some other program will also suppress the use of colour. - +.SH EXIT STATUS +If the supplied target cannot be found the exit status is 1. Should an +unrecognized option be provided, the exit status is 2. Otherwise, +.B captree +exits with status 0. .SH REPORTING BUGS Please report bugs via: .TP
View file
_service:tar_scm:libcap-2.61.tar.gz/doc/libpsx.3 -> _service:tar_scm:libcap-2.66.tar.gz/doc/libpsx.3
Changed
@@ -1,12 +1,13 @@ -.TH LIBPSX 3 "2021-03-06" "" "Linux Programmer's Manual" +.TH LIBPSX 3 "2021-12-12" "" "Linux Programmer's Manual" .SH NAME -psx_syscall3, psx_syscall6 \- POSIX semantics for system calls +psx_syscall3, psx_syscall6, psx_set_sensitivity \- POSIX semantics for system calls .SH SYNOPSIS .nf #include <sys/psx_syscall.h> long int psx_syscall3(long int syscall_nr, long int arg1, long int arg2, long int arg3); long int psx_syscall6(long int syscall_nr, long int arg1, long int arg2, long int arg3, long int arg4, long int arg5, long int arg6); +int psx_set_sensitivity(psx_sensitivity_t sensitivity); .fi .sp Link with one of these: @@ -62,6 +63,17 @@ and .BR psx_syscall6 () functions as needed. +.PP +.BR psx_set_sensitivity () +changes the behavior of the mirrored system calls: +.B PSX_IGNORE +ensures that differences are ignored (the default behavior); +.B PSX_WARNING +prints a stderr notification about how the results differ; and +.B PSX_ERROR +prints the error details and generates a +.B SIGSYS +signal. .SH RETURN VALUE The return value for system call functions is generally the value returned by the kernel, or \-1 in the case of an error. In such cases
View file
_service:tar_scm:libcap-2.66.tar.gz/doc/psx_set_sensitivity.3
Added
@@ -0,0 +1,1 @@ +.so man3/libpsx.3
View file
_service:tar_scm:libcap-2.61.tar.gz/go/.gitignore -> _service:tar_scm:libcap-2.66.tar.gz/go/.gitignore
Changed
@@ -2,14 +2,21 @@ compare-cap try-launching try-launching-cgo +psx-fd +psx-fd-cgo psx-signals psx-signals-cgo b210613 +b215283 +b215283-cgo +mismatch +mismatch-cgo mknames web setid gowns captree +captrace ok vendor go.sum
View file
_service:tar_scm:libcap-2.61.tar.gz/go/Makefile -> _service:tar_scm:libcap-2.66.tar.gz/go/Makefile
Changed
@@ -14,9 +14,9 @@ PKGDIR=pkg/$(GOOSARCH)/$(IMPORTDIR) DEPS=../libcap/libcap.a ../libcap/libpsx.a -TESTS=compare-cap try-launching psx-signals +TESTS=compare-cap try-launching psx-signals mismatch -all: PSXGOPACKAGE CAPGOPACKAGE web setid gowns captree +all: PSXGOPACKAGE CAPGOPACKAGE web setid gowns captree captrace $(DEPS): $(MAKE) -C ../libcap all @@ -24,8 +24,10 @@ ../progs/tcapsh-static: $(MAKE) -C ../progs tcapsh-static -vendor/$(IMPORTDIR) vendor/modules.txt: +vendor/$(IMPORTDIR): mkdir -p "vendor/$(IMPORTDIR)" + +vendor/modules.txt: vendor/$(IMPORTDIR) echo "# $(IMPORTDIR)/psx v$(GOMAJOR).$(VERSION).$(MINOR)" > vendor/modules.txt echo "$(IMPORTDIR)/psx" >> vendor/modules.txt echo "# $(IMPORTDIR)/cap v$(GOMAJOR).$(VERSION).$(MINOR)" >> vendor/modules.txt @@ -55,7 +57,7 @@ # Compiles something with this package to compare it to libcap. This # tests more when run under sudotest (see ../progs/quicktest.sh for that). compare-cap: compare-cap.go CAPGOPACKAGE - CC="$(CC)" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< + CC="$(CC)" CGO_ENABLED="1" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< web: ../goapps/web/web.go CAPGOPACKAGE CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< @@ -74,8 +76,11 @@ captree: ../goapps/captree/captree.go CAPGOPACKAGE CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< -ok: ok.go - CC="$(CC)" CGO_ENABLED=0 $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< +captrace: ../goapps/captrace/captrace.go CAPGOPACKAGE + CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor -o $@ $< + +ok: ok.go vendor/modules.txt + CC="$(CC)" CGO_ENABLED="0" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< try-launching: try-launching.go CAPGOPACKAGE ok CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< @@ -83,6 +88,21 @@ 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. This is true for go1.16 and go1.17. The go1.18 +# release fixed this by rewriting the AllThreadsSyscall support, but +# the large change was not backported. (See noted bug for a much +# smaller patch for this issue on those older releases.) +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 $< @@ -94,14 +114,34 @@ b210613: b210613.go CAPGOPACKAGE CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< -test: setid gowns captree $(TESTS) +b215283: b215283.go CAPGOPACKAGE + CC="$(CC)" CGO_ENABLED="$(CGO_REQUIRED)" $(CGO_LDFLAGS_ALLOW) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build $(GO_BUILD_FLAGS) -mod=vendor $< + +ifeq ($(CGO_REQUIRED),0) +b215283-cgo: b215283.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 + +mismatch: mismatch.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 $< + +ifeq ($(CGO_REQUIRED),0) +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 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 + $(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" @@ -110,7 +150,7 @@ # Note, the user namespace doesn't require sudo, but I wanted to avoid # requiring that the hosting kernel supports user namespaces for the # regular test case. -sudotest: test ../progs/tcapsh-static b210613 +sudotest: test ../progs/tcapsh-static b210613 b215283 ../progs/tcapsh-static --has-b=cap_sys_admin || exit 0 && ./gowns --ns -- -c "echo gowns runs with user namespace" ./try-launching ifeq ($(CGO_REQUIRED),0) @@ -121,6 +161,12 @@ $(SUDO) ./try-launching-cgo endif $(SUDO) ../progs/tcapsh-static --cap-uid=$$(id -u) --caps="cap_setpcap=ep" --iab="^cap_setpcap" -- -c ./b210613 + $(SUDO) ./b215283 +ifeq ($(CGO_REQUIRED),0) + $(MAKE) b215283-cgo + $(SUDO) ./b215283-cgo +endif + # As of libcap-2.55 We stopped installing the cap and psx packages as # part of the install. Most distribution's packagers skip the Go @@ -139,8 +185,9 @@ clean: rm -f *.o *.so *~ mknames ok good-names.go - rm -f web setid gowns captree + rm -f web setid gowns captree captrace rm -f compare-cap try-launching try-launching-cgo rm -f $(topdir)/cap/*~ $(topdir)/psx/*~ - rm -f b210613 psx-signals psx-signals-cgo + rm -f b210613 b215283 b215283-cgo psx-signals psx-signals-cgo + rm -f mismatch mismatch-cgo psx-fd psx-fd-cgo rm -fr vendor CAPGOPACKAGE PSXGOPACKAGE go.sum
View file
_service:tar_scm:libcap-2.66.tar.gz/go/b215283.go
Added
@@ -0,0 +1,47 @@ +// Program b215283 requires privilege to execute and is a minimally adapted +// version of a test case provided by Lorenz Bauer as a reproducer for a +// problem he found and reported in: +// +// https://bugzilla.kernel.org/show_bug.cgi?id=215283 +package main + +import ( + "fmt" + "os" + + "kernel.org/pub/linux/libs/security/libcap/cap" +) + +func main() { + const secbits = cap.SecbitNoRoot | cap.SecbitNoSetUIDFixup + + if v, err := cap.GetProc().GetFlag(cap.Permitted, cap.SETPCAP); err != nil { + panic(fmt.Sprintf("failed to get flag value: %v", err)) + os.Exit(1) + } else if !v { + fmt.Printf("test requires cap_setpcap: found %q\n", cap.GetProc()) + os.Exit(1) + } + if bits := cap.GetSecbits(); bits != 0 { + fmt.Printf("test expects secbits=0 to run; found: 0%o\n", bits) + os.Exit(1) + } + + fmt.Println("secbits:", cap.GetSecbits(), " caps:", cap.GetProc()) + + l := cap.FuncLauncher(func(interface{}) error { + return cap.NewSet().SetProc() + }) + + if _, err := l.Launch(nil); err != nil { + fmt.Printf("launch failed: %v\n", err) + os.Exit(1) + } + + fmt.Println("secbits:", cap.GetSecbits(), " caps:", cap.GetProc()) + + if err := secbits.Set(); err != nil { + fmt.Printf("set securebits: %v", err.Error()) + os.Exit(1) + } +}
View file
_service:tar_scm:libcap-2.61.tar.gz/go/compare-cap.go -> _service:tar_scm:libcap-2.66.tar.gz/go/compare-cap.go
Changed
@@ -158,8 +158,8 @@ log.Fatalf("wrong of groups: got=%v want=100 l01", gs) } - if mode := cap.GetMode(); mode != cap.ModeUncertain { - log.Fatalf("initial mode should be 0 (UNCERTAIN), got: %d (%v)", mode, mode) + if mode := cap.GetMode(); mode != cap.ModeHybrid { + log.Fatalf("initial mode should be 4 (HYBRID), got: %d (%v)", mode, mode) } // To distinguish PURE1E and PURE1E_INIT we need an inheritable capability set.
View file
_service:tar_scm:libcap-2.61.tar.gz/go/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/go/go.mod
Changed
@@ -3,6 +3,6 @@ go 1.11 require ( - kernel.org/pub/linux/libs/security/libcap/cap v1.2.61 - kernel.org/pub/linux/libs/security/libcap/psx v1.2.61 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 + kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 )
View file
_service:tar_scm:libcap-2.66.tar.gz/go/mismatch.go
Added
@@ -0,0 +1,15 @@ +// Program mismatch should panic because the syscall being requested +// never returns consistent results. +package main + +import ( + "fmt" + "syscall" + + "kernel.org/pub/linux/libs/security/libcap/psx" +) + +func main() { + tid, _, err := psx.Syscall3(syscall.SYS_GETTID, 0, 0, 0) + fmt.Printf("gettid() -> %d: %v\n", tid, err) +}
View file
_service:tar_scm:libcap-2.66.tar.gz/go/psx-fd.go
Added
@@ -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() +}
View file
_service:tar_scm:libcap-2.66.tar.gz/goapps/captrace
Added
+(directory)
View file
_service:tar_scm:libcap-2.66.tar.gz/goapps/captrace/captrace.go
Added
@@ -0,0 +1,230 @@ +// Program captrace traces processes and notices when they attempt +// kernel actions that require Effective capabilities. +// +// The reference material for developing this tool was the the book +// "Linux Observabililty with BPF" by David Calavera and Lorenzo +// Fontana. +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "log" + "os" + "os/exec" + "strconv" + "strings" + "sync" + "syscall" + "time" + + "kernel.org/pub/linux/libs/security/libcap/cap" +) + +var ( + bpftrace = flag.String("bpftrace", "bpftrace", "command to launch bpftrace") + debug = flag.Bool("debug", false, "more output") + pid = flag.Int("pid", -1, "PID of target process to trace (-1 = trace all)") +) + +type thread struct { + PPID, Datum int + Value cap.Value + Token string +} + +// mu protects these two maps. +var mu sync.Mutex + +// tids tracks which PIDs we are following. +var tids = make(mapintint) + +// cache tracks in-flight cap_capable invocations. +var cache = make(mapint*thread) + +// event adds or resolves a capability event. +func event(add bool, tid int, th *thread) { + mu.Lock() + defer mu.Unlock() + + if len(tids) != 0 { + if _, ok := tidsth.PPID; !ok { + if *debug { + log.Printf("dropped %d %d %v event", th.PPID, tid, *th) + } + return + } + tidstid = th.PPID + tidsth.PPID = th.PPID + } + + if add { + cachetid = th + } else { + if b, ok := cachetid; ok { + detail := "" + if th.Datum < 0 { + detail = fmt.Sprintf(" (%v)", syscall.Errno(-th.Datum)) + } + task := "" + if th.PPID != tid { + task = fmt.Sprintf("+{%d}", tid) + } + log.Printf("%-16s %d%s opt=%d %q -> %d%s", b.Token, b.PPID, task, b.Datum, b.Value, th.Datum, detail) + } + delete(cache, tid) + } +} + +// tailTrace tails the bpftrace command output recognizing lines of +// interest. +func tailTrace(cmd *exec.Cmd, out io.Reader) { + launched := false + sc := bufio.NewScanner(out) + for sc.Scan() { + fields := strings.Split(sc.Text(), " ") + if len(fields) < 4 { + continue // ignore + } + if !launched { + launched = true + mu.Unlock() + } + switch fields0 { + case "CB": + if len(fields) < 6 { + continue + } + pid, err := strconv.Atoi(fields1) + if err != nil { + continue + } + th := &thread{ + PPID: pid, + } + tid, err := strconv.Atoi(fields2) + if err != nil { + continue + } + c, err := strconv.Atoi(fields3) + if err != nil { + continue + } + th.Value = cap.Value(c) + aud, err := strconv.Atoi(fields4) + if err != nil { + continue + } + th.Datum = aud + th.Token = strings.Join(fields5:, " ") + event(true, tid, th) + case "CE": + if len(fields) < 4 { + continue + } + pid, err := strconv.Atoi(fields1) + if err != nil { + continue + } + th := &thread{ + PPID: pid, + } + tid, err := strconv.Atoi(fields2) + if err != nil { + continue + } + aud, err := strconv.Atoi(fields3) + if err != nil { + continue + } + th.Datum = aud + event(false, tid, th) + default: + if *debug { + fmt.Println("unparsable:", fields) + } + } + } + if err := sc.Err(); err != nil { + log.Fatalf("scanning failed: %v", err) + } +} + +// tracer invokes bpftool it returns an error if the invocation fails. +func tracer() (*exec.Cmd, error) { + cmd := exec.Command(*bpftrace, "-e", `kprobe:cap_capable { + printf("CB %d %d %d %d %s\n", pid, tid, arg2, arg3, comm); +} +kretprobe:cap_capable { + printf("CE %d %d %d\n", pid, tid, retval); +}`) + out, err := cmd.StdoutPipe() + cmd.Stderr = os.Stderr + if err != nil { + return nil, fmt.Errorf("unable to create stdout for %q: %v", *bpftrace, err) + } + mu.Lock() // Unlocked on first ouput from tracer. + if err := cmd.Start(); err != nil { + return nil, fmt.Errorf("failed to start %q: %v", *bpftrace, err) + } + go tailTrace(cmd, out) + return cmd, nil +} + +func main() { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s options command ... + +This tool monitors cap_capable() kernel execution to summarize when +Effective Flag capabilities are checked in a running process{thread}. +The monitoring is performed indirectly using the bpftrace tool. + +Each line logged has a timestamp at which the tracing program is able to +summarize the return value of the check. A return value of " -> 0" implies +the check succeeded and confirms the process{thread} does have the +specified Effective capability. + +The listed "opt=" value indicates some auditing context for why the +kernel needed to check the capability was Effective. + +Options: +`, os.Args0) + flag.PrintDefaults() + } + flag.Parse() + + tr, err := tracer() + if err != nil { + log.Fatalf("failed to start tracer: %v", err) + } + + mu.Lock() + + if *pid != -1 { + tids*pid = *pid + } else if len(flag.Args()) != 0 { + args := flag.Args() + cmd := exec.Command(args0, args1:...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Start(); err != nil { + log.Fatalf("failed to start %v: %v", flag.Args(), err) + } + tidscmd.Process.Pid = cmd.Process.Pid + + // waiting for the trace to complete is racy, so we sleep + // to obtain the last events then kill the tracer and wait + // for it to exit. Defers are in reverse order. + defer tr.Wait() + defer tr.Process.Kill() + defer time.Sleep(1 * time.Second) + + tr = cmd + } + + mu.Unlock() + tr.Wait() +}
View file
_service:tar_scm:libcap-2.66.tar.gz/goapps/captrace/go.mod
Added
@@ -0,0 +1,5 @@ +module captrace + +go 1.16 + +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/goapps/captree/captree.go -> _service:tar_scm:libcap-2.66.tar.gz/goapps/captree/captree.go
Changed
@@ -340,6 +340,7 @@ return } fmt.Printf("no process matched %q\n", glob) + os.Exit(1) }() return finds } @@ -356,6 +357,10 @@ } func main() { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s options pid|glob ...\nOptions:\n", os.Args0) + flag.PrintDefaults() + } flag.Parse() // Honor the command line request if possible.
View file
_service:tar_scm:libcap-2.61.tar.gz/goapps/captree/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/goapps/captree/go.mod
Changed
@@ -2,4 +2,4 @@ go 1.16 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.61 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/goapps/gowns/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/goapps/gowns/go.mod
Changed
@@ -2,4 +2,4 @@ go 1.15 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.61 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/goapps/setid/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/goapps/setid/go.mod
Changed
@@ -3,6 +3,6 @@ go 1.11 require ( - kernel.org/pub/linux/libs/security/libcap/cap v1.2.61 - kernel.org/pub/linux/libs/security/libcap/psx v1.2.61 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 + kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 )
View file
_service:tar_scm:libcap-2.61.tar.gz/goapps/web/go.mod -> _service:tar_scm:libcap-2.66.tar.gz/goapps/web/go.mod
Changed
@@ -2,4 +2,4 @@ go 1.11 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.61 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/Makefile -> _service:tar_scm:libcap-2.66.tar.gz/libcap/Makefile
Changed
@@ -52,13 +52,13 @@ $(MAKE) $(PSXTITLE).pc endif -ifeq ($(BUILD_GPERF),yes) +ifeq ($(USE_GPERF),yes) USE_GPERF_OUTPUT = $(GPERF_OUTPUT) INCLUDE_GPERF_OUTPUT = -DINCLUDE_GPERF_OUTPUT='"$(GPERF_OUTPUT)"' endif $(LIBTITLE).pc: $(LIBTITLE).pc.in - sed -e 's,@prefix@,$(prefix),' \ + $(BUILD_SED) -e 's,@prefix@,$(prefix),' \ -e 's,@exec_prefix@,$(exec_prefix),' \ -e 's,@libdir@,$(LIBDIR),' \ -e 's,@includedir@,$(inc_prefix)/include,' \ @@ -67,7 +67,7 @@ $< >$@ $(PSXTITLE).pc: $(PSXTITLE).pc.in - sed -e 's,@prefix@,$(prefix),' \ + $(BUILD_SED) -e 's,@prefix@,$(prefix),' \ -e 's,@exec_prefix@,$(exec_prefix),' \ -e 's,@libdir@,$(LIBDIR),' \ -e 's,@includedir@,$(inc_prefix)/include,' \ @@ -81,18 +81,22 @@ cap_names.h: _makenames ./_makenames > cap_names.h -$(GPERF_OUTPUT): cap_names.list.h - perl -e 'print "struct __cap_token_s { const char *name; int index; };\n%{\nconst struct __cap_token_s *__cap_lookup_name(const char *, size_t);\n%}\n%%\n"; while ($$l = <>) { $$l =~ s/\{\"//g; $$l =~ s/\}.*// ; print $$l; }' < $< | gperf --ignore-case --language=ANSI-C --readonly --null-strings --global-table --hash-function-name=__cap_hash_name --lookup-function-name="__cap_lookup_name" -c -t -m20 $(INDENT) > $@ - sed -e 's/unsigned int len/size_t len/' -i $@ +$(GPERF_OUTPUT): cap_names.list.h cap_names.header Makefile + (cat cap_names.header ; $(BUILD_SED) -e 's/\{\}"//g' -e 's/,$$//' cap_names.list.h) | gperf --ignore-case --language=ANSI-C --readonly --null-strings --global-table --hash-function-name=__cap_hash_name --lookup-function-name="__cap_lookup_name" -c -t -m20 $(INDENT) > $@ + $(BUILD_SED) -e 's/unsigned int len/size_t len/' -i $@ # Intention is that libcap keeps up with torvalds' tree, as reflected # by this maintained version of the kernel header. libcap dynamically # trims the meaning of "all" capabilities down to that of the running -# kernel as of 2.30. +# kernel as of 2.30. That is, all production kernels should be equal +# to or behind libcap. +# +# Note "./libcap.so --summary" should explain how the built libcap.so +# compares to the running kernel. UAPI_HEADER := $(topdir)/libcap/include/uapi/linux/capability.h cap_names.list.h: Makefile $(UAPI_HEADER) @echo "=> making $@ from $(UAPI_HEADER)" - perl -e 'while ($$l=<>) { if ($$l =~ /^\#define \t(CAP_A-Z+) \t+(0-9+)\s+$$/) { $$tok=$$1; $$val=$$2; $$tok =~ tr/A-Z/a-z/; print "{\"$$tok\",$$val},\n"; } }' $(UAPI_HEADER) | fgrep -v 0x > $@ + $(BUILD_EGREP) '^#define\s+CAP_(^\s+)\s+0-9+\s*$$' include/uapi/linux/capability.h | $(BUILD_SED) -e 's/^#define\s\+/{"/' -e 's/\s*$$/},/' -e 's/\s\+/",/' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' > $@ $(STACAPLIBNAME): $(CAPOBJS) $(AR) rcs $@ $^ @@ -104,6 +108,9 @@ ifeq ($(SHARED),yes) +empty: empty.c + $(CC) -o $@ $< + loader.txt: empty $(OBJCOPY) --dump-section .interp=$@ $< /dev/null
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/cap_alloc.c -> _service:tar_scm:libcap-2.66.tar.gz/libcap/cap_alloc.c
Changed
@@ -19,14 +19,15 @@ __attribute__((constructor (300))) void _libcap_initialize() { + int errno_saved = errno; _cap_mu_lock(&__libcap_mutex); - if (_cap_max_bits) { - _cap_mu_unlock(&__libcap_mutex); - return; + if (!_cap_max_bits) { + cap_set_syscall(NULL, NULL); + _binary_search(_cap_max_bits, cap_get_bound, 0, __CAP_MAXBITS, + __CAP_BITS); } - cap_set_syscall(NULL, NULL); - _binary_search(_cap_max_bits, cap_get_bound, 0, __CAP_MAXBITS, __CAP_BITS); _cap_mu_unlock(&__libcap_mutex); + errno = errno_saved; } cap_value_t cap_max_bits(void)
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/cap_file.c -> _service:tar_scm:libcap-2.66.tar.gz/libcap/cap_file.c
Changed
@@ -12,7 +12,6 @@ #include <byteswap.h> #include <sys/stat.h> #include <unistd.h> -#include <linux/xattr.h> /* * We hardcode the prototypes for the Linux system calls here since
View file
_service:tar_scm:libcap-2.66.tar.gz/libcap/cap_names.header
Added
@@ -0,0 +1,5 @@ +struct __cap_token_s { const char *name; int index; }; +%{ +const struct __cap_token_s *__cap_lookup_name(const char *, size_t); +%} +%%
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/cap_proc.c -> _service:tar_scm:libcap-2.66.tar.gz/libcap/cap_proc.c
Changed
@@ -18,8 +18,6 @@ #include <sys/types.h> #include <sys/wait.h> -#include <linux/limits.h> - #include "libcap.h" /* @@ -137,7 +135,13 @@ long int pr_cmd, long int arg1, long int arg2) { if (_libcap_overrode_syscalls) { - return sc->three(SYS_prctl, pr_cmd, arg1, arg2); + int result; + result = sc->three(SYS_prctl, pr_cmd, arg1, arg2); + if (result >= 0) { + return result; + } + errno = -result; + return -1; } return prctl(pr_cmd, arg1, arg2, 0, 0, 0); } @@ -147,7 +151,13 @@ long int arg3, long int arg4, long int arg5) { if (_libcap_overrode_syscalls) { - return sc->six(SYS_prctl, pr_cmd, arg1, arg2, arg3, arg4, arg5); + int result; + result = sc->six(SYS_prctl, pr_cmd, arg1, arg2, arg3, arg4, arg5); + if (result >= 0) { + return result; + } + errno = -result; + return -1; } return prctl(pr_cmd, arg1, arg2, arg3, arg4, arg5); } @@ -273,26 +283,12 @@ int cap_get_bound(cap_value_t cap) { - int result; - - result = prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0)); - if (result < 0) { - errno = -result; - return -1; - } - return result; + return prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0)); } static int _cap_drop_bound(struct syscaller_s *sc, cap_value_t cap) { - int result; - - result = _libcap_wprctl3(sc, PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0)); - if (result < 0) { - errno = -result; - return -1; - } - return result; + return _libcap_wprctl3(sc, PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0)); } /* drop a capability from the bounding set */ @@ -318,7 +314,7 @@ static int _cap_set_ambient(struct syscaller_s *sc, cap_value_t cap, cap_flag_value_t set) { - int result, val; + int val; switch (set) { case CAP_SET: val = PR_CAP_AMBIENT_RAISE; @@ -330,13 +326,8 @@ errno = EINVAL; return -1; } - result = _libcap_wprctl6(sc, PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap), - pr_arg(0), pr_arg(0), pr_arg(0)); - if (result < 0) { - errno = -result; - return -1; - } - return result; + return _libcap_wprctl6(sc, PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap), + pr_arg(0), pr_arg(0), pr_arg(0)); } /* @@ -488,7 +479,9 @@ /* for good measure */ _cap_set_no_new_privs(sc); break; - + case CAP_MODE_HYBRID: + ret = _cap_set_secbits(sc, 0); + break; default: errno = EINVAL; ret = -1; @@ -524,6 +517,9 @@ { unsigned secbits = cap_get_secbits(); + if (secbits == 0) { + return CAP_MODE_HYBRID; + } if ((secbits & CAP_SECURED_BITS_BASIC) != CAP_SECURED_BITS_BASIC) { return CAP_MODE_UNCERTAIN; }
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/cap_test.c -> _service:tar_scm:libcap-2.66.tar.gz/libcap/cap_test.c
Changed
@@ -124,7 +124,7 @@ } if (strlen(tmp) > __CAP_NAME_SIZE) { printf("cap_to_text buffer size reservation needs fixing (%ld > %d)\n", - strlen(tmp), __CAP_NAME_SIZE); + (long int)strlen(tmp), __CAP_NAME_SIZE); result = -1; } free(tmp); @@ -254,6 +254,21 @@ return retval; } +static int test_prctl(void) +{ + int ret, retval=0; + errno = 0; + ret = cap_get_bound((cap_value_t) -1); + if (ret != -1) { + printf("cap_get_bound(-1) did not return error: %d\n", ret); + retval = -1; + } else if (errno != EINVAL) { + perror("cap_get_bound(-1) errno != EINVAL"); + retval = -1; + } + return retval; +} + int main(int argc, char **argv) { int result = 0; @@ -269,6 +284,9 @@ printf("test_alloc: being called\n"); fflush(stdout); result = test_alloc() | result; + printf("test_prctl: being called\n"); + fflush(stdout); + result = test_prctl() | result; printf("tested\n"); fflush(stdout);
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/cap_text.c -> _service:tar_scm:libcap-2.66.tar.gz/libcap/cap_text.c
Changed
@@ -503,6 +503,8 @@ return "PURE1E"; case CAP_MODE_UNCERTAIN: return "UNCERTAIN"; + case CAP_MODE_HYBRID: + return "HYBRID"; default: return "UNKNOWN"; }
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/include/sys/capability.h -> _service:tar_scm:libcap-2.66.tar.gz/libcap/include/sys/capability.h
Changed
@@ -2,7 +2,7 @@ * <sys/capability.h> * * Copyright (C) 1997 Aleph One - * Copyright (C) 1997,8, 2008,19,20 Andrew G. Morgan <morgan@kernel.org> + * Copyright (C) 1997,8, 2008,19-22 Andrew G. Morgan <morgan@kernel.org> * * defunct POSIX.1e Standard: 25.2 Capabilities <sys/capability.h> */ @@ -15,13 +15,18 @@ #endif /* + * Provide a programmatic way to #ifdef around features. + */ +#define LIBCAP_MAJOR 2 +#define LIBCAP_MINOR 66 + +/* * This file complements the kernel file by providing prototype * information for the user library. */ #include <sys/types.h> #include <stdint.h> -#include <linux/types.h> #ifndef __user #define __user @@ -122,6 +127,7 @@ #define CAP_MODE_NOPRIV ((cap_mode_t) 1) #define CAP_MODE_PURE1E_INIT ((cap_mode_t) 2) #define CAP_MODE_PURE1E ((cap_mode_t) 3) +#define CAP_MODE_HYBRID ((cap_mode_t) 4) /* libcap/cap_alloc.c */ extern cap_t cap_dup(cap_t);
View file
_service:tar_scm:libcap-2.61.tar.gz/libcap/include/uapi/linux/capability.h -> _service:tar_scm:libcap-2.66.tar.gz/libcap/include/uapi/linux/capability.h
Changed
@@ -14,7 +14,9 @@ #ifndef _UAPI_LINUX_CAPABILITY_H #define _UAPI_LINUX_CAPABILITY_H -#include <linux/types.h> +#include <stdint.h> +#define __u32 uint32_t +#define __le32 __u32 /* User-level do most of the mapping between kernel and user capabilities based on the version tag given by the kernel. The @@ -422,5 +424,4 @@ #define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */ #define CAP_TO_MASK(x) (1u << ((x) & 31)) /* mask for indexed __u32 */ - #endif /* _UAPI_LINUX_CAPABILITY_H */
View file
_service:tar_scm:libcap-2.61.tar.gz/pgp.keys.asc -> _service:tar_scm:libcap-2.66.tar.gz/pgp.keys.asc
Changed
@@ -3,7 +3,6 @@ pub 4096R/E2CCF3F4 2011-10-07 Andrew G. Morgan (Work Address) <agm@google.com> uid Andrew G. Morgan <morgan@kernel.org> -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.15 (GNU/Linux) mQINBE6OiBIBEADpdtUxC8Fmhn5UK6UCZdU7mFgZwN8U9cabFUPfUIkMqXULhCD0 hG2/amuiiUoLollPjOopNqk4cc8LcZfszOdBFAYj7MeWzNySVw4KkWrVCEH/bZ0Q @@ -16,97 +15,144 @@ acBfbBtRzVlcDTnGltDNMuRTXzujaY9C3B0L2E+Jfrds8WcM8ASO4mHwJUTMrBwM b5sFSG+/X9Ufg/c2G086HQ7xMERUA5oz66P5ReHCph8WHQN2L5vtZwL7//hZB9hn G0K1210YEDXpFPijpis/54MKUSkWEFOLjUbiSPbwEfb79A00CcHojQQinwARAQAB -tDBBbmRyZXcgRy4gTW9yZ2FuIChXb3JrIEFkZHJlc3MpIDxhZ21AZ29vZ2xlLmNv -bT6JAjgEEwECACIFAk6VD4ICGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ -ECnuhIrizPP0zNoQAMDjx3iovvf0rpAYFvvAoPbzhEXcJ41/T+paxWOJm8SEg7fX -nUHgXeTwW3RJPIp7PguctPogvKQV+7GcU5Dcg13DZO4nMrSsvInsLQkfeDVU/zl2 -MuHFOtBMpDp6iGcUwjS0bYbvl03fPj7ZXIML+I7OSyNeoZ/n2ztI9UiIBHovsHqZ -qYm4d7VOi4nVj1Y/Gak99sw3cLvUwq9f3i8ioNzynqBT7jA+GWFaeVJuGrOCBBBg -uIu0Ekg42NAZ2AR32wQP5eEtlSAq8Il9RZzewa1v74loDNJOl+kW5/jQK6tGj2A9 -vlTqVzHUDmPZ9n6Ds7h3wo2g3gzYX1cuM3spW9UsA8XUDNY2yNFYDC9IsAI09u18 -N7f89isG/yYh5MZpJz2fx7cecHtwSVukTGHDsaoHTXMlfjQmVU5efORZJa6Bx0Tk -aSCwecem3q+3OcdgW8XwPWik/5Wv8B3dJopMH1Mw3pRhirtTd6/88xNyLkJStptB -DZvbqvB2nMmSiqgh0mPeslnwubxJ5/4FbP9zlLN7zp49RZHKDl/8EMSXGCjmG6UT -xW6I3YpKdc4+yEd19/UUtxqQOfbgFvlcbesQ5ILvLOzZidkS7y0v4i9rZBe/HEy3 -eG8z4s5dloBrpSBvKySwqWuuSDn3tMqw4Bz2Be3FgtYA4TnNy7shcFR2BMFotCRB -bmRyZXcgRy4gTW9yZ2FuIDxtb3JnYW5Aa2VybmVsLm9yZz6JAjsEEwECACUCGwMG -CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJOmRGPAhkBAAoJECnuhIrizPP0wK0P -/RMvjmzeXbgoa36cBDvDKReAiC56Au4qGXkNah3984tNPT1hVUKCiwiUmULoNJbE -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 -9ifyrw== -=Ibs8 +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 +=0HgQ -----END PGP PUBLIC KEY BLOCK----- pub 1024D/D41A6DF2 2002-09-23 Andrew G. Morgan <morgan@kernel.org> -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.15 (GNU/Linux) mQGiBD2PVCcRBADmR2dfKJIaGj120v0EjrGbnYic8nKCrDLUHmtiZyIlMeTNqnw/ /Q2m057SIyFC5K5W7XV8LIsOcpEBAdIS5QLClwec/wqVj1FU5TLHNifR9fBq+DaI @@ -140,8 +186,33 @@ Q7ya5ps2AdIKNixiSRPC+6cNB85NBorLXs9yg+JkQlPeUI7/DZb2iz1iZXTnyCZv SvKA7JMYpCOzZ6fWshanZ/91hxQvsYHjYC+zQVTErSYQlBqz8fDLPfyYQiqQFn4c T/i1WsxYMEaZtexvLuQe9LeaDqyY19DyBaJIIiN6EcGZ4sXRa7M6QUD1HKjEWt62 -U4shHkPGIMgQWLcRZDepovlpGVXLmXEf -=oXom +U4shHkPGIMgQWLcRZDepovlpGVXLmXEfiQIcBBABAgAGBQJbnYNFAAoJECnuhIri +zPP0M+4QAI9UJZJL7X7wPkLr3srTZBDbMhJkEQVHQolirrnb3Ojkp1NAQ8vsujqm +tyPM9OPvQC3gylat/tQoMPO9C0/2ztfqMY0ZlxPuiys582wn23/Iqrwn3a3UicU4 +iiCwOS0iBVPeNFr5QuZRZJ58S9af1w53PoPr7ZdS0+bg4hcuO7sq/3VMzqmvkL5O +ptXNd7LEiHzxZDMNrdsgnLwC+umOvzV4/wSY0N5BCwCGYpoTipH9X08KF19uSKGV +xG80eEErYKo1o20OMAoDEUHlc6wIPArqdsXg9tt4qclyx0Y83LFWTyc4f6lesG3c +dZKFZXFSjIFEn5NVgsX/NhzOkUag+rRqpJR6hxz2MunHGNGmmT+O6B/z84PEHxqp +VbMFOIhQJO6MMwJ1sv2RTk4yNeZS7IcW4q/ApKTWRaNoDl3s6csIKGD1myHTGs8e +/yAodElwIHXQL3TroY7kP0dtsDj3Am1+UTbM6O8ro4vjhOVm9Ce+f5nek+es9JiX +4xCWC3ngjnqrPMGKMEWark9mJZRk+QOqBb1H9ZzQJnvbiq6MQJot83hMBxsirlZp +AdI1p1Qzmai7TToQnzyrZqKc1fl9dJrbxxIbPbJNClU19LTcXraPh0GLVpgdkt1q +27PKbyeWnKK7FBKnnFJeOXgO4HSP7XkpMiUSGYZgu/QpJ5SkipW8iFcEExECABcF +Aj2PVCcFCwcKAwQDFQMCAxYCAQIXgAAKCRBCF4Sr1Bpt8u+VAJ9BWCevOxPoNaWm +O81Sz1HIPuII+QCeNaquwRuYR19cjrT6C0HWwmd4v8eJAjMEEAEKAB0WIQSJGKuw +tf7CG2l+zlr71JgaT2BXfAUCYsdB1QAKCRD71JgaT2BXfIiFEACqo6nZhMVjldEF +Pat89Hka/OTSMtG/m4U5Sf5JgZD+DvqbVojk06+Ca8viLQgz0EJHthyLwP7T7L0y +o0ZBTcaJAjTgjtEb9ZeAFuq+lgK9XCAf0+rElVqJ93cAhS6+hucsLjLhhakDr60K +TUwJzdWMnzlizOQjEKm8TdYbukG3xYE/DVCYLHWW39aYGFcOo1N9+UszN4YKSjTa +zJ1+yR9/VncIIH8KWN1EMW8bOAJ5SYjkdA5cQc1oP0aNqMM3mgTtCnCS0EFtoBxl +HRc+tg9oJoCAnmj3sPvZfaFhLoqz8+Xp1QHRFSkxaunXr33L1Y/KxNWWCQBpe7J9 +/FSReMmKiqZaUoNRrkh7RfSGXtSIXpAB/cr5iTdty5TYLYCuGY7ITe0DzGjhn3GJ +87i2uJgvVKETJV0lO6lcugqXN/FGXGlJNtgsWCmRlrkqix+S91ZCI6FNTfY9d78y +fxNpWxElT9rs35CvggIDigQ8YJKVb9JSciZhXFSE1U/2/xW3DTUXrHQDmvB1Ch+I +L5N75Q/n56eQKN5Mb2oUchXluJBg7Bu0oR63/vEDA5ALaK/6OX7u0pbTDhugFjym +ssYorVQQgFarAZU13JmzNX3PWDf2VPTf/rxETHmBiVYnCh9Ois9ZYEpxTrWy0AY7 +RF7BYQDbZJbxCppcYIIDh1S6EYFvrw== +=w+Ya -----END PGP PUBLIC KEY BLOCK----- The following is my DSA key 'D41A6DF2' signed with my old '2A398175'
View file
_service:tar_scm:libcap-2.61.tar.gz/progs/capsh.c -> _service:tar_scm:libcap-2.66.tar.gz/progs/capsh.c
Changed
@@ -509,7 +509,7 @@ { pid_t child = 0; unsigned i; - int strict = 0, quiet_start = 0; + int strict = 0, quiet_start = 0, dont_set_env = 0; const char *shell = SHELL; for (i=1; i<argc; ++i) { @@ -558,6 +558,8 @@ perror("failed to reset ambient set"); exit(1); } + } else if (!strcmp("--noenv", argvi)) { + dont_set_env = 1; } else if (!strncmp("--inh=", argvi, 6)) { cap_t all, raised_for_setpcap; char *text; @@ -912,6 +914,20 @@ pwd->pw_uid, user, strerror(errno)); exit(1); } + if (!dont_set_env) { + /* + * not setting this confuses bash at start up, but use + * --noenv to preserve the HOME etc values instead. + */ + if (setenv("HOME", pwd->pw_dir, 1) != 0) { + perror("unable to set HOME"); + exit(1); + } + if (setenv("USER", user, 1) != 0) { + perror("unable to set USER"); + exit(1); + } + } } else if (!strncmp("--decode=", argvi, 9)) { unsigned long long value; unsigned cap; @@ -1170,6 +1186,7 @@ " --modes list libcap named modes\n" " --no-new-privs set sticky process privilege limiter\n" " --noamb reset (drop) all ambient capabilities\n" + " --noenv no fixup of env vars (for --user)\n" " --print display capability relevant state\n" " --quiet if first argument skip max cap check\n" " --secbits=<n> write a new value for securebits\n"
View file
_service:tar_scm:libcap-2.61.tar.gz/progs/getpcaps.c -> _service:tar_scm:libcap-2.66.tar.gz/progs/getpcaps.c
Changed
@@ -1,5 +1,5 @@ /* - * Copyright (c) 1997,2008 Andrew G. Morgan <morgan@kernel.org> + * Copyright (c) 1997-8,2007-8,19,21-22 Andrew G. Morgan <morgan@kernel.org> * * This displays the capabilities of given target process(es). */ @@ -14,7 +14,7 @@ static void usage(int code) { fprintf(stderr, -"usage: getcaps <pid> <pid> ...\n\n" +"usage: getcaps opts <pid> <pid> ...\n\n" " This program displays the capabilities on the queried process(es).\n" " The capabilities are displayed in the cap_from_text(3) format.\n" "\n" @@ -38,31 +38,48 @@ usage(1); } - for ( ++argv; --argc > 0; ++argv ) { + for (++argv; --argc > 0; ++argv) { + long lpid; int pid; + char *endarg; cap_t cap_d; + const char *arg = *argv; - if (!strcmp(argv0, "--help") || !strcmp(argv0, "--usage") || - !strcmp(argv0, "-h")) { + if (!strcmp(arg, "--help") || !strcmp(arg, "--usage") || + !strcmp(arg, "-h")) { usage(0); - } else if (!strcmp(argv0, "--license")) { + } else if (!strcmp(arg, "--license")) { printf("%s see LICENSE file for details.\n" - "Copyright (c) 1997-8,2007,19,21" + "Copyright (c) 1997-8,2007-8,19,21-22" " Andrew G. Morgan <morgan@kernel.org>\n", - argv0); + arg); exit(0); - } else if (!strcmp(argv0, "--verbose")) { + } else if (!strcmp(arg, "--verbose")) { verbose = 1; continue; - } else if (!strcmp(argv0, "--ugly") || !strcmp(argv0, "--legacy")) { + } else if (!strcmp(arg, "--ugly") || !strcmp(arg, "--legacy")) { verbose = 2; continue; - } else if (!strcmp(argv0, "--iab")) { + } else if (!strcmp(arg, "--iab")) { iab = 1; continue; } - pid = atoi(argv0); + errno = 0; + lpid = strtol(arg, &endarg, 10); + if (errno == 0) { + if (*endarg != '\0') { + errno = EINVAL; + } else if (lpid < 0 || lpid != (pid_t) lpid) { + errno = EOVERFLOW; + } + } + if (errno != 0) { + fprintf(stderr, "Cannot parse pid %s: (%s)\n", arg, strerror(errno)); + retval = 1; + continue; + } + pid = lpid; cap_d = cap_get_pid(pid); if (cap_d == NULL) { @@ -70,43 +87,44 @@ " (%s)\n", pid, strerror(errno)); retval = 1; continue; - } else { - char *result = cap_to_text(cap_d, NULL); - if (iab) { - printf("%s:", *argv); - if (verbose || strcmp("=", result) != 0) { - printf(" \"%s\"", result); - } - cap_iab_t iab_val = cap_iab_get_pid(pid); - if (iab_val == NULL) { - fprintf(stderr, " no IAB value for %d\n", pid); + } + + char *result = cap_to_text(cap_d, NULL); + if (iab) { + printf("%s:", arg); + if (verbose || strcmp("=", result) != 0) { + printf(" \"%s\"", result); + } + cap_iab_t iab_val = cap_iab_get_pid(pid); + if (iab_val == NULL) { + fprintf(stderr, " no IAB value for %d\n", pid); + exit(1); + } + int cf = cap_iab_compare(noiab, iab_val); + if (verbose || + CAP_IAB_DIFFERS(cf, CAP_IAB_AMB) || + CAP_IAB_DIFFERS(cf, CAP_IAB_BOUND)) { + char *iab_text = cap_iab_to_text(iab_val); + if (iab_text == NULL) { + perror(" no text for IAB"); exit(1); } - int cf = cap_iab_compare(noiab, iab_val); - if (verbose || - CAP_IAB_DIFFERS(cf, CAP_IAB_AMB) || - CAP_IAB_DIFFERS(cf, CAP_IAB_BOUND)) { - char *iab_text = cap_iab_to_text(iab_val); - if (iab_text == NULL) { - perror(" no text for IAB"); - exit(1); - } - printf(" %s", iab_text); - cap_free(iab_text); - } - cap_free(iab_val); - printf("\n"); - } else if (verbose == 1) { - printf("Capabilities for '%s': %s\n", *argv, result); - } else if (verbose == 2) { - fprintf(stderr, "Capabilities for `%s': %s\n", *argv, result); - } else { - printf("%s: %s\n", *argv, result); + printf(" %s", iab_text); + cap_free(iab_text); } - cap_free(result); - result = NULL; - cap_free(cap_d); + cap_free(iab_val); + printf("\n"); + } else if (verbose == 1) { + printf("Capabilities for '%s': %s\n", arg, result); + } else if (verbose == 2) { + fprintf(stderr, "Capabilities for `%s': %s\n", arg, result); + } else { + printf("%s: %s\n", arg, result); } + + cap_free(result); + result = NULL; + cap_free(cap_d); } return retval;
View file
_service:tar_scm:libcap-2.61.tar.gz/progs/setcap.c -> _service:tar_scm:libcap-2.66.tar.gz/progs/setcap.c
Changed
@@ -176,7 +176,7 @@ { char *result = cap_to_text(cap_d, NULL); fprintf(stderr, "caps set to: %s\n", result); - cap_free(result) + cap_free(result); } #endif }
View file
_service:tar_scm:libcap-2.61.tar.gz/psx/psx.c -> _service:tar_scm:libcap-2.66.tar.gz/psx/psx.c
Changed
@@ -29,6 +29,26 @@ #include "psx_syscall.h" +#ifdef _PSX_DEBUG_MEMORY + +static void *_psx_calloc(const char *file, const int line, + size_t nmemb, size_t size) { + void *ptr = calloc(nmemb, size); + fprintf(stderr, "psx:%d:%s:%d: calloc(%ld, %ld) -> %p\n", gettid(), + file, line, (long int)nmemb, (long int)size, ptr); + return ptr; +} + +static void _psx_free(const char *file, const int line, void *ptr) { + fprintf(stderr, "psx:%d:%s:%d: free(%p)\n", gettid(), file, line, ptr); + return free(ptr); +} + +#define calloc(a, b) _psx_calloc(__FILE__, __LINE__, a, b) +#define free(a) _psx_free(__FILE__, __LINE__, a) + +#endif /* def _PSX_DEBUG_MEMORY */ + /* * psx_load_syscalls() can be weakly defined in dependent libraries to * provide a mechanism for a library to optionally leverage this psx @@ -56,6 +76,8 @@ pthread_mutex_t mu; int pending; int gone; + long int retval; + pid_t tid; } registered_thread_t; static pthread_once_t psx_tracker_initialized = PTHREAD_ONCE_INIT; @@ -81,6 +103,7 @@ psx_tracker_state_t state; int initialized; int psx_sig; + psx_sensitivity_t sensitivity; struct { long syscall_nr; @@ -136,19 +159,20 @@ return; } + long int retval; if (!psx_tracker.cmd.six) { - (void) syscall(psx_tracker.cmd.syscall_nr, - psx_tracker.cmd.arg1, - psx_tracker.cmd.arg2, - psx_tracker.cmd.arg3); + retval = syscall(psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3); } else { - (void) syscall(psx_tracker.cmd.syscall_nr, - psx_tracker.cmd.arg1, - psx_tracker.cmd.arg2, - psx_tracker.cmd.arg3, - psx_tracker.cmd.arg4, - psx_tracker.cmd.arg5, - psx_tracker.cmd.arg6); + retval = syscall(psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3, + psx_tracker.cmd.arg4, + psx_tracker.cmd.arg5, + psx_tracker.cmd.arg6); } /* @@ -160,6 +184,8 @@ if (ref) { pthread_mutex_lock(&ref->mu); ref->pending = 0; + ref->retval = retval; + ref->tid = syscall(SYS_gettid); pthread_mutex_unlock(&ref->mu); } /* * else thread must be dying and its psx_action_key has already @@ -171,6 +197,7 @@ * Some forward declarations for the initialization * psx_syscall_start() routine. */ +static void _psx_cleanup(void); static void _psx_prepare_fork(void); static void _psx_fork_completed(void); static void _psx_forked_child(void); @@ -234,6 +261,7 @@ psx_confirm_sigaction(); psx_do_registration(); /* register the main thread. */ + atexit(_psx_cleanup); psx_tracker.initialized = 1; } @@ -259,7 +287,9 @@ } /* - * under lock perform a state transition. + * under lock perform a state transition. Changing state is generally + * done via this function. However, there is a single exception in + * _psx_cleanup(). */ static void psx_new_state(psx_tracker_state_t was, psx_tracker_state_t is) { @@ -323,7 +353,7 @@ * * We do this because the glibc man page for fork() suggests that * only a subset of things will work post fork(). Specifically, - * only a "async-signal-safe functions (see signal- safety(7)) + * only a "async-signal-safe functions (see signal-safety(7)) * until such time as it calls execve(2)" can be relied upon. That * man page suggests that you can't expect mutexes to work: "not * async-signal-safe because it uses pthread_mutex_lock(3) @@ -414,7 +444,7 @@ pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL); /* - * Allow the rest of the psx system carry on as per normal. + * Allow the rest of the psx system to carry on as per normal. */ psx_new_state(_PSX_EXITING, _PSX_IDLE); } @@ -607,6 +637,7 @@ } psx_unlock(); + int mismatch = 0; for (;;) { int waiting = 0; psx_lock(); @@ -619,8 +650,12 @@ pthread_mutex_lock(&ref->mu); int pending = ref->pending; int gone = ref->gone; - if (pending && !gone) { - gone = (pthread_kill(ref->thread, 0) != 0); + if (!gone) { + if (pending) { + gone = (pthread_kill(ref->thread, 0) != 0); + } else { + mismatch |= (ref->retval != ret); + } } pthread_mutex_unlock(&ref->mu); if (!gone) { @@ -639,10 +674,92 @@ sched_yield(); } - errno = restore_errno; psx_tracker.cmd.active = 0; + if (mismatch) { + psx_lock(); + switch (psx_tracker.sensitivity) { + case PSX_IGNORE: + break; + default: + fprintf(stderr, "psx_syscall result differs.\n"); + if (psx_tracker.cmd.six) { + fprintf(stderr, "trap:%ld a123456=%ld,%ld,%ld,%ld,%ld,%ld\n", + psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3, + psx_tracker.cmd.arg4, + psx_tracker.cmd.arg5, + psx_tracker.cmd.arg6); + } else { + fprintf(stderr, "trap:%ld a123=%ld,%ld,%ld\n", + psx_tracker.cmd.syscall_nr, + psx_tracker.cmd.arg1, + psx_tracker.cmd.arg2, + psx_tracker.cmd.arg3); + } + fprintf(stderr, "results:"); + for (ref = psx_tracker.root; ref; ref = next) { + next = ref->next; + if (ref->thread == self) { + continue; + } + if (ret != ref->retval) { + fprintf(stderr, " %d={%ld}", ref->tid, ref->retval); + } + } + fprintf(stderr, " wanted={%ld}\n", ret); + if (psx_tracker.sensitivity == PSX_WARNING) { + break; + } + pthread_kill(self, SIGSYS); + } + psx_unlock(); + } + errno = restore_errno; psx_new_state(_PSX_SYSCALL, _PSX_IDLE); defer: return ret; } + +/* + * _psx_cleanup its called when the program exits. It is used to free + * any memory used by the thread tracker. + */ +static void _psx_cleanup(void) { + registered_thread_t *ref, *next; + + /* + * We enter the exiting state. Unlike exiting a single thread we + * never leave this state since this cleanup is only done at + * program exit. + */ + psx_lock(); + while (psx_tracker.state != _PSX_IDLE && psx_tracker.state != _PSX_INFORK) { + pthread_cond_wait(&psx_tracker.cond, &psx_tracker.state_mu); + } + psx_tracker.state = _PSX_EXITING; + psx_unlock(); + + for (ref = psx_tracker.root; ref; ref = next) { + next = ref->next; + psx_do_unregister(ref); + } +} + +/* + * Change the PSX sensitivity level. If the threads appear to have + * diverged in behavior, this can cause the library to notify the + * user. + */ +int psx_set_sensitivity(psx_sensitivity_t level) { + if (level < PSX_IGNORE || level > PSX_ERROR) { + errno = EINVAL; + return -1; + } + psx_lock(); + psx_tracker.sensitivity = level; + psx_unlock(); + return 0; +}
View file
_service:tar_scm:libcap-2.61.tar.gz/psx/psx_cgo.go -> _service:tar_scm:libcap-2.66.tar.gz/psx/psx_cgo.go
Changed
@@ -4,6 +4,7 @@ import ( "runtime" + "sync" "syscall" ) @@ -32,6 +33,15 @@ return int(C.__errno_too(C.long(v))) } +var makeFatal sync.Once + +// forceFatal configures the psx_syscall mechanism to PSX_ERROR. +func forceFatal() { + makeFatal.Do(func() { + C.psx_set_sensitivity(C.PSX_ERROR) + }) +} + //go:uintptrescapes // Syscall3 performs a 3 argument syscall. Syscall3 differs from @@ -45,6 +55,7 @@ // If CGO_ENABLED=0 it redirects to the go1.16+ // syscall.AllThreadsSyscall() function. func Syscall3(syscallnr, arg1, arg2, arg3 uintptr) (uintptr, uintptr, syscall.Errno) { + forceFatal() // We lock to the OSThread here because we may need errno to // be the one for this thread. runtime.LockOSThread() @@ -65,6 +76,7 @@ // arguments, its behavior is identical to that of Syscall3() - see // above for the full documentation. func Syscall6(syscallnr, arg1, arg2, arg3, arg4, arg5, arg6 uintptr) (uintptr, uintptr, syscall.Errno) { + forceFatal() // We lock to the OSThread here because we may need errno to // be the one for this thread. runtime.LockOSThread()
View file
_service:tar_scm:libcap-2.61.tar.gz/psx/psx_syscall.h -> _service:tar_scm:libcap-2.66.tar.gz/psx/psx_syscall.h
Changed
@@ -67,6 +67,27 @@ long int, long int, long int, long int, long int, long int)); +/* + * psx_sensitivity_t holds the level of paranoia for non-POSIX syscall + * behavior. The default is PSX_IGNORE: which is best effort - no + * enforcement; PSX_WARNING will dump to stderr a warning when a + * syscall's results differ; PSX_ERROR will dump info as per + * PSX_WARNING and generate a SIGSYS. The current mode can be set with + * psx_set_sensitivity(). + */ +typedef enum { + PSX_IGNORE = 0, + PSX_WARNING = 1, + PSX_ERROR = 2, +} psx_sensitivity_t; + +/* + * psx_set_sensitivity sets the current sensitivity of the PSX + * mechanism. The function returns 0 on success and -1 if the + * requested level is invalid. + */ +int psx_set_sensitivity(psx_sensitivity_t level); + #ifdef __cplusplus } #endif
View file
_service:tar_scm:libcap-2.61.tar.gz/tests/libcap_launch_test.c -> _service:tar_scm:libcap-2.66.tar.gz/tests/libcap_launch_test.c
Changed
@@ -1,3 +1,4 @@ +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -119,6 +120,11 @@ }, }; + if (errno != 0) { + perror("unexpected initial value for errno"); + exit(1); + } + cap_t orig = cap_get_proc(); if (orig == NULL) { perror("failed to get process capabilities");
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2