Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libcap for openSUSE:Factory checked in at 2022-10-03 13:44:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libcap (Old) and /work/SRC/openSUSE:Factory/.libcap.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libcap" Mon Oct 3 13:44:42 2022 rev:55 rq:1007104 version:2.66 Changes: -------- --- /work/SRC/openSUSE:Factory/libcap/libcap.changes 2022-07-31 23:00:08.639552286 +0200 +++ /work/SRC/openSUSE:Factory/.libcap.new.2275/libcap.changes 2022-10-03 13:44:58.369377254 +0200 @@ -1,0 +2,19 @@ +Thu Sep 29 19:49:37 UTC 2022 - Dirk M??ller <dmuel...@suse.com> + +- update to 2.66: + * Fix documentation typos in cap_from_text.3 + * Some getpcaps code clean up and a fix for PID argument parsing from Jakub + Wilk. + * Slightly more robust Makefiles to address an error with make -j48 test observed + * Include a simple Go program, captrace, to trace kernel capability validation + checks + * This program can be used to figure out what capabilities a program needs to + operate. + * captrace (a wrapper for bpftrace) uses BPF kprobes to monitor the kernel for + capability checks and whether or not they succeed for the system, a specific + PID or a program's direct execution. + * Trim down the default file capabilities for contrib/sucap/su to those actually + needed and set USER and HOME environment variables so bash doesn't complain + about a sourcing error. + +------------------------------------------------------------------- Old: ---- libcap-2.65.tar.sign libcap-2.65.tar.xz New: ---- libcap-2.66.tar.sign libcap-2.66.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libcap.spec ++++++ --- /var/tmp/diff_new_pack.vfI2gt/_old 2022-10-03 13:44:59.429379586 +0200 +++ /var/tmp/diff_new_pack.vfI2gt/_new 2022-10-03 13:44:59.433379595 +0200 @@ -17,7 +17,7 @@ Name: libcap -Version: 2.65 +Version: 2.66 Release: 0 Summary: Library for Capabilities (linux-privs) Support License: BSD-3-Clause OR GPL-2.0-only ++++++ libcap-2.65.tar.xz -> libcap-2.66.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/Make.Rules new/libcap-2.66/Make.Rules --- old/libcap-2.65/Make.Rules 2022-07-18 00:28:28.000000000 +0200 +++ new/libcap-2.66/Make.Rules 2022-09-24 22:41:21.000000000 +0200 @@ -1,7 +1,7 @@ # Common version number defines for libcap LIBTITLE=libcap VERSION=2 -MINOR=65 +MINOR=66 # ## Optional prefixes: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/cap/go.mod new/libcap-2.66/cap/go.mod --- old/libcap-2.65/cap/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/cap/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -2,4 +2,4 @@ go 1.11 -require kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 +require kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/contrib/seccomp/go.mod new/libcap-2.66/contrib/seccomp/go.mod --- old/libcap-2.65/contrib/seccomp/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/contrib/seccomp/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -2,4 +2,4 @@ go 1.14 -require kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 +require kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/contrib/sucap/Makefile new/libcap-2.66/contrib/sucap/Makefile --- old/libcap-2.65/contrib/sucap/Makefile 2021-11-21 06:47:51.000000000 +0100 +++ new/libcap-2.66/contrib/sucap/Makefile 2022-08-28 23:14:48.000000000 +0200 @@ -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 *~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/contrib/sucap/su.c new/libcap-2.66/contrib/sucap/su.c --- old/libcap-2.65/contrib/sucap/su.c 2021-09-18 05:56:21.000000000 +0200 +++ new/libcap-2.66/contrib/sucap/su.c 2022-08-28 23:14:48.000000000 +0200 @@ -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 */ } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/doc/cap_from_text.3 new/libcap-2.66/doc/cap_from_text.3 --- old/libcap-2.65/doc/cap_from_text.3 2021-03-07 04:55:56.000000000 +0100 +++ new/libcap-2.66/doc/cap_from_text.3 2022-09-24 22:41:21.000000000 +0200 @@ -1,7 +1,7 @@ .\" .\" written by Andrew Main <zef...@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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/go/.gitignore new/libcap-2.66/go/.gitignore --- old/libcap-2.65/go/.gitignore 2022-01-24 07:02:32.000000000 +0100 +++ new/libcap-2.66/go/.gitignore 2022-09-24 22:41:21.000000000 +0200 @@ -16,6 +16,7 @@ setid gowns captree +captrace ok vendor go.sum diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/go/Makefile new/libcap-2.66/go/Makefile --- old/libcap-2.65/go/Makefile 2022-05-21 23:42:00.000000000 +0200 +++ new/libcap-2.66/go/Makefile 2022-09-18 18:53:14.000000000 +0200 @@ -16,7 +16,7 @@ DEPS=../libcap/libcap.a ../libcap/libpsx.a 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 @@ -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 $< @@ -180,7 +185,7 @@ 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 b215283 b215283-cgo psx-signals psx-signals-cgo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/go/go.mod new/libcap-2.66/go/go.mod --- old/libcap-2.65/go/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/go/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -3,6 +3,6 @@ go 1.11 require ( - kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 - kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 + kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/captrace/captrace.go new/libcap-2.66/goapps/captrace/captrace.go --- old/libcap-2.65/goapps/captrace/captrace.go 1970-01-01 01:00:00.000000000 +0100 +++ new/libcap-2.66/goapps/captrace/captrace.go 2022-09-19 01:30:03.000000000 +0200 @@ -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(map[int]int) + +// cache tracks in-flight cap_capable invocations. +var cache = make(map[int]*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 := tids[th.PPID]; !ok { + if *debug { + log.Printf("dropped %d %d %v event", th.PPID, tid, *th) + } + return + } + tids[tid] = th.PPID + tids[th.PPID] = th.PPID + } + + if add { + cache[tid] = th + } else { + if b, ok := cache[tid]; 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 fields[0] { + case "CB": + if len(fields) < 6 { + continue + } + pid, err := strconv.Atoi(fields[1]) + if err != nil { + continue + } + th := &thread{ + PPID: pid, + } + tid, err := strconv.Atoi(fields[2]) + if err != nil { + continue + } + c, err := strconv.Atoi(fields[3]) + if err != nil { + continue + } + th.Value = cap.Value(c) + aud, err := strconv.Atoi(fields[4]) + if err != nil { + continue + } + th.Datum = aud + th.Token = strings.Join(fields[5:], " ") + event(true, tid, th) + case "CE": + if len(fields) < 4 { + continue + } + pid, err := strconv.Atoi(fields[1]) + if err != nil { + continue + } + th := &thread{ + PPID: pid, + } + tid, err := strconv.Atoi(fields[2]) + if err != nil { + continue + } + aud, err := strconv.Atoi(fields[3]) + 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.Args[0]) + 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(args[0], args[1:]...) + 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) + } + tids[cmd.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() +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/captrace/go.mod new/libcap-2.66/goapps/captrace/go.mod --- old/libcap-2.65/goapps/captrace/go.mod 1970-01-01 01:00:00.000000000 +0100 +++ new/libcap-2.66/goapps/captrace/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -0,0 +1,5 @@ +module captrace + +go 1.16 + +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/captree/go.mod new/libcap-2.66/goapps/captree/go.mod --- old/libcap-2.65/goapps/captree/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/goapps/captree/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -2,4 +2,4 @@ go 1.16 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/gowns/go.mod new/libcap-2.66/goapps/gowns/go.mod --- old/libcap-2.65/goapps/gowns/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/goapps/gowns/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -2,4 +2,4 @@ go 1.15 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/setid/go.mod new/libcap-2.66/goapps/setid/go.mod --- old/libcap-2.65/goapps/setid/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/goapps/setid/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -3,6 +3,6 @@ go 1.11 require ( - kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 - kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 + kernel.org/pub/linux/libs/security/libcap/psx v1.2.66 ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/goapps/web/go.mod new/libcap-2.66/goapps/web/go.mod --- old/libcap-2.65/goapps/web/go.mod 2022-07-18 00:31:01.000000000 +0200 +++ new/libcap-2.66/goapps/web/go.mod 2022-09-24 22:41:21.000000000 +0200 @@ -2,4 +2,4 @@ go 1.11 -require kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 +require kernel.org/pub/linux/libs/security/libcap/cap v1.2.66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/libcap/Makefile new/libcap-2.66/libcap/Makefile --- old/libcap-2.65/libcap/Makefile 2021-12-12 00:00:00.000000000 +0100 +++ new/libcap-2.66/libcap/Makefile 2022-08-28 23:14:48.000000000 +0200 @@ -108,6 +108,9 @@ ifeq ($(SHARED),yes) +empty: empty.c + $(CC) -o $@ $< + loader.txt: empty $(OBJCOPY) --dump-section .interp=$@ $< /dev/null diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/libcap/include/sys/capability.h new/libcap-2.66/libcap/include/sys/capability.h --- old/libcap-2.65/libcap/include/sys/capability.h 2022-07-18 00:31:52.000000000 +0200 +++ new/libcap-2.66/libcap/include/sys/capability.h 2022-09-24 22:41:21.000000000 +0200 @@ -18,7 +18,7 @@ * Provide a programmatic way to #ifdef around features. */ #define LIBCAP_MAJOR 2 -#define LIBCAP_MINOR 65 +#define LIBCAP_MINOR 66 /* * This file complements the kernel file by providing prototype diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libcap-2.65/progs/getpcaps.c new/libcap-2.66/progs/getpcaps.c --- old/libcap-2.65/progs/getpcaps.c 2021-09-18 05:56:21.000000000 +0200 +++ new/libcap-2.66/progs/getpcaps.c 2022-09-04 23:36:18.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997,2008 Andrew G. Morgan <mor...@kernel.org> + * Copyright (c) 1997-8,2007-8,19,21-22 Andrew G. Morgan <mor...@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(argv[0], "--help") || !strcmp(argv[0], "--usage") || - !strcmp(argv[0], "-h")) { + if (!strcmp(arg, "--help") || !strcmp(arg, "--usage") || + !strcmp(arg, "-h")) { usage(0); - } else if (!strcmp(argv[0], "--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 <mor...@kernel.org>]\n", - argv[0]); + arg); exit(0); - } else if (!strcmp(argv[0], "--verbose")) { + } else if (!strcmp(arg, "--verbose")) { verbose = 1; continue; - } else if (!strcmp(argv[0], "--ugly") || !strcmp(argv[0], "--legacy")) { + } else if (!strcmp(arg, "--ugly") || !strcmp(arg, "--legacy")) { verbose = 2; continue; - } else if (!strcmp(argv[0], "--iab")) { + } else if (!strcmp(arg, "--iab")) { iab = 1; continue; } - pid = atoi(argv[0]); + 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;