Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libcap for openSUSE:Factory checked 
in at 2021-02-07 15:13:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libcap (Old)
 and      /work/SRC/openSUSE:Factory/.libcap.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libcap"

Sun Feb  7 15:13:35 2021 rev:42 rq:867074 version:2.47

Changes:
--------
--- /work/SRC/openSUSE:Factory/libcap/libcap.changes    2021-01-22 
21:48:51.525554206 +0100
+++ /work/SRC/openSUSE:Factory/.libcap.new.28504/libcap.changes 2021-02-07 
15:13:38.233361949 +0100
@@ -1,0 +2,9 @@
+Wed Jan 27 07:53:21 UTC 2021 - Dirk M??ller <dmuel...@suse.com>
+
+- update to 2.47:
+  * Restructured gowns to default to uid base of getuid().
+  * Augment NOPRIV libcap mode with the sticky NO_NEW_PRIVS prctl bit.
+  * Improve the usage and diagnostic message for setcap
+  * Documentation fixes, license declarations, example updates
+
+-------------------------------------------------------------------

Old:
----
  libcap-2.46.tar.xz

New:
----
  libcap-2.47.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libcap.spec ++++++
--- /var/tmp/diff_new_pack.qLqqWP/_old  2021-02-07 15:13:39.037362809 +0100
+++ /var/tmp/diff_new_pack.qLqqWP/_new  2021-02-07 15:13:39.041362813 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           libcap
-Version:        2.46
+Version:        2.47
 Release:        0
 Summary:        Library for Capabilities (linux-privs) Support
 License:        BSD-3-Clause AND GPL-2.0-only

++++++ libcap-2.46.tar.xz -> libcap-2.47.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/Make.Rules new/libcap-2.47/Make.Rules
--- old/libcap-2.46/Make.Rules  2020-12-13 00:54:26.000000000 +0100
+++ new/libcap-2.47/Make.Rules  2021-01-24 03:06:05.000000000 +0100
@@ -1,7 +1,7 @@
 # Common version number defines for libcap
 LIBTITLE=libcap
 VERSION=2
-MINOR=46
+MINOR=47
 
 #
 ## Optional prefixes:
@@ -43,9 +43,9 @@
 PKGCONFIGDIR=$(LIBDIR)/pkgconfig
 GOPKGDIR=$(prefix)/share/gocode/src
 
-# Go modules have their own semantics. I plan to leave this value at 0
-# and keep it there. The Go packages should always remain backwardly
-# compatible, but I may have to up it if Go's syntax changes in a
+# Once go1.16 is released, I plan to set this value to 1 and keep it
+# there. The Go packages should always remain backwardly compatible,
+# but I may have to up it if Go's syntax dramatically changes in a
 # backwards incompatible manner. (Let's hope not.)
 GOMAJOR=0
 
@@ -113,10 +113,6 @@
 CGO_LDFLAGS := -L$(topdir)/libcap
 CGO_LDFLAGS_ALLOW := -Wl,-?-wrap[=,][^-.@][^,]*
 CGO_REQUIRED=$(shell $(topdir)/go/cgo-required.sh)
-ifeq ($(CGO_REQUIRED),0)
-# Hopefully this will not be needed at some point.
-GOBUILDTAG=-tags allthreadssyscall
-endif
 endif
 endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/cap/cap.go new/libcap-2.47/cap/cap.go
--- old/libcap-2.46/cap/cap.go  2020-12-11 06:35:28.000000000 +0100
+++ new/libcap-2.47/cap/cap.go  2021-01-24 03:01:25.000000000 +0100
@@ -42,17 +42,14 @@
 // uniformly over the whole Go (and CGo linked) process runtime.
 //
 // Note, if the Go runtime syscall interface contains the Linux
-// variant syscall.AllThreadsSyscall() API (it is not in go1.15
-// for example, but see https://github.com/golang/go/issues/1435 for
-// current status) then this present package can use that to invoke
-// Capability setting system calls in pure Go binaries. In such an
-// enhanced Go runtime, to force this behavior, use the CGO_ENABLED=0
-// environment variable and, for now, a build tag:
+// variant syscall.AllThreadsSyscall() API (it debuted in go1.16 see
+// https://github.com/golang/go/issues/1435 for its history) then
+// the "psx" package will use that to invoke Capability setting system
+// calls in pure Go binaries. In such an enhanced Go runtime, to force
+// this behavior, use the CGO_ENABLED=0 environment variable.
 //
-//   CGO_ENABLED=0 go build -tags allthreadssyscall ...
 //
-//
-// Copyright (c) 2019,20 Andrew G. Morgan <mor...@kernel.org>
+// Copyright (c) 2019-21 Andrew G. Morgan <mor...@kernel.org>
 //
 // The cap and psx packages are licensed with a (you choose) BSD
 // 3-clause or GPL2. See LICENSE file for details.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/cap/convenience.go 
new/libcap-2.47/cap/convenience.go
--- old/libcap-2.46/cap/convenience.go  2020-08-02 03:31:08.000000000 +0200
+++ new/libcap-2.47/cap/convenience.go  2020-12-29 02:01:07.000000000 +0100
@@ -36,6 +36,7 @@
        prSetKeepCaps   = 8
        prGetSecureBits = 27
        prSetSecureBits = 28
+       prSetNoNewPrivs = 38
 )
 
 // GetSecbits returns the current setting of the process' Secbits.
@@ -163,6 +164,9 @@
        }
        w.ClearFlag(Permitted)
 
+       // For good measure.
+       sc.prctlwcall6(prSetNoNewPrivs, 1, 0, 0, 0, 0)
+
        return nil
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/cap/go.mod new/libcap-2.47/cap/go.mod
--- old/libcap-2.46/cap/go.mod  2020-12-13 00:55:02.000000000 +0100
+++ new/libcap-2.47/cap/go.mod  2021-01-24 03:07:25.000000000 +0100
@@ -2,4 +2,4 @@
 
 go 1.11
 
-require kernel.org/pub/linux/libs/security/libcap/psx v0.2.46
+require kernel.org/pub/linux/libs/security/libcap/psx v0.2.47
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/cap/launch.go 
new/libcap-2.47/cap/launch.go
--- old/libcap-2.46/cap/launch.go       2020-07-16 04:31:24.000000000 +0200
+++ new/libcap-2.47/cap/launch.go       2020-12-24 01:46:18.000000000 +0100
@@ -106,18 +106,18 @@
 var ErrNoLaunch = errors.New("launch not supported")
 
 // ErrAmbiguousChroot indicates that the Launcher is being used in
-// addition to callback supplied Chroot. The former should be used
+// addition to a callback supplied Chroot. The former should be used
 // exclusively for this.
 var ErrAmbiguousChroot = errors.New("use Launcher for chroot")
 
 // ErrAmbiguousIDs indicates that the Launcher is being used in
-// addition to callback supplied Credentials. The former should be
+// addition to a callback supplied Credentials. The former should be
 // used exclusively for this.
 var ErrAmbiguousIDs = errors.New("use Launcher for uids and gids")
 
 // ErrAmbiguousAmbient indicates that the Launcher is being used in
-// addition callback supplied ambient set and the former should be
-// used exclusively in a Launch call.
+// addition to a callback supplied ambient set and the former should
+// be used exclusively in a Launch call.
 var ErrAmbiguousAmbient = errors.New("use Launcher for ambient caps")
 
 // lName is the name we temporarily give to the launcher thread. Note,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/cap/text.go new/libcap-2.47/cap/text.go
--- old/libcap-2.46/cap/text.go 2020-07-25 04:28:01.000000000 +0200
+++ new/libcap-2.47/cap/text.go 2020-12-24 01:46:18.000000000 +0100
@@ -187,7 +187,7 @@
 //
 //    "=p all+ei"  "all=pie"   "=pi all+e"   "=eip"
 //
-//    "cap_chown=p cap_setuid=i"  "cap_chown=ip-p"   "cap_chown=i"
+//    "cap_setuid=p cap_chown=i"  "cap_chown=ip-p"   "cap_chown=i"
 //
 //    "cap_chown=-p"   "all="   "cap_setuid=pie-pie"   "="
 //
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/contrib/seccomp/explore.go 
new/libcap-2.47/contrib/seccomp/explore.go
--- old/libcap-2.46/contrib/seccomp/explore.go  1970-01-01 01:00:00.000000000 
+0100
+++ new/libcap-2.47/contrib/seccomp/explore.go  2021-01-24 03:01:25.000000000 
+0100
@@ -0,0 +1,276 @@
+// Program explore is evolved from the code discussed in more depth
+// here:
+//
+//   https://github.com/golang/go/issues/3405
+//
+// The code here demonstrates that while PR_SET_NO_NEW_PRIVS only
+// applies to the calling thread, since
+// 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=103502a35cfce0710909da874f092cb44823ca03
+// the seccomp filter application forces the setting to be mirrored on
+// all the threads of a process.
+//
+// Based on the command line options, we can manipulate the program to
+// behave in various ways. Example command lines:
+//
+//   sudo ./explore
+//   sudo ./explore --kill=false
+//   sudo ./explore --kill=false --errno=0
+//
+// Supported Go toolchains are after go1.10. Those prior to go1.15
+// require this environment variable to be set to build successfully:
+//
+//   export CGO_LDFLAGS_ALLOW="-Wl,-?-wrap[=,][^-.@][^,]*"
+//
+// Go toolchains go1.16+ can be compiled CGO_ENABLED=0 too,
+// demonstrating native nocgo support for seccomp features.
+package main
+
+import (
+       "flag"
+       "fmt"
+       "log"
+       "runtime"
+       "syscall"
+       "time"
+       "unsafe"
+
+       "kernel.org/pub/linux/libs/security/libcap/psx"
+)
+
+var (
+       withPSX = flag.Bool("psx", false, "use the psx mechanism to invoke 
prctl syscall")
+       delays  = flag.Bool("delays", false, "use this to pause the program at 
various places")
+       kill    = flag.Bool("kill", true, "kill the process if setuid 
attempted")
+       errno   = flag.Int("errno", int(syscall.ENOTSUP), "if kill is false, 
block syscall and return this errno")
+)
+
+const (
+       PR_SET_NO_NEW_PRIVS = 38
+
+       SYS_SECCOMP               = 317        // x86_64 syscall number
+       SECCOMP_SET_MODE_FILTER   = 1          // uses user-supplied filter.
+       SECCOMP_FILTER_FLAG_TSYNC = (1 << 0)   // mirror filtering on all 
threads.
+       SECCOMP_RET_ERRNO         = 0x00050000 // returns an errno
+       SECCOMP_RET_DATA          = 0x0000ffff // mask for RET data payload 
(ex. errno)
+       SECCOMP_RET_KILL_PROCESS  = 0x80000000 // kill the whole process 
immediately
+       SECCOMP_RET_TRAP          = 0x00030000 // disallow and force a SIGSYS
+       SECCOMP_RET_ALLOW         = 0x7fff0000
+
+       BPF_LD  = 0x00
+       BPF_JMP = 0x05
+       BPF_RET = 0x06
+
+       BPF_W = 0x00
+
+       BPF_ABS = 0x20
+       BPF_JEQ = 0x10
+
+       BPF_K = 0x00
+
+       AUDIT_ARCH_X86_64 = 3221225534 // HACK: I don't understand this value
+       ARCH_NR           = AUDIT_ARCH_X86_64
+
+       syscall_nr = 0
+)
+
+// SockFilter is a single filter block.
+type SockFilter struct {
+       // Code is the filter code instruction.
+       Code uint16
+       // Jt is the target for a true result from the code execution.
+       Jt uint8
+       // Jf is the target for a false result from the code execution.
+       Jf uint8
+       // K is a generic multiuse field
+       K uint32
+}
+
+// SockFProg is a
+type SockFProg struct {
+       // Len is the number of contiguous SockFilter blocks that can
+       // be found at *Filter.
+       Len uint16
+       // Filter is the address of the first SockFilter block of a
+       // program sequence.
+       Filter *SockFilter
+}
+
+type SockFilterSlice []SockFilter
+
+func BPF_STMT(code uint16, k uint32) SockFilter {
+       return SockFilter{code, 0, 0, k}
+}
+
+func BPF_JUMP(code uint16, k uint32, jt uint8, jf uint8) SockFilter {
+       return SockFilter{code, jt, jf, k}
+}
+
+func ValidateArchitecture() []SockFilter {
+       return []SockFilter{
+               BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 4), // HACK: I don't understand 
this 4.
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0),
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS),
+       }
+}
+
+func ExamineSyscall() []SockFilter {
+       return []SockFilter{
+               BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr),
+       }
+}
+
+func AllowSyscall(syscallNum uint32) []SockFilter {
+       return []SockFilter{
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1),
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+       }
+}
+
+func DisallowSyscall(syscallNum, errno uint32) []SockFilter {
+       return []SockFilter{
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1),
+               BPF_STMT(BPF_RET+BPF_K, 
SECCOMP_RET_ERRNO|(errno&SECCOMP_RET_DATA)),
+       }
+}
+
+func KillProcess() []SockFilter {
+       return []SockFilter{
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS),
+       }
+}
+
+func NotifyProcessAndDie() []SockFilter {
+       return []SockFilter{
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
+       }
+}
+
+func TrapOnSyscall(syscallNum uint32) []SockFilter {
+       return []SockFilter{
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscallNum, 0, 1),
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
+       }
+}
+
+func AllGood() []SockFilter {
+       return []SockFilter{
+               BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+       }
+}
+
+// prctl executes the prctl - unless the --psx commandline argument is
+// used, this is on a single thread.
+//go:uintptrescapes
+func prctl(option, arg1, arg2, arg3, arg4, arg5 uintptr) error {
+       var e syscall.Errno
+       if *withPSX {
+               _, _, e = psx.Syscall6(syscall.SYS_PRCTL, option, arg1, arg2, 
arg3, arg4, arg5)
+       } else {
+               _, _, e = syscall.RawSyscall6(syscall.SYS_PRCTL, option, arg1, 
arg2, arg3, arg4, arg5)
+       }
+       if e != 0 {
+               return e
+       }
+       if *delays {
+               fmt.Println("prctl'd - check now")
+               time.Sleep(1 * time.Minute)
+       }
+       return nil
+}
+
+// seccomp_set_mode_filter is our wrapper for performing our seccomp system 
call.
+//go:uintptrescapes
+func seccomp_set_mode_filter(prog *SockFProg) error {
+       if _, _, e := syscall.RawSyscall(SYS_SECCOMP, SECCOMP_SET_MODE_FILTER, 
SECCOMP_FILTER_FLAG_TSYNC, uintptr(unsafe.Pointer(prog))); e != 0 {
+               return e
+       }
+       return nil
+}
+
+var empty func()
+
+func lockProcessThread(pick bool) {
+       // Make sure we are
+       pid := uintptr(syscall.Getpid())
+       runtime.LockOSThread()
+       for {
+               tid, _, _ := syscall.RawSyscall(syscall.SYS_GETTID, 0, 0, 0)
+               if (tid == pid) == pick {
+                       fmt.Println("validated TID:", tid, "== PID:", pid, 
"is", pick)
+                       break
+               }
+               runtime.UnlockOSThread()
+               go func() {
+                       time.Sleep(1 * time.Microsecond)
+               }()
+               runtime.Gosched()
+               runtime.LockOSThread()
+       }
+}
+
+// applyPolicy uploads the program sequence.
+func applyPolicy(prog *SockFProg) {
+       // Without PSX we can't guarantee the thread we execute the
+       // seccomp call on will be the same one that we disabled new
+       // privs on. With PSX, the disabling of new privs is mirrored
+       // on all threads.
+       if !*withPSX {
+               lockProcessThread(false)
+               defer runtime.UnlockOSThread()
+       }
+
+       // This is required to load a filter without privilege.
+       if err := prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0); err != nil {
+               log.Fatalf("Prctl(PR_SET_NO_NEW_PRIVS): %v", err)
+       }
+
+       fmt.Println("Applying syscall policy...")
+       if err := seccomp_set_mode_filter(prog); err != nil {
+               log.Fatalf("seccomp_set_mode_filter: %v", err)
+       }
+       fmt.Println("...Policy applied")
+}
+
+func main() {
+       flag.Parse()
+
+       if *delays {
+               fmt.Println("check first", syscall.Getpid())
+               time.Sleep(60 * time.Second)
+       }
+
+       var filter []SockFilter
+       filter = append(filter, ValidateArchitecture()...)
+
+       // Grab the system call number.
+       filter = append(filter, ExamineSyscall()...)
+
+       // List disallowed syscalls.
+       for _, x := range []uint32{
+               syscall.SYS_SETUID,
+       } {
+               if *kill {
+                       filter = append(filter, TrapOnSyscall(x)...)
+               } else {
+                       filter = append(filter, DisallowSyscall(x, 
uint32(*errno))...)
+               }
+       }
+
+       filter = append(filter, AllGood()...)
+
+       prog := &SockFProg{
+               Len:    uint16(len(filter)),
+               Filter: &filter[0],
+       }
+
+       applyPolicy(prog)
+
+       // Ensure we are running on the TID=PID.
+       lockProcessThread(true)
+
+       log.Print("Now it is time to try to run something privileged...")
+       if _, _, e := syscall.RawSyscall(syscall.SYS_SETUID, 1, 0, 0); e != 0 {
+               log.Fatalf("setuid failed with an error: %v", e)
+       }
+       log.Print("Looked like that worked, but it really didn't: uid == ", 
syscall.Getuid(), " != 1")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/contrib/seccomp/go.mod 
new/libcap-2.47/contrib/seccomp/go.mod
--- old/libcap-2.46/contrib/seccomp/go.mod      1970-01-01 01:00:00.000000000 
+0100
+++ new/libcap-2.47/contrib/seccomp/go.mod      2021-01-24 03:08:01.000000000 
+0100
@@ -0,0 +1,5 @@
+module explore
+
+go 1.14
+
+require kernel.org/pub/linux/libs/security/libcap/psx v0.2.47
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/go/Makefile new/libcap-2.47/go/Makefile
--- old/libcap-2.46/go/Makefile 2020-12-12 08:57:35.000000000 +0100
+++ new/libcap-2.47/go/Makefile 2020-12-24 01:46:18.000000000 +0100
@@ -54,7 +54,7 @@
        GO111MODULE=off CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" 
CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" GOPATH=$(GOPATH) $(GO) 
build $<
 
 web: ../goapps/web/web.go $(CAPGOPACKAGE)
-       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ 
$(GOBUILDTAG) $<
+       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ $<
 ifeq ($(RAISE_GO_FILECAP),yes)
        make -C ../progs setcap
        sudo ../progs/setcap cap_setpcap,cap_net_bind_service=p web
@@ -62,16 +62,16 @@
 endif
 
 setid: ../goapps/setid/setid.go $(CAPGOPACKAGE) $(PSXGOPACKAGE)
-       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ 
$(GOBUILDTAG) $<
+       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ $<
 
 gowns: ../goapps/gowns/gowns.go $(CAPGOPACKAGE)
-       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ 
$(GOBUILDTAG) $<
+       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@ $<
 
 ok: ok.go
        GO111MODULE=off CGO_ENABLED=0 GOPATH=$(GOPATH) $(GO) build $<
 
 try-launching: try-launching.go $(CAPGOPACKAGE) ok
-       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build 
$(GOBUILDTAG) $<
+       GO111MODULE=off CGO_ENABLED="$(CGO_REQUIRED)" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build $<
 ifeq ($(CGO_REQUIRED),0)
        GO111MODULE=off CGO_ENABLED="1" 
CGO_LDFLAGS_ALLOW="$(CGO_LDFLAGS_ALLOW)" GOPATH=$(GOPATH) $(GO) build -o $@-cgo 
$<
 endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/go/try-launching.go 
new/libcap-2.47/go/try-launching.go
--- old/libcap-2.46/go/try-launching.go 2020-09-07 23:08:11.000000000 +0200
+++ new/libcap-2.47/go/try-launching.go 2020-12-29 02:01:07.000000000 +0100
@@ -28,6 +28,7 @@
                iab        string
                uid        int
                gid        int
+               mode       cap.Mode
                groups     []int
        }{
                {args: []string{root + "/go/ok"}},
@@ -44,6 +45,11 @@
                        chroot: root + "/go",
                        fail:   syscall.Getuid() != 0,
                },
+               {
+                       args: []string{root + "/progs/tcapsh-static", 
"--inmode=NOPRIV", "--has-no-new-privs"},
+                       mode: cap.ModeNoPriv,
+                       fail: syscall.Getuid() != 0,
+               },
        }
 
        ps := make([]int, len(vs))
@@ -61,6 +67,9 @@
                if v.gid != 0 {
                        e.SetGroups(v.gid, v.groups)
                }
+               if v.mode != 0 {
+                       e.SetMode(v.mode)
+               }
                if v.iab != "" {
                        if iab, err := cap.IABFromText(v.iab); err != nil {
                                log.Fatalf("failed to parse iab=%q: %v", v.iab, 
err)
@@ -68,6 +77,7 @@
                                e.SetIAB(iab)
                        }
                }
+               log.Printf("[%d] trying: %q\n", i, v.args)
                if ps[i], err = e.Launch(nil); err != nil {
                        if v.fail {
                                continue
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/goapps/gowns/go.mod 
new/libcap-2.47/goapps/gowns/go.mod
--- old/libcap-2.46/goapps/gowns/go.mod 2020-12-13 00:55:39.000000000 +0100
+++ new/libcap-2.47/goapps/gowns/go.mod 2021-01-24 03:08:53.000000000 +0100
@@ -2,4 +2,4 @@
 
 go 1.15
 
-require kernel.org/pub/linux/libs/security/libcap/cap v0.2.46
+require kernel.org/pub/linux/libs/security/libcap/cap v0.2.47
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/goapps/gowns/gowns.go 
new/libcap-2.47/goapps/gowns/gowns.go
--- old/libcap-2.46/goapps/gowns/gowns.go       2020-12-12 08:20:40.000000000 
+0100
+++ new/libcap-2.47/goapps/gowns/gowns.go       2021-01-24 03:01:25.000000000 
+0100
@@ -1,5 +1,5 @@
 // Program gowns is a small program to explore and demonstrate using
-// GO to Wrap a child in a NameSpace under Linux.
+// Go to Wrap a child in a NameSpace under Linux.
 package main
 
 import (
@@ -17,17 +17,25 @@
 // nsDetail is how we summarize the type of namespace we want to
 // enter.
 type nsDetail struct {
-       // uid holds the uid for "root" in this namespace.
+       // uid holds the uid for the base user in this namespace (defaults to 
getuid).
        uid int
-       // gid holds the gid for "root" in this namespace.
+
+       // uidMap holds the namespace mapping of uid values.
+       uidMap []syscall.SysProcIDMap
+
+       // gid holds the gid for the base user in this namespace (defaults to 
getgid).
        gid int
+
+       // uidMap holds the namespace mapping of gid values.
+       gidMap []syscall.SysProcIDMap
 }
 
 var (
-       uid  = flag.Int("uid", -1, "uid of the hosting user")
-       gid  = flag.Int("gid", -1, "gid of the hosting user")
-       iab  = flag.String("iab", "", "IAB string for inheritable capabilities")
-       mode = flag.String("mode", "", "force a libcap mode (capsh --modes for 
list)")
+       baseID = flag.Int("base", -1, "base id for uids and gids (-1 = 
invoker's uid)")
+       uid    = flag.Int("uid", -1, "uid of the hosting user")
+       gid    = flag.Int("gid", -1, "gid of the hosting user")
+       iab    = flag.String("iab", "", "IAB string for inheritable 
capabilities")
+       mode   = flag.String("mode", "", "force a libcap mode (capsh --modes 
for list)")
 
        ns   = flag.Bool("ns", false, "enable user namespace features")
        uids = flag.String("uids", "", "comma separated UID ranges to map 
contiguously (req. CAP_SETUID)")
@@ -81,70 +89,73 @@
 // nsSetup is the callback used to enter the namespace for the user
 // via callback in the cap.Launcher mechanism.
 func nsSetup(pa *syscall.ProcAttr, data interface{}) error {
-       have := cap.GetProc()
        nsD, ok := data.(nsDetail)
        if !ok {
                return errUnableToSetup
        }
 
-       sys := pa.Sys
-       if sys == nil {
-               sys = &syscall.SysProcAttr{}
-               pa.Sys = sys
+       if pa.Sys == nil {
+               pa.Sys = &syscall.SysProcAttr{}
        }
-       sys.Cloneflags |= syscall.CLONE_NEWUSER
-       sys.UidMappings = append(pa.Sys.UidMappings,
-               syscall.SysProcIDMap{
-                       ContainerID: 0,
-                       HostID:      nsD.uid,
-                       Size:        1,
-               })
-       if able, err := have.GetFlag(cap.Effective, cap.SETUID); err != nil {
-               log.Fatalf("cap package SETUID error: %v", err)
-       } else if able {
-               base := 1
-               for _, next := range ranges(*uids) {
-                       sys.UidMappings = append(pa.Sys.UidMappings,
-                               syscall.SysProcIDMap{
-                                       ContainerID: base,
-                                       HostID:      next.base,
-                                       Size:        next.count,
-                               })
-                       base += next.count
-               }
+       pa.Sys.Cloneflags |= syscall.CLONE_NEWUSER
+       pa.Sys.UidMappings = nsD.uidMap
+       pa.Sys.GidMappings = nsD.gidMap
+       return nil
+}
+
+func parseRanges(detail *nsDetail, ids string, id int) []syscall.SysProcIDMap {
+       base := *baseID
+       if base < 0 {
+               base = detail.uid
        }
 
-       sys.GidMappings = append(pa.Sys.GidMappings,
+       list := []syscall.SysProcIDMap{
                syscall.SysProcIDMap{
-                       ContainerID: 0,
-                       HostID:      nsD.gid,
+                       ContainerID: base,
+                       HostID:      id,
                        Size:        1,
-               })
-       if able, err := have.GetFlag(cap.Effective, cap.SETGID); err != nil {
-               log.Fatalf("cap package SETGID error: %v", err)
-       } else if able {
-               base := 1
-               for _, next := range ranges(*gids) {
-                       sys.GidMappings = append(pa.Sys.GidMappings,
-                               syscall.SysProcIDMap{
-                                       ContainerID: base,
-                                       HostID:      next.base,
-                                       Size:        next.count,
-                               })
-                       base += next.count
-               }
+               },
        }
-       return nil
+
+       base++
+       for _, next := range ranges(ids) {
+               fmt.Println("next:", next)
+               list = append(list,
+                       syscall.SysProcIDMap{
+                               ContainerID: base,
+                               HostID:      next.base,
+                               Size:        next.count,
+                       })
+               base += next.count
+       }
+       return list
 }
 
 func main() {
        flag.Parse()
 
        detail := nsDetail{
-               uid: syscall.Getuid(),
                gid: syscall.Getgid(),
        }
 
+       thisUID := syscall.Getuid()
+       switch *uid {
+       case -1:
+               detail.uid = thisUID
+       default:
+               detail.uid = *uid
+       }
+       detail.uidMap = parseRanges(&detail, *uids, detail.uid)
+
+       thisGID := syscall.Getgid()
+       switch *gid {
+       case -1:
+               detail.gid = thisGID
+       default:
+               detail.gid = *gid
+       }
+       detail.gidMap = parseRanges(&detail, *gids, detail.gid)
+
        unparsed := flag.Args()
 
        arg0 := *shell
@@ -164,13 +175,11 @@
                w.Callback(nsSetup)
        }
 
-       have := cap.GetProc()
-       if *uid >= 0 {
-               detail.uid = *uid
-               cap.SetUID(detail.uid)
+       if thisUID != detail.uid {
+               w.SetUID(detail.uid)
        }
-       if *gid >= 0 {
-               detail.gid = *gid
+
+       if thisGID != detail.gid {
                w.SetGroups(detail.gid, nil)
        }
 
@@ -195,6 +204,7 @@
 
        // The launcher can enable more functionality if involked with
        // effective capabilities.
+       have := cap.GetProc()
        for _, c := range []cap.Value{cap.SETUID, cap.SETGID} {
                if canDo, err := have.GetFlag(cap.Permitted, c); err != nil {
                        log.Fatalf("failed to explore process capabilities, %q 
for %q", have, c)
@@ -205,12 +215,12 @@
                }
        }
        if err := have.SetProc(); err != nil {
-               log.Fatalf("privilege assertion failed: %v", err)
+               log.Fatalf("privilege assertion %q failed: %v", have, err)
        }
 
        if *debug {
                if *ns {
-                       fmt.Println("launching:", detail.uid, "-> root ...")
+                       fmt.Println("launching namespace")
                } else {
                        fmt.Println("launching without namespace")
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/goapps/setid/go.mod 
new/libcap-2.47/goapps/setid/go.mod
--- old/libcap-2.46/goapps/setid/go.mod 2020-12-13 00:55:58.000000000 +0100
+++ new/libcap-2.47/goapps/setid/go.mod 2021-01-24 03:08:38.000000000 +0100
@@ -3,6 +3,6 @@
 go 1.11
 
 require (
-       kernel.org/pub/linux/libs/security/libcap/cap v0.2.46
-       kernel.org/pub/linux/libs/security/libcap/psx v0.2.46
+       kernel.org/pub/linux/libs/security/libcap/cap v0.2.47
+       kernel.org/pub/linux/libs/security/libcap/psx v0.2.47
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/goapps/web/go.mod 
new/libcap-2.47/goapps/web/go.mod
--- old/libcap-2.46/goapps/web/go.mod   2020-12-13 00:56:36.000000000 +0100
+++ new/libcap-2.47/goapps/web/go.mod   2021-01-24 03:08:24.000000000 +0100
@@ -2,4 +2,4 @@
 
 go 1.11
 
-require kernel.org/pub/linux/libs/security/libcap/cap v0.2.46
+require kernel.org/pub/linux/libs/security/libcap/cap v0.2.47
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/libcap/cap_proc.c 
new/libcap-2.47/libcap/cap_proc.c
--- old/libcap-2.46/libcap/cap_proc.c   2020-07-19 23:39:03.000000000 +0200
+++ new/libcap-2.47/libcap/cap_proc.c   2020-12-29 02:01:07.000000000 +0100
@@ -390,7 +390,7 @@
 }
 
 /*
- * Set the security mode of the current process.
+ * Set the secbits of the current process.
  */
 int cap_set_secbits(unsigned bits)
 {
@@ -398,6 +398,14 @@
 }
 
 /*
+ * Attempt to raise the no new privs prctl value.
+ */
+static void _cap_set_no_new_privs(struct syscaller_s *sc)
+{
+    (void) _libcap_wprctl6(sc, PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0);
+}
+
+/*
  * Some predefined constants
  */
 #define CAP_SECURED_BITS_BASIC                                 \
@@ -448,7 +456,11 @@
                (void) _cap_drop_bound(sc, c);
            }
            (void) cap_clear_flag(working, CAP_PERMITTED);
+
+           /* for good measure */
+           _cap_set_no_new_privs(sc);
            break;
+
        default:
            errno = EINVAL;
            ret = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/progs/capsh.c 
new/libcap-2.47/progs/capsh.c
--- old/libcap-2.46/progs/capsh.c       2020-11-03 02:58:32.000000000 +0100
+++ new/libcap-2.47/progs/capsh.c       2020-12-29 02:01:07.000000000 +0100
@@ -1,9 +1,10 @@
 /*
  * Copyright (c) 2008-11,16,19,2020 Andrew G. Morgan <mor...@kernel.org>
  *
- * This is a simple 'bash' (-DSHELL) wrapper program that can be used
- * to raise and lower both the bset and pI capabilities before
- * invoking /bin/bash.
+ * This is a multifunction shell wrapper tool that can be used to
+ * launch capable files in various ways with a variety of settings. It
+ * also supports some testing modes, which are used extensively as
+ * part of the libcap build system.
  *
  * The --print option can be used as a quick test whether various
  * capability manipulations work as expected (or not).
@@ -107,8 +108,9 @@
     set = cap_get_secbits();
     if (set >= 0) {
        const char *b = binary(set);  /* verilog convention for binary string */
-       printf("Securebits: 0%lo/0x%lx/%u'b%s\n", set, set,
-              (unsigned) strlen(b), b);
+       printf("Securebits: 0%lo/0x%lx/%u'b%s (no-new-privs=%d)\n", set, set,
+              (unsigned) strlen(b), b,
+              prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0, 0));
        printf(" secure-noroot: %s (%s)\n",
               (set & SECBIT_NOROOT) ? "yes":"no",
               (set & SECBIT_NOROOT_LOCKED) ? "locked":"unlocked");
@@ -909,47 +911,66 @@
                exit(1);
            }
            cap_free(iab);
+       } else if (!strcmp("--no-new-privs", argv[i])) {
+           if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0) != 0) {
+               perror("unable to set no-new-privs");
+               exit(1);
+           }
+       } else if (!strcmp("--has-no-new-privs", argv[i])) {
+           if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0, 0) != 1) {
+               fprintf(stderr, "no-new-privs not set\n");
+               exit(1);
+           }
+       } else if (!strcmp("--license", argv[i])) {
+           printf(
+               "%s has a you choose license: BSD 3-clause or GPL2\n"
+               "Copyright (c) 2008-11,16,19,2020 Andrew G. Morgan"
+               " <mor...@kernel.org>\n", argv[0]);
+           exit(0);
        } else {
        usage:
            printf("usage: %s [args ...]\n"
-                  "  --help         this message (or try 'man capsh')\n"
-                  "  --print        display capability relevant state\n"
-                  "  --decode=xxx   decode a hex string to a list of caps\n"
-                  "  --supports=xxx exit 1 if capability xxx unsupported\n"
-                  "  --has-p=xxx    exit 1 if capability xxx not permitted\n"
-                  "  --has-i=xxx    exit 1 if capability xxx not inheritable\n"
-                  "  --drop=xxx     remove xxx,.. capabilities from bset\n"
-                  "  --dropped=xxx  exit 1 unless bounding cap xxx dropped\n"
-                  "  --has-ambient  exit 1 unless ambient vector supported\n"
                   "  --has-a=xxx    exit 1 if capability xxx not ambient\n"
+                  "  --has-ambient  exit 1 unless ambient vector supported\n"
                   "  --addamb=xxx   add xxx,... capabilities to ambient set\n"
-                  "  --delamb=xxx   remove xxx,... capabilities from ambient\n"
-                  "  --noamb        reset (drop) all ambient capabilities\n"
+                  "  --cap-uid=<n>  use libcap cap_setuid() to change uid\n"
                   "  --caps=xxx     set caps as per cap_from_text()\n"
-                  "  --inh=xxx      set xxx,.. inheritable set\n"
-                  "  --secbits=<n>  write a new value for securebits\n"
+                  "  --chroot=path  chroot(2) to this path\n"
+                  "  --decode=xxx   decode a hex string to a list of caps\n"
+                  "  --delamb=xxx   remove xxx,... capabilities from ambient\n"
+                  "  --forkfor=<n>  fork and make child sleep for <n> sec\n"
+                  "  --gid=<n>      set gid to <n> (hint: id <username>)\n"
+                  "  --groups=g,... set the supplemental groups\n"
+                  "  --has-p=xxx    exit 1 if capability xxx not permitted\n"
+                  "  --has-i=xxx    exit 1 if capability xxx not inheritable\n"
+                  "  --has-no-new-privs  exit 1 if privs not limited\n"
+                  "  --help, -h     this message (or try 'man capsh')\n"
                   "  --iab=...      use cap_iab_from_text() to set iab\n"
-                  "  --keep=<n>     set keep-capability bit to <n>\n"
-                  "  --uid=<n>      set uid to <n> (hint: id <username>)\n"
-                  "  --cap-uid=<n>  libcap cap_setuid() to change uid\n"
+                  "  --inh=xxx      set xxx,.. inheritable set\n"
+                  "  --inmode=<xxx> exit 1 if current mode is not <xxx>\n"
                   "  --is-uid=<n>   exit 1 if uid != <n>\n"
-                  "  --gid=<n>      set gid to <n> (hint: id <username>)\n"
                   "  --is-gid=<n>   exit 1 if gid != <n>\n"
-                  "  --groups=g,... set the supplemental groups\n"
-                   "  --user=<name>  set uid,gid and groups to that of user\n"
-                  "  --chroot=path  chroot(2) to this path\n"
+                  "  --keep=<n>     set keep-capability bit to <n>\n"
+                  "  --killit=<n>   send signal(n) to child\n"
+                  "  --license      display license info\n"
                   "  --modes        list libcap named capability modes\n"
                   "  --mode=<xxx>   set capability mode to <xxx>\n"
-                  "  --inmode=<xxx> exit 1 if current mode is not <xxx>\n"
-                  "  --killit=<n>   send signal(n) to child\n"
-                  "  --forkfor=<n>  fork and make child sleep for <n> sec\n"
+                  "  --no-new-privs set sticky process privilege limiter\n"
+                  "  --noamb        reset (drop) all ambient capabilities\n"
+                  "  --print        display capability relevant state\n"
+                  "  --secbits=<n>  write a new value for securebits\n"
                   "  --shell=/xx/yy use /xx/yy instead of " SHELL " for --\n"
+                  "  --supports=xxx exit 1 if capability xxx unsupported\n"
+                  "  --uid=<n>      set uid to <n> (hint: id <username>)\n"
+                   "  --user=<name>  set uid,gid and groups to that of user\n"
                   "  ==             re-exec(capsh) with args as for --\n"
                   "  --             remaining arguments are for " SHELL "\n"
                   "                 (without -- [%s] will simply exit(0))\n",
                   argv[0], argv[0]);
-
-           exit(strcmp("--help", argv[i]) != 0);
+           if (strcmp("--help", argv[1]) && strcmp("-h", argv[1])) {
+               exit(1);
+           }
+           exit(0);
        }
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/progs/getcap.c 
new/libcap-2.47/progs/getcap.c
--- old/libcap-2.46/progs/getcap.c      2020-07-01 04:43:01.000000000 +0200
+++ new/libcap-2.47/progs/getcap.c      2020-12-29 02:01:07.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997,2007 Andrew G. Morgan  <mor...@kernel.org>
+ * Copyright (c) 1997,2007 Andrew G. Morgan <mor...@kernel.org>
  *
  * This displays the capabilities of a given file.
  */
@@ -23,14 +23,14 @@
 static int recursive = 0;
 static int namespace = 0;
 
-static void usage(void)
+static void usage(int code)
 {
     fprintf(stderr,
-           "usage: getcap [-v] [-r] [-h] [-n] <filename> [<filename> ...]\n"
-           "\n"
-           "\tdisplays the capabilities on the queried file(s).\n"
+    "usage: getcap [-h] [-l] [-n] [-r] [-v] <filename> [<filename> ...]\n"
+    "\n"
+    "\tdisplays the capabilities on the queried file(s).\n"
        );
-    exit(1);
+    exit(code);
 }
 
 static int do_getcap(const char *fname, const struct stat *stbuf,
@@ -82,7 +82,7 @@
 {
     int i, c;
 
-    while ((c = getopt(argc, argv, "rvhn")) > 0) {
+    while ((c = getopt(argc, argv, "rvhnl")) > 0) {
        switch(c) {
        case 'r':
            recursive = 1;
@@ -93,13 +93,20 @@
        case 'n':
            namespace = 1;
            break;
+       case 'h':
+           usage(0);
+       case 'l':
+           printf("%s has a you choose license: BSD 3-clause or GPL2\n"
+               "Copyright (c) 1997,2007 Andrew G. Morgan"
+               " <mor...@kernel.org>\n", argv[0]);
+           exit(0);
        default:
-           usage();
+           usage(1);
        }
     }
 
     if (!argv[optind])
-       usage();
+       usage(1);
 
     for (i=optind; argv[i] != NULL; i++) {
        struct stat stbuf;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/progs/getpcaps.c 
new/libcap-2.47/progs/getpcaps.c
--- old/libcap-2.46/progs/getpcaps.c    2020-07-01 04:43:01.000000000 +0200
+++ new/libcap-2.47/progs/getpcaps.c    2020-12-29 02:01:07.000000000 +0100
@@ -11,19 +11,19 @@
 #include <stdlib.h>
 #include <sys/capability.h>
 
-static void usage(int exiter)
+static void usage(int code)
 {
     fprintf(stderr,
 "usage: getcaps <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"
-"  Optional arguments:\n"
-"     --help or --usage     display this message.\n"
-"     --verbose             use a more verbose output format.\n"
-"     --ugly or --legacy    use the archaic legacy output format.\n\n"
-"[Copyright (c) 1997-8,2007,2019 Andrew G. Morgan  <mor...@kernel.org>]\n"
-       );
-    exit(exiter);
+           "  The capabilities are displayed in the cap_from_text(3) format.\n"
+           "\n"
+           "  Optional arguments:\n"
+           "     --help, -h or --usage display this message.\n"
+           "     --verbose             use a more verbose output format.\n"
+           "     --ugly or --legacy    use the archaic legacy output format.\n"
+           "     --license             display license info\n");
+    exit(code);
 }
 
 int main(int argc, char **argv)
@@ -40,8 +40,14 @@
        int pid;
        cap_t cap_d;
 
-       if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "--usage")) {
+       if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "--usage") ||
+           !strcmp(argv[0], "-h")) {
            usage(0);
+       } else if (!strcmp(argv[0], "--license")) {
+           printf("%s has a you choose license: BSD 3-clause or GPL2\n"
+"[Copyright (c) 1997-8,2007,2019 Andrew G. Morgan <mor...@kernel.org>]\n",
+                  argv[0]);
+           exit(0);
        } else if (!strcmp(argv[0], "--verbose")) {
            verbose = 1;
            continue;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/progs/setcap.c 
new/libcap-2.47/progs/setcap.c
--- old/libcap-2.46/progs/setcap.c      2020-07-01 04:43:01.000000000 +0200
+++ new/libcap-2.47/progs/setcap.c      2020-12-29 02:01:07.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997,2007-8 Andrew G. Morgan  <mor...@kernel.org>
+ * Copyright (c) 1997,2007-8,2020 Andrew G. Morgan <mor...@kernel.org>
  *
  * This sets/verifies the capabilities of a given file.
  */
@@ -11,15 +11,24 @@
 #include <sys/capability.h>
 #include <unistd.h>
 
-static void usage(void)
+static void usage(int status)
 {
     fprintf(stderr,
-           "usage: setcap [-q] [-v] [-n <rootid>] (-r|-|<caps>) <filename> "
+           "usage: setcap [-h] [-q] [-v] [-n <rootid>] (-r|-|<caps>) 
<filename> "
            "[ ... (-r|-|<capsN>) <filenameN> ]\n"
            "\n"
            " Note <filename> must be a regular (non-symlink) file.\n"
+           " -r          remove capability from file\n"
+           " -           read capability text from stdin\n"
+           " <capsN>     cap_from_text(3) formatted file capability\n"
+           "\n"
+           " -h          this message and exit status 0\n"
+           " -q          quietly\n"
+           " -v          validate supplied capability matches file\n"
+           " -n <rootid> write a user namespace limited capability\n"
+           " --license   display the license info\n"
        );
-    exit(1);
+    exit(status);
 }
 
 #define MAXCAP  2048
@@ -65,8 +74,8 @@
     cap_value_t capflag;
     uid_t rootid = 0, f_rootid;
 
-    if (argc < 3) {
-       usage();
+    if (argc < 2) {
+       usage(1);
     }
 
     mycaps = cap_get_proc();
@@ -83,6 +92,16 @@
            quiet = 1;
            continue;
        }
+       if (!strcmp("--license", *argv)) {
+           printf(
+               "%s has a you choose license: BSD 3-clause or GPL2\n"
+               "Copyright (c) 1997,2007-8,2020 Andrew G. Morgan"
+               " <mor...@kernel.org>\n", argv[0]);
+           exit(0);
+       }
+       if (!strcmp(*argv, "-h")) {
+           usage(0);
+       }
        if (!strcmp(*argv, "-v")) {
            verify = 1;
            continue;
@@ -107,7 +126,7 @@
            if (!strcmp(*argv,"-")) {
                retval = read_caps(quiet, *argv, buffer);
                if (retval)
-                   usage();
+                   usage(1);
                text = buffer;
            } else {
                text = *argv;
@@ -116,7 +135,7 @@
            cap_d = cap_from_text(text);
            if (cap_d == NULL) {
                perror("fatal error");
-               usage();
+               usage(1);
            }
            if (cap_set_nsowner(cap_d, rootid)) {
                perror("unable to set nsowner");
@@ -134,7 +153,7 @@
        }
 
        if (--argc <= 0)
-           usage();
+           usage(1);
        /*
         * Set the filesystem capability for this file.
         */
@@ -194,6 +213,7 @@
            if (retval != 0) {
                int explained = 0;
                int oerrno = errno;
+               int somebits = 0;
 #ifdef linux
                cap_value_t cap;
                cap_flag_value_t per_state;
@@ -201,24 +221,28 @@
                for (cap = 0;
                     cap_get_flag(cap_d, cap, CAP_PERMITTED, &per_state) != -1;
                     cap++) {
-                   cap_flag_value_t inh_state, eff_state;
+                   cap_flag_value_t inh_state, eff_state, combined;
 
                    cap_get_flag(cap_d, cap, CAP_INHERITABLE, &inh_state);
                    cap_get_flag(cap_d, cap, CAP_EFFECTIVE, &eff_state);
-                   if ((inh_state | per_state) != eff_state) {
-                       fprintf(stderr, "NOTE: Under Linux, effective file 
capabilities must either be empty, or\n"
-                               "      exactly match the union of selected 
permitted and inheritable bits.\n");
+                   combined = (inh_state | per_state);
+                   somebits |= !!eff_state;
+                   if (combined != eff_state) {
                        explained = 1;
                        break;
                    }
                }
+               if (somebits && explained) {
+                   fprintf(stderr, "NOTE: Under Linux, effective file 
capabilities must either be empty, or\n"
+                           "      exactly match the union of selected 
permitted and inheritable bits.\n");
+               }
 #endif /* def linux */
-               
+
                fprintf(stderr,
                        "Failed to set capabilities on file `%s' (%s)\n",
                        argv[0], strerror(oerrno));
                if (!explained) {
-                   usage();
+                   usage(1);
                }
            }
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/psx/psx.go new/libcap-2.47/psx/psx.go
--- old/libcap-2.46/psx/psx.go  2020-12-12 08:57:35.000000000 +0100
+++ new/libcap-2.47/psx/psx.go  2020-12-24 01:46:18.000000000 +0100
@@ -1,5 +1,5 @@
 // +build linux,!cgo
-// +build go1.16 allthreadssyscall
+// +build go1.16
 
 package psx // import "kernel.org/pub/linux/libs/security/libcap/psx"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libcap-2.46/tests/libcap_launch_test.c 
new/libcap-2.47/tests/libcap_launch_test.c
--- old/libcap-2.46/tests/libcap_launch_test.c  2020-10-18 22:55:28.000000000 
+0200
+++ new/libcap-2.47/tests/libcap_launch_test.c  2020-12-29 02:01:07.000000000 
+0100
@@ -70,7 +70,8 @@
            .iab = "!^cap_chown"
        },
        {
-           .args = { "../progs/tcapsh-static", "--inmode=NOPRIV" },
+           .args = { "../progs/tcapsh-static", "--inmode=NOPRIV",
+                     "--has-no-new-privs" },
            .result = 0,
            .mode = CAP_MODE_NOPRIV
        },

Reply via email to