Projects
Factory:RISC-V:Base
libcap
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
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 {
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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
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(); + }
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