Mark Android R (rvc-dev-plus-aosp-without-vendor@6692709) as merged

Bug: 166295507
Merged-In: Ib802163dd78dc2cb06eefb928110f19deea34122
Change-Id: Iac3610c6f32e0e4d1f50410bdf22ce868a496754
diff --git a/METADATA b/METADATA
index 79be92f..8a3445f 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@
     type: GIT
     value: "https://git.kernel.org/pub/scm/linux/kernel/git/morgan/libcap.git"
   }
-  version: "libcap-2.39"
+  version: "libcap-2.42"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 7
-    day: 13
+    month: 8
+    day: 3
   }
 }
diff --git a/Make.Rules b/Make.Rules
index 98fb9db..8440e18 100644
--- a/Make.Rules
+++ b/Make.Rules
@@ -41,7 +41,7 @@
 # Common version number defines for libcap
 LIBTITLE=libcap
 VERSION=2
-MINOR=39
+MINOR=42
 
 # 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
@@ -54,20 +54,20 @@
 KERNEL_HEADERS := $(topdir)/libcap/include/uapi
 IPATH += -fPIC -I$(KERNEL_HEADERS) -I$(topdir)/libcap/include
 
-CC := $(CROSS_COMPILE)gcc
+CC ?= $(CROSS_COMPILE)gcc
 DEFINES := -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-CFLAGS := -O2 $(DEFINES)
-BUILD_CC := $(CC)
-BUILD_CFLAGS := -O2 $(DEFINES) $(IPATH)
-AR := $(CROSS_COMPILE)ar
-RANLIB := $(CROSS_COMPILE)ranlib
+CFLAGS ?= -O2 $(DEFINES)
+BUILD_CC ?= $(CC)
+BUILD_CFLAGS ?= -O2 $(DEFINES) $(IPATH)
+AR ?= $(CROSS_COMPILE)ar
+RANLIB ?= $(CROSS_COMPILE)ranlib
 DEBUG = -g #-DDEBUG
 WARNINGS=-Wall -Wwrite-strings \
         -Wpointer-arith -Wcast-qual -Wcast-align \
         -Wstrict-prototypes -Wmissing-prototypes \
         -Wnested-externs -Winline -Wshadow
 LD=$(CC) -Wl,-x -shared
-LDFLAGS := #-g
+LDFLAGS ?= #-g
 LIBCAPLIB := -L$(topdir)/libcap -lcap
 LIBPSXLIB := -L$(topdir)/libcap -lpsx -lpthread
 
@@ -77,7 +77,7 @@
 INCS=$(topdir)/libcap/include/sys/capability.h
 LDFLAGS += -L$(topdir)/libcap
 CFLAGS += -Dlinux $(WARNINGS) $(DEBUG)
-PAM_CAP := $(shell if [ -f /usr/include/security/pam_modules.h ]; then echo yes ; else echo no ; fi)
+PAM_CAP ?= $(shell if [ -f /usr/include/security/pam_modules.h ]; then echo yes ; else echo no ; fi)
 INDENT := $(shell if [ -n "$$(which indent 2>/dev/null)" ]; then echo "| indent -kr" ; fi)
 DYNAMIC := $(shell if [ ! -d "$(topdir)/.git" ]; then echo yes; fi)
 
diff --git a/Makefile b/Makefile
index e148633..03d7748 100644
--- a/Makefile
+++ b/Makefile
@@ -31,8 +31,9 @@
 
 distclean: clean
 	$(DISTCLEAN)
-	@echo "CONFIRM Go package cap has right version dependency on psx:"
-	grep -F "require kernel.org/pub/linux/libs/security/libcap/psx v$(GOMAJOR).$(VERSION).$(MINOR)" cap/go.mod
+	@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 to v$(GOMAJOR).$(VERSION).$(MINOR)" ; exit 1 ; done
+	@echo "ALL go.mod files updated"
 
 release: distclean
 	cd .. && ln -s libcap libcap-$(VERSION).$(MINOR) && tar cvf libcap-$(VERSION).$(MINOR).tar --exclude patches libcap-$(VERSION).$(MINOR)/* && rm libcap-$(VERSION).$(MINOR)
diff --git a/cap/README b/cap/README
new file mode 100644
index 0000000..3ac8433
--- /dev/null
+++ b/cap/README
@@ -0,0 +1,10 @@
+Package cap is the libcap API for Linux Capabilities written in
+Go. The official release announcement site for libcap is:
+
+   https://sites.google.com/site/fullycapable/
+
+Like libcap, the cap package is distributed with a "you choose"
+License. Specifically: BSD three clause, or GPL2. See the LICENSE
+file.
+
+Andrew G. Morgan <morgan@kernel.org>
diff --git a/cap/cap.go b/cap/cap.go
index cb9511f..ed087e1 100644
--- a/cap/cap.go
+++ b/cap/cap.go
@@ -1,4 +1,4 @@
-// Package cap provides the Linux Capabilities userspace library API
+// Package cap provides all the Linux Capabilities userspace library API
 // bindings in native Go.
 //
 // Capabilities are a feature of the Linux kernel that allow fine
@@ -13,26 +13,49 @@
 // described in that paper as well as supporting subsequent changes to
 // the kernel for other styles of inheritable Capability.
 //
+// Some simple things you can do with this package are:
+//
+//   // Read and display the capabilities of the running process
+//   c := cap.GetProc()
+//   log.Printf("this process has these caps:", c)
+//
+//   // Drop any privilege a process might have (including for root,
+//   // but note root 'owns' a lot of system files so a cap-limited
+//   // root can still do considerable damage to a running system).
+//   old := cap.GetProc()
+//   empty := cap.NewSet()
+//   if err := empty.SetProc(); err != nil {
+//       log.Fatalf("failed to drop privilege: %q -> %q: %v", old, empty, err)
+//   }
+//   now := cap.GetProc()
+//   if cap.Differs(now.Compare(empty)) {
+//       log.Fatalf("failed to fully drop privilege: have=%q, wanted=%q", now, empty)
+//   }
+//
 // See https://sites.google.com/site/fullycapable/ for recent updates,
-// some walk-through examples of ways of using 'cap.Set's etc and
-// information on how to file bugs.
+// some more complete walk-through examples of ways of using
+// 'cap.Set's etc and information on how to file bugs.
 //
 // For CGo linked binaries, behind the scenes, the package
 // "kernel.org/pub/linux/libs/security/libcap/psx" is used to perform
 // POSIX semantics system calls that manipulate thread state
 // 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.15beta1
+// Note, if the Go runtime syscall interface contains the Linux
+// variant syscall.AllThreadsSyscall() API (it is not in go1.15rc1
 // 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 for pure Go binaries. In such an
+// 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:
 //
 //   CGO_ENABLED=0 go build -tags allthreadssyscall ...
 //
+//
 // Copyright (c) 2019,20 Andrew G. Morgan <morgan@kernel.org>
+//
+// The cap and psx packages are licensed with a (you choose) BSD
+// 3-clause or GPL2. See LICENSE file for details.
 package cap // import "kernel.org/pub/linux/libs/security/libcap/cap"
 
 import (
@@ -46,13 +69,12 @@
 // Value is the type of a single capability (or permission) bit.
 type Value uint
 
-// Flag is the type of one of the three Value dimensions held in a Set.
-// It is also used in the API for changing the Bounding and Ambient Vectors.
-// For these, in addition to direct manipulation of these vectors see the
-// package supports an IAB abstraction.
+// Flag is the type of one of the three Value dimensions held in a
+// Set.  It is also used in the (*IAB).Fill() method for changing the
+// Bounding and Ambient Vectors.
 type Flag uint
 
-// Effective, Permitted, Inheritable are the three dimensions of Values
+// Effective, Permitted, Inheritable are the three Flags of Values
 // held in a Set.
 const (
 	Effective Flag = iota
@@ -60,12 +82,34 @@
 	Inheritable
 )
 
+// String identifies a Flag value by its conventional "e", "p" or "i"
+// string abbreviation.
+func (f Flag) String() string {
+	switch f {
+	case Effective:
+		return "e"
+	case Permitted:
+		return "p"
+	case Inheritable:
+		return "i"
+	default:
+		return "<Error>"
+	}
+}
+
 // data holds a 32-bit slice of the compressed bitmaps of capability
 // sets as understood by the kernel.
 type data [Inheritable + 1]uint32
 
 // Set is an opaque capabilities container for a set of system
-// capbilities.
+// capbilities. It holds individually addressable capability Value's
+// for the three capability Flag's. See GetFlag() and SetFlag() for
+// how to adjust them individually, and Clear() and ClearFlag() for
+// how to do bulk operations.
+//
+// For admin tasks associated with managing namespace specific file
+// capabilities, Set can also support a namespace-root-UID value which
+// defaults to zero. See GetNSOwner() and SetNSOwner().
 type Set struct {
 	// mu protects all other members of a Set.
 	mu sync.RWMutex
@@ -94,7 +138,7 @@
 	magic uint32
 
 	// words holds the number of uint32's associated with each
-	// capability dimension for this session.
+	// capability Flag for this session.
 	words int
 
 	// maxValues holds the number of bit values that are named by
@@ -378,11 +422,14 @@
 	return nil
 }
 
-// SetAmbient attempts to set a specific Value bit to the enable
-// state. This function will return an error if insufficient
+// SetAmbient attempts to set a specific Value bit to the state,
+// enable. This function will return an error if insufficient
 // permission is available to perform this task. The settings are
 // performed in order and the function returns immediately an error is
-// detected. Use GetAmbient() to unravel where things went wrong.
+// detected. Use GetAmbient() to unravel where things went
+// wrong. Note, the cap package manages an abstraction IAB that
+// captures all three inheritable vectors in a single type. Consider
+// using that.
 func SetAmbient(enable bool, val ...Value) error {
 	scwMu.Lock()
 	defer scwMu.Unlock()
@@ -407,9 +454,9 @@
 // cleared. It works by first reading the set and if it finds any bits
 // raised it will attempt a reset. The test before attempting a reset
 // behavior is a workaround for situations where the Ambient API is
-// locked, but a reset is not actually needed. No Ambient bit not already
-// raised in both the Permitted and Inheritable Set is allowed by the
-// kernel.
+// locked, but a reset is not actually needed. No Ambient bit not
+// already raised in both the Permitted and Inheritable Set is allowed
+// to be raised by the kernel.
 func ResetAmbient() error {
 	scwMu.Lock()
 	defer scwMu.Unlock()
diff --git a/cap/cap_test.go b/cap/cap_test.go
index 662afab..017c565 100644
--- a/cap/cap_test.go
+++ b/cap/cap_test.go
@@ -57,8 +57,12 @@
 	}{
 		{"", "", ErrBadText},
 		{"=", "=", nil},
-		{"= cap_chown+iep cap_chown-i", "= cap_chown+ep", nil},
-		{"= cap_setfcap,cap_chown+iep cap_chown-i", "= cap_setfcap+eip cap_chown+ep", nil},
+		{"= cap_chown+iep cap_chown-i", "cap_chown=ep", nil},
+		{"= cap_setfcap,cap_chown+iep cap_chown-i", "cap_setfcap=eip cap_chown+ep", nil},
+		{"cap_setfcap,cap_chown=iep cap_chown-i", "cap_setfcap=eip cap_chown+ep", nil},
+		{"=i =p", "=p", nil},
+		{"all+pie", "=eip", nil},
+		{"all=p+ie-e", "=ip", nil},
 	}
 	for i, v := range vs {
 		c, err := FromText(v.from)
diff --git a/cap/convenience.go b/cap/convenience.go
index 54e64c6..f094e52 100644
--- a/cap/convenience.go
+++ b/cap/convenience.go
@@ -172,10 +172,10 @@
 // the desired mode.
 //
 // This function will raise cap.SETPCAP in order to achieve this
-// operation, and will completely lower the Effective dimension of
-// the process's Set before returning. This function may fail
-// for lack of permission or because (some of) the Secbits are
-// already locked for the current process.
+// operation, and will completely lower the Effective Flag of the
+// process' Set before returning. This function may fail for lack of
+// permission or because (some of) the Secbits are already locked for
+// the current process.
 func (m Mode) Set() error {
 	scwMu.Lock()
 	defer scwMu.Unlock()
@@ -229,10 +229,10 @@
 // dropping the privilege of the current process. This function will
 // raise cap.SETUID in order to achieve this operation, and will
 // completely lower the Effective vector of the process before
-// returning. Unlike the traditional method of dropping privilege
-// when changing from [e]uid=0 to some other uid, this function only
-// performs a change of uid cap.SETUID is available, and the action
-// does not alter the Permitted dimension of the process' Set.
+// returning. Unlike the traditional method of dropping privilege when
+// changing from [E]UID=0 to some other UID, this function only
+// performs a change of UID cap.SETUID is available, and the action
+// does not alter the Permitted Flag of the process' Set.
 func SetUID(uid int) error {
 	scwMu.Lock()
 	defer scwMu.Unlock()
@@ -279,7 +279,7 @@
 // and all other variants of GID (EGID etc) to the specified value, as
 // well as setting all of the supplementary groups. This function will
 // raise cap.SETGID in order to achieve this operation, and will
-// completely lower the Effective dimension of the process Set before
+// completely lower the Effective Flag of the process Set before
 // returning.
 func SetGroups(gid int, suppl ...int) error {
 	scwMu.Lock()
diff --git a/cap/file.go b/cap/file.go
index b6dc254..a3695b0 100644
--- a/cap/file.go
+++ b/cap/file.go
@@ -52,11 +52,18 @@
 
 // ErrBadSize indicates the the loaded file capability has
 // an invalid number of bytes in it.
-var (
-	ErrBadSize  = errors.New("filecap bad size")
-	ErrBadMagic = errors.New("unsupported magic")
-	ErrBadPath  = errors.New("file is not a regular executable")
-)
+var ErrBadSize = errors.New("filecap bad size")
+
+// ErrBadMagic indicates that the kernel preferred magic number for
+// capability Set values is not supported by this package. This
+// generally implies you are using an exceptionally old
+// "../libcap/cap" package. An upgrade is needed, or failing that see
+// https://sites.google.com/site/fullycapable/ for how to file a bug.
+var ErrBadMagic = errors.New("unsupported magic")
+
+// ErrBadPath indicates a failed attempt to set a file capability on
+// an irregular (non-executable) file.
+var ErrBadPath = errors.New("file is not a regular executable")
 
 // digestFileCap unpacks a file capability and returns it in a *Set
 // form.
@@ -157,6 +164,21 @@
 	return c.nsRoot, nil
 }
 
+// SetNSOwner adds an explicit namespace owner UID to the capability
+// Set. This is only honored when generating file capabilities, and is
+// generally for use by a setup process when installing binaries that
+// use file capabilities to become capable inside a namespace to be
+// administered by that UID. If capability aware code within that
+// namespace writes file capabilities without explicitly setting such
+// a UID, the kernel will fixup the capabilities to be specific to
+// that owner. In this way, the kernel prevents filesystem
+// capabilities from leaking out of that restricted namespace.
+func (c *Set) SetNSOwner(uid int) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	c.nsRoot = uid
+}
+
 // packFileCap transforms a system capability into a VFS form. Because
 // of the way Linux stores capabilities in the file extended
 // attributes, the process is a little lossy with respect to effective
@@ -204,7 +226,7 @@
 // (*os.File).Fd(). This function can also be used to delete a file's
 // capabilities, by calling with c = nil.
 //
-// Note, Linux does not store the full Effective Value dimension in the
+// Note, Linux does not store the full Effective Value Flag in the
 // metadata for the file. Only a single Effective bit is stored in
 // this metadata. This single bit is non-zero if the Permitted vector
 // has any overlapping bits with the Effective or Inheritable vector
@@ -213,8 +235,9 @@
 // capabability unaware binaries that will only work if they magically
 // launch with the needed bits already raised (this bit is sometimes
 // referred to simply as the 'legacy' bit). Without *full* support for
-// capability manipulation, as it is provided in this cap package,
-// this was the only way for Go programs to make use of capabilities.
+// capability manipulation, as it is provided in this "../libcap/cap"
+// package, this was the only way for Go programs to make use of
+// capabilities.
 //
 // The preferred way a binary will actually manipulate its
 // file-acquired capabilities is to carefully and deliberately using
diff --git a/cap/go.mod b/cap/go.mod
index 6c0d56a..da5b4e5 100644
--- a/cap/go.mod
+++ b/cap/go.mod
@@ -2,4 +2,4 @@
 
 go 1.11
 
-require kernel.org/pub/linux/libs/security/libcap/psx v0.2.39
+require kernel.org/pub/linux/libs/security/libcap/psx v0.2.42
diff --git a/cap/iab.go b/cap/iab.go
index e4c2ad6..877ed12 100644
--- a/cap/iab.go
+++ b/cap/iab.go
@@ -9,11 +9,11 @@
 }
 
 // IAB holds a summary of all of the inheritable capability vectors:
-// Inheritable, Ambient and Bounding sets. The Bounding set entries
-// are inverted insofar as a raised bit here implies that when applied
-// to the current process, the capability is dropped - think of this
-// as synonymous with Blocked. This convention is used to support the
-// empty IAB as being mostly harmless.
+// Inh, Amb and Bound. The Bound vector is the logical inverse (two's
+// complement) of the process' Bounding set. That is, raising a Value
+// in the Bound (think blocked) vector is equivalent to dropping that
+// Value from the process' Bounding set. This convention is used to
+// support the empty IAB as being mostly harmless.
 type IAB struct {
 	a, i, nb []uint32
 }
@@ -31,6 +31,21 @@
 	Bound
 )
 
+// String identifies a Vector value by its conventional I A or B
+// string abbreviation.
+func (v Vector) String() string {
+	switch v {
+	case Inh:
+		return "I"
+	case Amb:
+		return "A"
+	case Bound:
+		return "B"
+	default:
+		return "<Error>"
+	}
+}
+
 // IABInit returns an empty IAB.
 func IABInit() *IAB {
 	startUp.Do(multisc.cInit)
@@ -41,8 +56,8 @@
 	}
 }
 
-// IABGetProc summarizes the Inheritable, Ambient and Bounding
-// capabilty vectors of the current process.
+// IABGetProc summarizes the Inh, Amb and Bound capabilty vectors of
+// the current process.
 func IABGetProc() *IAB {
 	iab := IABInit()
 	current := GetProc()
@@ -60,7 +75,7 @@
 	return iab
 }
 
-// IABFromText parses a string representing an IAB set, as generated
+// IABFromText parses a string representing an IAB, as generated
 // by IAB.String(), to generate an IAB.
 func IABFromText(text string) (*IAB, error) {
 	iab := IABInit()
@@ -173,10 +188,10 @@
 }
 
 // SetProc attempts to change the Inheritable, Ambient and Bounding
-// capabilty vectors of the current process. The Bounding vector strongly
-// affects the potential for setting other bits, so this function
-// carefully performs the the combined operation in the most flexible
-// order.
+// capabilty vectors of the current process using the content,
+// iab. The Bounding vector strongly affects the potential for setting
+// other bits, so this function carefully performs the the combined
+// operation in the most flexible manner.
 func (iab *IAB) SetProc() error {
 	scwMu.Lock()
 	defer scwMu.Unlock()
@@ -203,10 +218,12 @@
 }
 
 // SetVector sets all of the vals in the specified vector to the
-// raised value.  Note, the A vector cannot contain values not raised
-// in the I vector, so setting values directly in one vector may have
+// raised value.  Note, the Ambient vector cannot contain values not raised
+// in the Inh vector, so setting values directly in one vector may have
 // the side effect of mirroring the value in the other vector to
-// maintain this constraint.
+// maintain this constraint. Note, raising a Bound vector bit is
+// equivalent to lowering the Bounding vector of the process (when
+// successfully applied with (*IAB).SetProc()).
 func (iab *IAB) SetVector(vec Vector, raised bool, vals ...Value) error {
 	for _, val := range vals {
 		if val >= Value(maxValues) {
@@ -241,12 +258,12 @@
 	return nil
 }
 
-// Fill fills one of the Inheritable, Ambient and Bounding
-// capability vectors from one of the flag vectors of a Set.  Note,
-// filling the I vector will mask the A vector, and filling the A
-// vector may raise entries in the I vector. Further, when filling the
-// Bounding vector, the bits are inverted - that is lowered bits from
-// the Set will be raised in the Bounding vector.
+// Fill fills one of the Inh, Amb and Bound capability vectors from
+// one of the flag vectors of a Set.  Note, filling the Inh vector
+// will mask the Amb vector, and filling the Amb vector may raise
+// entries in the Inh vector. Further, when filling the Bound vector,
+// the bits are inverted from what you might expect - that is lowered
+// bits from the Set will be raised in the Bound vector.
 func (iab *IAB) Fill(vec Vector, c *Set, flag Flag) error {
 	if len(c.flat) != 0 || flag > Inheritable {
 		return ErrBadSet
diff --git a/cap/launch.go b/cap/launch.go
index 90aec85..2f37a2a 100644
--- a/cap/launch.go
+++ b/cap/launch.go
@@ -224,7 +224,7 @@
 }
 
 // Launch performs a new program launch with security state specified
-// in the supplied launcher.
+// in the supplied attr settings.
 func (attr *Launcher) Launch(data interface{}) (int, error) {
 	if attr.path == "" || len(attr.args) == 0 {
 		return -1, ErrLaunchFailed
diff --git a/cap/names.go b/cap/names.go
index 066fd70..ff60017 100644
--- a/cap/names.go
+++ b/cap/names.go
@@ -2,13 +2,24 @@
 
 /* ** DO NOT EDIT THIS FILE. IT WAS AUTO-GENERATED BY LIBCAP'S GO BUILDER (mknames.go) ** */
 
-// NamedCount holds the number of capabilities with official names.
+// NamedCount holds the number of capability values with official
+// names known at the time this libcap/cap version, was released. The
+// "../libcap/cap" package is fully able to manipulate higher numbered
+// capability values by numerical value. However, if you find
+// cap.NamedCount < cap.MaxBits(), it is probably time to upgrade this
+// package on your system.
+//
+// FWIW the userspace tool '/sbin/capsh' also contains a runtime check
+// for the condition that libcap is behind the running kernel in this
+// way.
 const NamedCount = 40
 
-// CHOWN etc., are the named capability values of the Linux kernel. The
-// canonical source for each name is the "uapi/linux/capabilities.h"
-// file, a snapshot (from kernel.org) is hard-coded into this package.
-// Some values may not be available (yet) where the kernel is older.
+// CHOWN etc., are the named capability values of the Linux
+// kernel. The canonical source for each name is the
+// "uapi/linux/capabilities.h" file.  Some values may not be available
+// (yet) where the kernel is older.  The actual number of capabities
+// supported by the running kernel can be obtained using the
+// cap.MaxBits() function.
 const (
 	// CHOWN allows a process to arbitrarily change the user and
 	// group ownership of a file.
diff --git a/cap/oslockluster.go b/cap/oslockluster.go
index 7c753ec..0b2cf2e 100644
--- a/cap/oslockluster.go
+++ b/cap/oslockluster.go
@@ -18,14 +18,12 @@
 //   https://github.com/golang/go/issues/20395
 //   https://github.com/golang/go/issues/20458
 //
-// A value of false for this constant causes cap.(*Launcher).Launch()
-// to park the go routine used to perform the launch indefinitely so
-// its kernel privilege state of the OS Thread locked to it does not
-// pollute the rest of the runtime - yes, it leaks an OSThread. If
-// this is a problem for your application you have two workarounds:
+// A value of false for this constant causes the Launch functionality
+// to fail with an error: cap.ErrNoLaunch. If this value is false you
+// have two choices with respect to the Launch functionality:
 //
-// 1) don't use cap.(*Launcher).Launch()
-// 2) upgrade your Go toolchain to 1.10+
+//   1) don't use cap.(*Launcher).Launch()
+//   2) upgrade your Go toolchain to 1.10+ (ie., do this one).
 const LaunchSupported = false
 
 // validatePA confirms that the pa.Sys entry is not incompatible with
diff --git a/cap/oslocks.go b/cap/oslocks.go
index 10db24c..9754020 100644
--- a/cap/oslocks.go
+++ b/cap/oslocks.go
@@ -18,14 +18,12 @@
 //   https://github.com/golang/go/issues/20395
 //   https://github.com/golang/go/issues/20458
 //
-// A value of false for this constant causes cap.(*Launcher).Launch()
-// to park the go routine used to perform the launch indefinitely so
-// the kernel privilege state of the OS Thread locked to it does not
-// pollute the rest of the runtime - yes, it leaks an OSThread. If
-// this is a problem for your application you have two workarounds:
+// A value of false for this constant causes the Launch functionality
+// to fail with an error: cap.ErrNoLaunch. If this value is false you
+// have two choices with respect to the Launch functionality:
 //
-// 1) don't use cap.(*Launcher).Launch()
-// 2) upgrade your Go toolchain to 1.10+ (ie., do this one).
+//   1) don't use cap.(*Launcher).Launch()
+//   2) upgrade your Go toolchain to 1.10+ (ie., do this one).
 const LaunchSupported = true
 
 // validatePA confirms that the pa.Sys entry is not incompatible with
diff --git a/cap/text.go b/cap/text.go
index 4f37c8f..11dae90 100644
--- a/cap/text.go
+++ b/cap/text.go
@@ -48,7 +48,7 @@
 var combos = []string{"", "e", "p", "ep", "i", "ei", "ip", "eip"}
 
 // histo generates a histogram of flag state combinations.
-func (c *Set) histo(m uint, bins []int, patterns []uint, from, limit Value) uint {
+func (c *Set) histo(bins []int, patterns []uint, from, limit Value) uint {
 	for v := from; v < limit; v++ {
 		b := uint(v & 31)
 		u, bit, err := bitOf(0, v)
@@ -60,28 +60,42 @@
 		x |= uint((c.flat[u][Inheritable]&bit)>>b) * iBin
 		bins[x]++
 		patterns[uint(v)] = x
-		if bins[m] <= bins[x] {
-			m = x
+	}
+	// Note, in the loop, we use >= to pick the smallest value for
+	// m with the highest bin value. That is ties break towards
+	// m=0.
+	m := uint(7)
+	for t := m; t > 0; {
+		t--
+		if bins[t] >= bins[m] {
+			m = t
 		}
 	}
 	return m
 }
 
-// String converts a full capability Set into it canonical readable
-// string representation (which may contain spaces).
+// String converts a full capability Set into a single short readable
+// string representation (which may contain spaces). See the
+// cap.FromText() function for an explanation of its return values.
+//
+// Note (*cap.Set).String() may evolve to generate more compact
+// strings representing the a given Set over time, but it should
+// maintain compatibility with the libcap:cap_to_text() function for
+// any given release. Further, it will always be an inverse of
+// cap.FromText().
 func (c *Set) String() string {
 	if c == nil || len(c.flat) == 0 {
 		return "<invalid>"
 	}
 	bins := make([]int, 8)
-	patterns := make([]uint, 32*words)
+	patterns := make([]uint, maxValues)
 
 	c.mu.RLock()
 	defer c.mu.RUnlock()
 
 	// Note, in order to have a *Set pointer, startUp.Do(cInit)
 	// must have been called which sets maxValues.
-	m := c.histo(0, bins, patterns, 0, Value(maxValues))
+	m := c.histo(bins, patterns, 0, Value(maxValues))
 
 	// Background state is the most popular of the named bits.
 	vs := []string{"=" + combos[m]}
@@ -97,19 +111,29 @@
 			}
 			list = append(list, Value(j).String())
 		}
+		x := strings.Join(list, ",")
+		var y, z string
 		if cf := i & ^m; cf != 0 {
-			vs = append(vs, strings.Join(list, ",")+"+"+combos[cf])
+			op := "+"
+			if len(vs) == 1 && vs[0] == "=" {
+				// Special case "= foo+..." == "foo=...".
+				// Prefer because it
+				vs = nil
+				op = "="
+			}
+			y = op + combos[cf]
 		}
 		if cf := m & ^i; cf != 0 {
-			vs = append(vs, strings.Join(list, ",")+"-"+combos[cf])
+			z = "-" + combos[cf]
 		}
+		vs = append(vs, x+y+z)
 	}
 
 	// The unnamed bits can only add to the above named ones since
 	// unnamed ones are always defaulted to lowered.
 	uBins := make([]int, 8)
 	uPatterns := make([]uint, 32*words)
-	c.histo(0, uBins, uPatterns, Value(maxValues), 32*Value(words))
+	c.histo(uBins, uPatterns, Value(maxValues), 32*Value(words))
 	for i := uint(7); i > 0; i-- {
 		if uBins[i] == 0 {
 			continue
@@ -132,6 +156,43 @@
 
 // FromText converts the canonical text representation for a Set into
 // a freshly allocated Set.
+//
+// The format follows the following pattern: a set of space separated
+// sequences. Each sequence applies over the previous sequence to
+// build up a Set. The format of a sequence is:
+//
+//   [comma list of cap_values][[ops][flags]]*
+//
+// Examples:
+//
+//   "all=ep"
+//   "cap_chown,cap_setuid=ip cap_setuid+e"
+//   "=p cap_setpcap-p+i"
+//
+// Here "all" refers to all named capabilities known to the hosting
+// kernel, and "all" is assumed if no capabilities are listed before
+// an "=".
+//
+// The ops values, "=", "+" and "-" imply "reset and raise", "raise"
+// and "lower" respectively. The "e", "i" and "p" characters
+// correspond to the capabilities of the corresponding Flag: "e"
+// (Effective); "i" (Inheritable); "p" (Permitted).
+//
+// This syntax is overspecified and there are many ways of building
+// the same final Set state. Any sequence that includes a '=' resets
+// the accumulated state of all Flags ignoring earlier sequences. On
+// each of the following lines we give three or more examples of ways
+// to specify a common Set. The last entry on each line is the one
+// generated by (*cap.Set).String() from that Set.
+//
+//    "=p all+ei"  "all=pie"   "=pi all+e"   "=eip"
+//
+//    "cap_chown=p cap_setuid=i"  "cap_chown=ip-p"   "cap_chown=i"
+//
+//    "cap_chown=-p"   "all="   "cap_setuid=pie-pie"   "="
+//
+// Note: FromText() is tested at release time to completely match the
+// import ability of the libcap:cap_from_text() function.
 func FromText(text string) (*Set, error) {
 	c := NewSet()
 	scanner := bufio.NewScanner(strings.NewReader(text))
@@ -139,7 +200,8 @@
 	chunks := 0
 	for scanner.Scan() {
 		chunks++
-		// Parsing for xxx[-+=][eip]+
+
+		// Parsing for xxx([-+=][eip]+)+
 		t := scanner.Text()
 		i := strings.IndexAny(t, "=+-")
 		if i < 0 {
@@ -147,7 +209,11 @@
 		}
 		var vs []Value
 		sep := t[i]
-		if vals := t[:i]; vals != "all" && vals != "" {
+		if vals := t[:i]; vals == "all" {
+			for v := Value(0); v < Value(maxValues); v++ {
+				vs = append(vs, v)
+			}
+		} else if vals != "" {
 			for _, name := range strings.Split(vals, ",") {
 				v, err := FromName(name)
 				if err != nil {
@@ -155,44 +221,102 @@
 				}
 				vs = append(vs, v)
 			}
-		} else if sep != '=' && vals == "" {
-			return nil, ErrBadText // Only "=" supports ""=="all".
+		} else if sep != '=' {
+			if vals == "" {
+				// Only "=" supports ""=="all".
+				return nil, ErrBadText
+			}
+		} else if j := i + 1; j+1 < len(t) {
+			switch t[j] {
+			case '+':
+				sep = 'P'
+				i++
+			case '-':
+				sep = 'M'
+				i++
+			}
 		}
-		sets := t[i+1:]
-		var fE, fP, fI bool
-		for j := 0; j < len(sets); j++ {
-			switch sets[j] {
-			case 'e':
-				fE = true
-			case 'p':
-				fP = true
-			case 'i':
-				fI = true
+		i++
+
+		// There are 5 ways to set: =, =+, =-, +, -. We call
+		// the 2nd and 3rd of these 'P' and 'M'.
+
+		for {
+			// read [eip]+ setting flags.
+			var fE, fP, fI bool
+			for ok := true; ok && i < len(t); i++ {
+				switch t[i] {
+				case 'e':
+					fE = true
+				case 'i':
+					fI = true
+				case 'p':
+					fP = true
+				default:
+					ok = false
+				}
+				if !ok {
+					break
+				}
+			}
+
+			if !(fE || fI || fP) {
+				if sep != '=' {
+					return nil, ErrBadText
+				}
+			}
+
+			switch sep {
+			case '=', 'P', 'M', '+':
+				if sep != '+' {
+					c.Clear()
+					if sep == 'M' {
+						break
+					}
+				}
+				if keep := len(vs) == 0; keep {
+					if sep != '=' {
+						return nil, ErrBadText
+					}
+					c.forceFlag(Effective, fE)
+					c.forceFlag(Permitted, fP)
+					c.forceFlag(Inheritable, fI)
+					break
+				}
+				// =, + and P for specific values are left.
+				if fE {
+					c.SetFlag(Effective, true, vs...)
+				}
+				if fP {
+					c.SetFlag(Permitted, true, vs...)
+				}
+				if fI {
+					c.SetFlag(Inheritable, true, vs...)
+				}
+			case '-':
+				if fE {
+					c.SetFlag(Effective, false, vs...)
+				}
+				if fP {
+					c.SetFlag(Permitted, false, vs...)
+				}
+				if fI {
+					c.SetFlag(Inheritable, false, vs...)
+				}
+			}
+
+			if i == len(t) {
+				break
+			}
+
+			switch t[i] {
+			case '+', '-':
+				sep = t[i]
+				i++
 			default:
 				return nil, ErrBadText
 			}
 		}
-		if sep == '=' {
-			// '=' means default to off for all named flags.
-			// '=ep' means default on for named e & p.
-			keep := len(vs) == 0
-			c.forceFlag(Effective, fE && keep)
-			c.forceFlag(Permitted, fP && keep)
-			c.forceFlag(Inheritable, fI && keep)
-			if keep {
-				continue
-			}
-
-		}
-		if fE {
-			c.SetFlag(Effective, sep != '-', vs...)
-		}
-		if fP {
-			c.SetFlag(Permitted, sep != '-', vs...)
-		}
-		if fI {
-			c.SetFlag(Inheritable, sep == '+', vs...)
-		}
 	}
 	if chunks == 0 {
 		return nil, ErrBadText
diff --git a/doc/cap_copy_ext.3 b/doc/cap_copy_ext.3
index 18c2fe6..acbb487 100644
--- a/doc/cap_copy_ext.3
+++ b/doc/cap_copy_ext.3
@@ -34,7 +34,7 @@
 .BR cap_copy_ext ()
 copies a capability state in working storage, identified by
 .IR cap_p ,
-from system managed space to user-managed space (pointed to by
+from system-managed space to user-managed space (pointed to by
 .IR ext_p )
 and returns the length of the resulting data record.  The size parameter
 represents the maximum size, in bytes, of the resulting data record.  The
diff --git a/doc/cap_from_text.3 b/doc/cap_from_text.3
index 455a52d..59724c7 100644
--- a/doc/cap_from_text.3
+++ b/doc/cap_from_text.3
@@ -139,9 +139,16 @@
 operator will raise all of the listed capabilities in the flagged
 capability sets.  The `\-' operator will lower all of the listed
 capabilities in the flagged capability sets.  For example:
-"all+p" will raise all of the Permitted capabilities; "cap_fowner+p\-i"
-will raise the override-file-ownership capability in the Permitted
-capability set and lower this Inheritable capability;
+"all+p" will raise all of the Permitted capabilities and
+"cap_fowner\-i" will lower the override-file-ownership in the Inheritable set.
+.PP
+The action list can consist of multiple
+.I operator flag
+pairs; the actions are performed in left-to-right order.
+Thus, for example,
+"cap_fowner+p\-i"
+is equivalent to "cap_fowner+p cap_fowner\-i".
+As another example,
 "cap_fowner+pe\-i" and "cap_fowner=+pe" are equivalent.
 .SH "RETURN VALUE"
 .BR cap_from_text (),
@@ -172,11 +179,11 @@
 .BR cap_from_text ()
 and
 .BR cap_to_text ().
-The following shell session shows a some example runs:
+The following shell session shows some example runs:
 .nf
 
 $ ./a.out "cap_chown=p cap_chown+e"
-caps_to_text() returned "= cap_chown+ep"
+caps_to_text() returned "cap_chown=ep"
 $ ./a.out "all=pe cap_chown\-e cap_kill\-pe"
 caps_to_text() returned "=ep cap_chown\-e cap_kill\-ep"
 
diff --git a/doc/cap_get_file.3 b/doc/cap_get_file.3
index a99ab40..3f73734 100644
--- a/doc/cap_get_file.3
+++ b/doc/cap_get_file.3
@@ -6,8 +6,6 @@
 cap_get_file, cap_set_file, cap_get_fd, cap_set_fd \- capability
 manipulation on files
 .SH SYNOPSIS
-.B
-.sp
 .B #include <sys/capability.h>
 .sp
 .BI "cap_t cap_get_file(const char *" path_p );
@@ -20,7 +18,7 @@
 .sp
 .BI "uid_t cap_get_nsowner(cap_t " caps );
 .sp
-.BI "int cap_set_nsowner(cap_t " caps ", uid_t " rootid );
+.BI "int cap_set_nsowner(cap_t " caps ", uid_t " rootuid );
 .sp
 Link with \fI\-lcap\fP.
 .SH DESCRIPTION
@@ -59,22 +57,22 @@
 .IR cap_p
 is used to indicate that capabilities for the file should be deleted.
 For these functions to succeed, the calling process must have the
-effective capability,
-.BR CAP_SETFCAP ,
-enabled and either the effective user ID of the process must match the
+.BR CAP_SETFCAP
+capability in its effective set
+and either the effective user ID of the process must match the
 file owner or the calling process must have the
 .B CAP_FOWNER
-flag in its effective capability set.  The effects of writing the
+capability in its effective capability set.  The effects of writing the
 capability state to any file type other than a regular file are
 undefined.
 .PP
-A capability set held in memory can be associated with the rootid in
-use in a specific namespace. It is possible to get and set this value
+A capability set held in memory can be associated with the root user ID in
+use in a specific user namespace. It is possible to get and set this value
 (in the memory copy) with
 .BR cap_get_nsowner ()
 and
 .BR cap_set_nsowner ()
-respectively. The rootid is ignored by the libcap library in all cases
+respectively. The root user ID is ignored by the libcap library in all cases
 other than when the capability is written to a file. Only if the value
 is non-zero will the library attempt to include it in the written file
 capability set.
@@ -136,4 +134,5 @@
 .BR cap_from_text (3),
 .BR cap_get_proc (3),
 .BR cap_init (3),
-.BR capabilities (7)
+.BR capabilities (7),
+.BR user_namespaces (7)
diff --git a/doc/cap_get_proc.3 b/doc/cap_get_proc.3
index b0a61d1..74e5e8c 100644
--- a/doc/cap_get_proc.3
+++ b/doc/cap_get_proc.3
@@ -167,8 +167,8 @@
 .RB ( cap_mode_t )0
 which
 .BR cap_get_name ()
-declares as
-.IR "UNCERTAIN" .
+identifies as
+.RI `` UNCERTAIN ''.
 Supported modes are:
 .BR CAP_MODE_NOPRIV ", " CAP_MODE_PURE1E_INIT " and " CAP_MODE_PURE1E .
 .PP
@@ -242,16 +242,16 @@
 If your program uses POSIX threads, to achieve meaningful POSIX
 semantics capability manipulation, you should link your program with:
 .sp
-.B ld ... -lcap -lpsx -lpthread --wrap=pthread_create
+.B ld ... \-lcap \-lpsx \-lpthread \-\-wrap=pthread_create
 .sp
 or,
 .sp
-.B gcc ... -lcap -lpsx -lpthread -Wl,-wrap,pthread_create
+.B gcc ... \-lcap \-lpsx \-lpthread \-Wl,\-wrap,pthread_create
 .sp
 When linked this way, due to linker magic, libcap uses
 .BR psx_syscall "(3) and " psx_syscall6 (3)
 to perform state setting system calls.
-.PP
+.SS capgetp() and capsetp()
 The library also supports the deprecated functions:
 .PP
 .BI "int capgetp(pid_t " pid ", cap_t " cap_d );
@@ -261,16 +261,23 @@
 .BR capgetp ()
 attempts to obtain the capabilities of some other process; storing the
 capabilities in a pre-allocated
-.IR cap_d . See
+.IR cap_d .
+See
 .BR cap_init ()
-for information on allocating an empty capability set. This function,
-.BR capgetp (),
-is deprecated, you should use
+for information on allocating an empty capability set. This function
+is deprecated; you should use
 .BR cap_get_pid ().
 .PP
 .BR capsetp ()
-attempts to set the capabilities of some other process(es),
-.IR pid . 
+attempts to set the capabilities of the calling porcess or of
+some other process(es),
+.IR pid .
+Note that setting capabilities of another process is only possible on older
+kernels that do not provide VFS support for setting file capabilities.
+See
+.BR capset (2)
+for information on which kernels provide such support.
+.PP
 If
 .I pid
 is positive it refers to a specific process;  if it is zero, it refers
@@ -279,29 +286,37 @@
 .BR init (8));
 other negative values refer to the
 .I \-pid
-process group.  In order to use this function, the kernel must support
+process group.
+.PP
+In order to use this function, the kernel must support
 it and the calling process must have
 .B CAP_SETPCAP
 raised in its Effective capability set. The capabilities set in the
 target process(es) are those contained in
 .IR cap_d .
+.PP
 Kernels that support filesystem capabilities redefine the semantics of
 .B CAP_SETPCAP
-and on such systems this function will always fail for any target not
+and on such systems,
+.BR capsetp ()
+will always fail for any target not
 equal to the calling process.
 .BR capsetp ()
 returns zero for success, and \-1 on failure.
-
-Where supported by the kernel, the function
+.PP
+On kernels where it is (was) supported,
 .BR capsetp ()
 should be used with care.  It existed, primarily, to overcome an early
 lack of support for capabilities in the filesystems supported by
-Linux.  Note that, by default, the only processes that have
+Linux.  Note that on older kernels where
+.BR capsetp ()
+could be used to set the capabilities of another process,
+the only processes that had
 .B CAP_SETPCAP
-available to them are processes started as a kernel thread.
+available to them by default were processes started as kernel threads.
 (Typically this includes
 .BR init (8),
-kflushd and kswapd.) You will need to recompile the kernel to modify
+kflushd and kswapd.) A kernel recompilation was needed to modify
 this default.
 .SH EXAMPLE
 The code segment below raises the
@@ -334,7 +349,7 @@
 
 .fi
 Alternatively, to completely drop privilege in a program launched
-setuid-root but wanting to run as a specific user-id etc. in such a
+setuid-root but wanting to run as a specific user ID etc. in such a
 way that neither it, nor any of its children can acquire privilege
 again:
 .nf
@@ -361,10 +376,10 @@
 .B capsh
 tool as follows:
 .sp
-.B sudo /sbin/capsh --user=nobody --mode=NOPRIV --print
+.B sudo /sbin/capsh \-\-user=nobody \-\-mode=NOPRIV \-\-print
 .sp
 where
-.B --print
+.B \-\-print
 displays the resulting privilege state.
 .SH "SEE ALSO"
 .BR libcap (3),
diff --git a/doc/cap_init.3 b/doc/cap_init.3
index 96cfea6..362db66 100644
--- a/doc/cap_init.3
+++ b/doc/cap_init.3
@@ -41,7 +41,7 @@
 argument may identify either a
 .I cap_t
 entity, or a
-.I char *
+.I "char\ *"
 entity allocated by the
 .BR cap_to_text ()
 function.
diff --git a/doc/capsh.1 b/doc/capsh.1
index cd30dc3..b02793b 100644
--- a/doc/capsh.1
+++ b/doc/capsh.1
@@ -10,9 +10,10 @@
 of capability testing and environment creation. It also provides some
 debugging features useful for summarizing capability state.
 .SH OPTIONS
-The tool takes a number of optional arguments, acting on them in the
+.B capsh
+takes a number of optional arguments, acting on them in the
 order they are provided. They are as follows:
-.TP 22
+.TP
 .B \-\-help
 Display the list of commands supported by
 .BR capsh .
@@ -30,7 +31,7 @@
 .B ==
 Execute
 .B capsh
-again with remaining arguments. Useful for testing
+again with the remaining arguments. Useful for testing
 .BR exec ()
 behavior.
 .TP
@@ -44,11 +45,12 @@
 .TP
 .BI \-\-drop= cap-list
 Remove the listed capabilities from the prevailing bounding set. The
-capabilities are a comma separated list of capabilities as recognized
+capabilities are a comma-separated list of capabilities as recognized
 by the
 .BR cap_from_name (3)
-function. Use of this feature requires that the capsh program is
-operating with
+function. Use of this feature requires that
+.B capsh
+is operating with
 .B CAP_SETPCAP
 in its effective set.
 .TP
@@ -57,13 +59,15 @@
 equal those provided in the comma separated list. For this action to
 succeed, the prevailing process should already have each of these
 capabilities in the union of the current inheritable and permitted
-capability sets, or the capsh program is operating with
+capability sets, or
+.B capsh
+should be operating with
 .B CAP_SETPCAP
 in its effective set.
 .TP
 .BI \-\-user= username
 Assume the identity of the named user. That is, look up the user's
-.IR uid " and " gid
+UID and GID
 with
 .BR getpwuid (3)
 and their group memberships with
@@ -73,7 +77,7 @@
 and
 .BR cap_setgroups (3).
 Following this command, the effective capabilities will be cleared,
-but the permitted set will not be so the running program is still
+but the permitted set will not be, so the running program is still
 privileged.
 .TP
 .B \-\-modes
@@ -87,11 +91,13 @@
 arrangement recommended for its pre-determined security stance.
 .TP
 .BR \-\-inmode= <mode>
-Confirm that the prevailing mode is so named, or exit with a status 1.
+Confirm that the prevailing mode is that specified in
+.IR <mode> ,
+or exit with a status 1.
 .TP
 .BI \-\-uid= id
 Force all
-.B uid
+UID
 values to equal
 .I id
 using the
@@ -102,41 +108,43 @@
 .BR \-\-cap\-uid= <uid>
 use the
 .BR cap_setuid (3)
-function to set the uid of the current process. This performs all
-prepations for setting the uid without dropping capabilities in the
+function to set the UID of the current process. This performs all
+preparations for setting the UID without dropping capabilities in the
 process. Following this command the prevailing effective capabilities
 will be lowered.
 .TP
-.BI \-\-is-uid= <id>
+.BI \-\-is\-uid= <id>
 Exit with status 1 unless the current
-.IR uid " equals " <id> .
+UID equals
+.IR <id> .
 .TP
 .BI \-\-gid= <id>
 Force all
-.B gid
+GID
 values to equal
 .I id
 using the
 .BR setgid (2)
 system call.
 .TP
-.BI \-\-is-gid= <id>
+.BI \-\-is\-gid= <id>
 Exit with status 1 unless the current
-.IR gid " equals " <id> .
+GIQ equals
+.IR <id> .
 .TP
 .BI \-\-groups= <gid-list>
 Set the supplementary groups to the numerical list provided. The
 groups are set with the
 .BR setgroups (2)
 system call. See
-.B --user
+.B \-\-user
 for a more convenient way of doing this.
 .TP
 .BI \-\-keep= <0|1>
 In a non-pure capability mode, the kernel provides liberal privilege
 to the super-user. However, it is normally the case that when the
 super-user changes
-.I uid
+UID
 to some lesser user, then capabilities are dropped. For these
 situations, the kernel can permit the process to retain its
 capabilities after a
@@ -152,18 +160,24 @@
 is deactivated when an
 .BR exec ()
 is performed. See
-.B --secbits
+.B \-\-secbits
 for ways to disable this feature.
 .TP
 .BI \-\-secbits= N
-Set the security-bits for the program, this is via
-.BR prctl "(2), " PR_SET_SECUREBITS
-API, and the list of supported bits and their meaning can be found in
+Set the security-bits for the program.
+This is done using the
+.BR prctl (2)
+.B PR_SET_SECUREBITS
+operation.
+The list of supported bits and their meaning can be found in
 the
 .B <sys/secbits.h>
 header file. The program will list these bits via the
 .B \-\-print
 command.
+The argument is expressed as a numeric bitmask,
+in any of the formats permitted by
+.BR strtoul (3).
 .TP
 .BI \-\-chroot= path
 Execute the
@@ -198,43 +212,46 @@
 there are some capability related fields of the following form:
 .nf
 
- CapInh:	0000000000000000
- CapPrm:	ffffffffffffffff
- CapEff:	fffffffffffffeff
- CapBnd:	ffffffffffffffff
+CapInh:	0000000000000000
+CapPrm:	0000003fffffffff
+CapEff:	0000003fffffffff
+CapBnd:	0000003fffffffff
+CapAmb:	0000000000000000
 
 .fi
 This option provides a quick way to decode a capability vector
-represented in this form. For example, the missing capability from
-this effective set is 0x0100. By running:
+represented in this hexadecimal form.
+Here's an example that decodes the two lowest capability bits:
+.IP
 .nf
-
- capsh \-\-decode=0x0100
-
+$ \fBcapsh \-\-decode=3\fP
+0x0000000000000003=cap_chown,cap_dac_override
 .fi
-we observe that the missing capability is:
-.BR cap_setpcap .
 .TP
 .BI \-\-supports= xxx
 As the kernel evolves, more capabilities are added. This option can be used
 to verify the existence of a capability on the system. For example,
 .BI \-\-supports= cap_syslog
-will cause capsh to promptly exit with a status of 1 when run on
+will cause
+.B capsh
+to promptly exit with a status of 1 when run on
 kernel 2.6.27.  However, when run on kernel 2.6.38 it will silently
 succeed.
 .TP
-.BI \-\-has-p= xxx
+.BI \-\-has\-p= xxx
 Exit with status 1 unless the
 .I permitted
 vector has capability
 .B xxx
 raised.
 .TP
-.B \-\-has-ambient
+.B \-\-has\-ambient
 Performs a check to see if the running kernel supports ambient
-capabilities. If not, the capsh command exits with status 1.
+capabilities. If not,
+.B capsh
+exits with status 1.
 .TP
-.BI \-\-has-a= xxx
+.BI \-\-has\-a= xxx
 Exit with status 1 unless the
 .I ambient
 vector has capability
@@ -242,18 +259,20 @@
 raised.
 .TP
 .BI \-\-addamb= xxx
-Adds the specificed ambient capability to the running process.
+Adds the specified ambient capability to the running process.
 .TP
 .BI \-\-delamb= xxx
 Removes the specified ambient capability from the running process.
 .TP
 .B \-\-noamb
 Drops all ambient capabilities from the running process.
-.TP
-
 .SH "EXIT STATUS"
-Following successful execution the tool exits with status 0. Following
-an error, the tool immediately exits with status 1.
+Following successful execution,
+.B capsh
+exits with status 0. Following
+an error,
+.B capsh
+immediately exits with status 1.
 .SH AUTHOR
 Written by Andrew G. Morgan <morgan@kernel.org>.
 .SH "REPORTING BUGS"
diff --git a/doc/getcap.8 b/doc/getcap.8
index 05ee9bb..04b601c 100644
--- a/doc/getcap.8
+++ b/doc/getcap.8
@@ -6,21 +6,22 @@
 \fBgetcap\fP [\-v] [\-n] [\-r] [\-h] \fIfilename\fP [ ... ]
 .SH DESCRIPTION
 .B getcap
-displays the name and capabilities of each specified
+displays the name and capabilities of each specified file.
 .SH OPTIONS
 .TP 4
 .B \-h
 prints quick usage.
 .TP 4
 .B \-n
-prints any non-zero namespace rootid value found to be associated with
+prints any non-zero user namespace root user ID value
+found to be associated with
 a file's capabilities.
 .TP 4
 .B \-r
 enables recursive search.
 .TP 4
 .B \-v
-enables to display all searched entries, even if it has no file-capabilities.
+display all searched entries, even if the have no file-capabilities.
 .TP 4
 .IR filename
 One file per line.
@@ -31,4 +32,6 @@
 .SH "SEE ALSO"
 .BR cap_get_file (3),
 .BR cap_to_text (3),
+.BR capabilities (7),
+.BR user_namespaces (7),
 .BR setcap (8)
diff --git a/doc/getpcaps.8 b/doc/getpcaps.8
index b070a3c..d519357 100644
--- a/doc/getpcaps.8
+++ b/doc/getpcaps.8
@@ -23,19 +23,21 @@
 format.
 .PP
 Optional arguments:
-.PP
-.BR --help " or " --usage
+.TP
+.BR \-\-help " or " \-\-usage
 Displays usage information and exits.
-.PP
-.BR --ugly " or " --legacy
+.TP
+.BR \-\-ugly " or " \-\-legacy
 Displays output in a somewhat ugly legacy format.
-.PP
-.B --verbose
+.TP
+.B \-\-verbose
 Displays usage in a legacy-like format but not quite so ugly in modern
 default terminal fonts.
 .SH SEE ALSO
-.BR capsh "(8), " setcap "(8) and " getcap (8).
-.br
+.BR capsh (1),
+.BR capabilities (7),
+.BR getcap (8),
+.BR setcap (8)
 .SH AUTHOR
 This manual page was originally written by Robert Bihlmeyer
 <robbe@debian.org>, for the Debian GNU/Linux system (but may be used
diff --git a/doc/libpsx.3 b/doc/libpsx.3
index 615fceb..a907d8b 100644
--- a/doc/libpsx.3
+++ b/doc/libpsx.3
@@ -11,9 +11,9 @@
 .sp
 Link with one of these:
 .sp
-.I   ld ... -lpsx -lpthread --wrap=pthread_create
+.I   ld ... \-lpsx \-lpthread \-\-wrap=pthread_create
 .sp
-.I   gcc ... -lpsx -lpthread -Wl,-wrap,pthread_create
+.I   gcc ... \-lpsx \-lpthread \-Wl,\-wrap,pthread_create
 .SH DESCRIPTION
 The
 .B libpsx
@@ -58,7 +58,7 @@
 functions.
 .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
+returned by the kernel, or \-1 in the case of an error. In such cases
 .BR errno (3)
 is set to the detailed error value. The
 .BR psx_syscall3 " and " psx_syscall6
diff --git a/doc/setcap.8 b/doc/setcap.8
index 445ed03..463752d 100644
--- a/doc/setcap.8
+++ b/doc/setcap.8
@@ -2,7 +2,7 @@
 .SH NAME
 setcap \- set file capabilities
 .SH SYNOPSIS
-\fBsetcap\fP [\-q] [\-n <rootid>] [\-v] {\fIcapabilities|\-|\-r} filename\fP [ ... \fIcapabilitiesN\fP \fIfileN\fP ]
+\fBsetcap\fP [\-q] [\-n <rootuid>] [\-v] {\fIcapabilities|\-|\-r} filename\fP [ ... \fIcapabilitiesN\fP \fIfileN\fP ]
 .SH DESCRIPTION
 In the absence of the
 .B \-v
@@ -13,19 +13,19 @@
 to the
 .I capabilities
 specified.  The optional
-.B \-n <rootid>
+.B \-n <rootuid>
 argument can be used to set the file capability for use only in a
-namespace with this rootid owner. The
+user namespace with this root user ID owner. The
 .B \-v
 option is used to verify that the specified capabilities are currently
 associated with the file. If \-v and \-n are supplied, the
-.B \-n <rootid>
+.B \-n <rootuid>
 argument is also verified.
 .PP
 The
 .I capabilities
 are specified in the form described in
-.IR cap_from_text (3).
+.BR cap_from_text (3).
 .PP
 The special capability string,
 .BR '\-' ,
@@ -39,7 +39,7 @@
 capability set is
 .B not the same
 as removing it. An empty set can be used to guarantee a file is not
-executed with privilege inspite of the fact that the prevailing
+executed with privilege in spite of the fact that the prevailing
 ambient+inheritable sets would otherwise bestow capabilities on
 executed binaries.
 .PP
@@ -58,4 +58,6 @@
 .SH "SEE ALSO"
 .BR cap_from_text (3),
 .BR cap_get_file (3),
+.BR capabilities (7),
+.BR user_namespaces (7),
 .BR getcap (8)
diff --git a/go/compare-cap.go b/go/compare-cap.go
index c874ad8..4424ebe 100644
--- a/go/compare-cap.go
+++ b/go/compare-cap.go
@@ -281,6 +281,58 @@
 		log.Fatalf("all decode failed in Go: got=%q, want=%q", got, want)
 	}
 
+	// Validate some random values stringify consistently between
+	// libcap.cap_to_text() and (*cap.Set).String().
+	mb := cap.MaxBits()
+	sample := cap.NewSet()
+	for c := cap.Value(0); c < 7*mb; c += 3 {
+		n := int(c)
+		raise, f := c%mb, cap.Flag(c/mb)%3
+		sample.SetFlag(f, true, raise)
+		if v, err := cap.FromText(sample.String()); err != nil {
+			log.Fatalf("[%d] cap to text for %q not reversible: %v", n, sample, err)
+		} else if cf, err := v.Compare(sample); err != nil {
+			log.Fatalf("[%d] FromText generated bad capability from %q: %v", n, sample, err)
+		} else if cf != 0 {
+			log.Fatalf("[%d] text import got=%q want=%q", n, v, sample)
+		}
+		e, err := sample.Export()
+		if err != nil {
+			log.Fatalf("[%d] failed to export %q: %v", n, sample, err)
+		}
+		i, err := cap.Import(e)
+		if err != nil {
+			log.Fatalf("[%d] failed to import %q: %v", n, sample, err)
+		}
+		if cf, err := i.Compare(sample); err != nil {
+			log.Fatalf("[%d] failed to compare %q vs original:%q", n, i, sample)
+		} else if cf != 0 {
+			log.Fatalf("[%d] import got=%q want=%q", n, i, sample)
+		}
+		// Confirm that importing this portable binary
+		// representation in libcap and converting to text,
+		// generates the same text as Go generates. This was
+		// broken prior to v0.2.41.
+		cCap := C.cap_copy_int(unsafe.Pointer(&e[0]))
+		if cCap == nil {
+			log.Fatalf("[%d] C import failed for %q export", n, sample)
+		}
+		var tCLen C.ssize_t
+		tC := C.cap_to_text(cCap, &tCLen)
+		if tC == nil {
+			log.Fatalf("[%d] basic c init caps -> text failure", n)
+		}
+		C.cap_free(unsafe.Pointer(cCap))
+		importT := C.GoString(tC)
+		C.cap_free(unsafe.Pointer(tC))
+		if got, want := len(importT), int(tCLen); got != want {
+			log.Fatalf("[%d] C text generated wrong length: Go=%d, C=%d", n, got, want)
+		}
+		if got, want := importT, sample.String(); got != want {
+			log.Fatalf("[%d] C and Go text rep disparity: C=%q Go=%q", n, got, want)
+		}
+	}
+
 	iab, err := cap.IABFromText("cap_chown,!cap_setuid,^cap_setgid")
 	if err != nil {
 		log.Fatalf("failed to initialize iab from text: %v", err)
diff --git a/go/mknames.go b/go/mknames.go
index 5ae8b3b..ff07218 100644
--- a/go/mknames.go
+++ b/go/mknames.go
@@ -15,7 +15,7 @@
 
 var (
 	header = flag.String("header", "", "name of header file")
-	text = flag.String("textdir", "", "directory name for value txt files")
+	text   = flag.String("textdir", "", "directory name for value txt files")
 )
 
 func main() {
@@ -52,13 +52,24 @@
 
 /* ** DO NOT EDIT THIS FILE. IT WAS AUTO-GENERATED BY LIBCAP'S GO BUILDER (mknames.go) ** */
 
-// NamedCount holds the number of capabilities with official names.
+// NamedCount holds the number of capability values with official
+// names known at the time this libcap/cap version, was released. The
+// "../libcap/cap" package is fully able to manipulate higher numbered
+// capability values by numerical value. However, if you find
+// cap.NamedCount < cap.MaxBits(), it is probably time to upgrade this
+// package on your system.
+//
+// FWIW the userspace tool '/sbin/capsh' also contains a runtime check
+// for the condition that libcap is behind the running kernel in this
+// way.
 const NamedCount = `, len(list), `
 
-// CHOWN etc., are the named capability values of the Linux kernel. The
-// canonical source for each name is the "uapi/linux/capabilities.h"
-// file, a snapshot (from kernel.org) is hard-coded into this package.
-// Some values may not be available (yet) where the kernel is older.
+// CHOWN etc., are the named capability values of the Linux
+// kernel. The canonical source for each name is the
+// "uapi/linux/capabilities.h" file.  Some values may not be available
+// (yet) where the kernel is older.  The actual number of capabities
+// supported by the running kernel can be obtained using the
+// cap.MaxBits() function.
 const (
 `)
 	bits := make(map[string]string)
@@ -68,7 +79,7 @@
 		if err != nil {
 			log.Fatalf("filed to read %q: %v", doc, err)
 		}
-		detail := strings.Split(strings.ReplaceAll(string(content), "CAP_", "cap."), "\n")
+		detail := strings.Split(strings.Replace(string(content), "CAP_", "cap.", -1), "\n")
 		if i != 0 {
 			fmt.Println()
 		}
diff --git a/goapps/setid/go.mod b/goapps/setid/go.mod
index a7d0877..2573dec 100644
--- a/goapps/setid/go.mod
+++ b/goapps/setid/go.mod
@@ -3,6 +3,6 @@
 go 1.11
 
 require (
-	kernel.org/pub/linux/libs/security/libcap/cap v0.2.38
-	kernel.org/pub/linux/libs/security/libcap/psx v0.2.38
+	kernel.org/pub/linux/libs/security/libcap/cap v0.2.42
+	kernel.org/pub/linux/libs/security/libcap/psx v0.2.42
 )
diff --git a/goapps/web/go.mod b/goapps/web/go.mod
index fbd7a86..84c8074 100644
--- a/goapps/web/go.mod
+++ b/goapps/web/go.mod
@@ -2,4 +2,4 @@
 
 go 1.11
 
-require kernel.org/pub/linux/libs/security/libcap/cap v0.2.38 // indirect
+require kernel.org/pub/linux/libs/security/libcap/cap v0.2.42
diff --git a/libcap/Makefile b/libcap/Makefile
index 4321c2f..81b089e 100644
--- a/libcap/Makefile
+++ b/libcap/Makefile
@@ -22,7 +22,9 @@
 MINLIBNAME=$(MAJLIBNAME).$(MINOR)
 GPERF_OUTPUT = _caps_output.gperf
 
-all: $(MINLIBNAME) $(STACAPLIBNAME) libcap.pc libpsx.pc $(STAPSXLIBNAME)
+all: $(MINLIBNAME) $(STACAPLIBNAME) pcs $(STAPSXLIBNAME)
+
+pcs: libcap.pc libpsx.pc
 
 ifeq ($(BUILD_GPERF),yes)
 USE_GPERF_OUTPUT = $(GPERF_OUTPUT)
@@ -91,22 +93,28 @@
 test: cap_test
 	./cap_test
 
-install: all
+install: install-shared install-static
+
+install-common: pcs
 	mkdir -p -m 0755 $(FAKEROOT)$(INCDIR)/sys
 	install -m 0644 include/sys/capability.h $(FAKEROOT)$(INCDIR)/sys
 	install -m 0644 include/sys/psx_syscall.h $(FAKEROOT)$(INCDIR)/sys
+	mkdir -p -m 0755 $(FAKEROOT)$(PKGCONFIGDIR)
+	install -m 0644 libcap.pc $(FAKEROOT)$(PKGCONFIGDIR)/libcap.pc
+	install -m 0644 libpsx.pc $(FAKEROOT)$(PKGCONFIGDIR)/libpsx.pc
+
+install-static: $(STACAPLIBNAME) $(STAPSXLIBNAME) install-common
 	mkdir -p -m 0755 $(FAKEROOT)$(LIBDIR)
 	install -m 0644 $(STACAPLIBNAME) $(FAKEROOT)$(LIBDIR)/$(STACAPLIBNAME)
 	install -m 0644 $(STAPSXLIBNAME) $(FAKEROOT)$(LIBDIR)/$(STAPSXLIBNAME)
+
+install-shared: $(MINLIBNAME) install-common
 	install -m 0644 $(MINLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MINLIBNAME)
 	ln -sf $(MINLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MAJLIBNAME)
 	ln -sf $(MAJLIBNAME) $(FAKEROOT)$(LIBDIR)/$(LIBNAME)
 ifeq ($(FAKEROOT),)
 	-/sbin/ldconfig
 endif
-	mkdir -p -m 0755 $(FAKEROOT)$(PKGCONFIGDIR)
-	install -m 0644 libcap.pc $(FAKEROOT)$(PKGCONFIGDIR)/libcap.pc
-	install -m 0644 libpsx.pc $(FAKEROOT)$(PKGCONFIGDIR)/libpsx.pc
 
 clean:
 	$(LOCALCLEAN)
diff --git a/libcap/cap_file.c b/libcap/cap_file.c
index 3739883..84ae3e1 100644
--- a/libcap/cap_file.c
+++ b/libcap/cap_file.c
@@ -340,9 +340,9 @@
  * Set rootid for the file capability sets.
  */
 
-int cap_set_nsowner(cap_t cap_d, uid_t rootid)
+int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
 {
-	cap_d->rootid = rootid;
+	cap_d->rootid = rootuid;
 	return 0;
 }
 
@@ -378,7 +378,7 @@
     return -1;
 }
 
-int cap_set_nsowner(cap_t cap_d, uid_t rootid)
+int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
 {
 	errno = EINVAL;
 	return -1;
diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c
index 1c97beb..3929f66 100644
--- a/libcap/cap_proc.c
+++ b/libcap/cap_proc.c
@@ -75,7 +75,7 @@
 static int _libcap_overrode_syscalls = 1;
 
 /*
- * psx_load_syscalls() is weakly defined so we can have it overriden
+ * psx_load_syscalls() is weakly defined so we can have it overridden
  * by libpsx if that library is linked. Specifically, when libcap
  * calls psx_load_sycalls() it is prepared to override the default
  * values for the syscalls that libcap uses to change security state.
@@ -238,7 +238,7 @@
 
 /*
  * set the caps on a specific process/pg etc.. The kernel has long
- * since deprecated this asynchronus interface. DON'T EXPECT THIS TO
+ * since deprecated this asynchronous interface. DON'T EXPECT THIS TO
  * EVER WORK AGAIN.
  */
 
@@ -468,7 +468,7 @@
  * set, these modes cannot be undone by the affected process tree and
  * can only be done by "cap_setpcap" permitted processes. Note, a side
  * effect of this function, whether it succeeds or fails, is to clear
- * atleast the CAP_EFFECTIVE flags for the current process.
+ * at least the CAP_EFFECTIVE flags for the current process.
  */
 int cap_set_mode(cap_mode_t flavor)
 {
diff --git a/libcap/cap_text.c b/libcap/cap_text.c
index 12cbf7f..b0fad9d 100644
--- a/libcap/cap_text.c
+++ b/libcap/cap_text.c
@@ -353,7 +353,7 @@
 char *cap_to_text(cap_t caps, ssize_t *length_p)
 {
     char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
-    char *p;
+    char *p, *base;
     int histo[8];
     int m, t;
     unsigned n;
@@ -384,6 +384,7 @@
 	    m = t;
 
     /* blank is not a valid capability set */
+    base = buf;
     p = sprintf(buf, "=%s%s%s",
 		(m & LIBCAP_EFF) ? "e" : "",
 		(m & LIBCAP_INH) ? "i" : "",
@@ -409,7 +410,16 @@
 	p--;
 	n = t & ~m;
 	if (n) {
-	    p += sprintf(p, "+%s%s%s",
+	    char op = '+';
+	    if (base[0] == '=' && base[1] == ' ') {
+		/*
+		 * Special case all lowered default "= foo,...+eip
+		 * ..." as "foo,...=eip ...". (Equivalent but shorter.)
+		 */
+		base += 2;
+		op = '=';
+	    }
+	    p += sprintf(p, "%c%s%s%s", op,
 			 (n & LIBCAP_EFF) ? "e" : "",
 			 (n & LIBCAP_INH) ? "i" : "",
 			 (n & LIBCAP_PER) ? "p" : "");
@@ -460,12 +470,12 @@
 	}
     }
 
-    _cap_debug("%s", buf);
+    _cap_debug("%s", base);
     if (length_p) {
-	*length_p = p - buf;
+	*length_p = p - base;
     }
 
-    return (_libcap_strdup(buf));
+    return (_libcap_strdup(base));
 }
 
 /*
diff --git a/libcap/include/uapi/linux/capability.h b/libcap/include/uapi/linux/capability.h
index 3281e73..6856f1f 100644
--- a/libcap/include/uapi/linux/capability.h
+++ b/libcap/include/uapi/linux/capability.h
@@ -368,7 +368,7 @@
 
 #define CAP_AUDIT_READ       37
 
-/* Alow system performace and observability privileged opeations using
+/* Allow system performance and observability privileged operations using
  * perf_events, i915_perf and other kernel subsystems. */
 
 #define CAP_PERFMON	     38
diff --git a/libcap/include/uapi/linux/securebits.h b/libcap/include/uapi/linux/securebits.h
index 6dae4e9..e9b1309 100644
--- a/libcap/include/uapi/linux/securebits.h
+++ b/libcap/include/uapi/linux/securebits.h
@@ -22,7 +22,7 @@
 #define SECBIT_NOROOT_LOCKED	(issecure_mask(SECURE_NOROOT_LOCKED))
 
 /* When set, setuid to/from uid 0 does not trigger capability-"fixup".
-   When unset, to provide compatiblility with old programs relying on
+   When unset, to provide compatibility with old programs relying on
    set*uid to gain/lose privilege, transitions to/from uid 0 cause
    capabilities to be gained/lost. */
 #define SECURE_NO_SETUID_FIXUP		2
diff --git a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c
index 3030692..6927f7b 100644
--- a/pam_cap/pam_cap.c
+++ b/pam_cap/pam_cap.c
@@ -321,7 +321,7 @@
 
     } else {
 
-	D(("there are no capabilities restrctions on this user"));
+	D(("there are no capabilities restrictions on this user"));
 	return PAM_IGNORE;
 
     }
diff --git a/progs/capsh.c b/progs/capsh.c
index 94bf57d..7bed98e 100644
--- a/progs/capsh.c
+++ b/progs/capsh.c
@@ -879,10 +879,10 @@
 		   "  --delamb=xxx   remove xxx,... capabilities from ambient\n"
 		   "  --noamb        reset (drop) all ambient capabilities\n"
 		   "  --caps=xxx     set caps as per cap_from_text()\n"
-		   "  --inh=xxx      set xxx,.. inheritiable set\n"
+		   "  --inh=xxx      set xxx,.. inheritable set\n"
 		   "  --secbits=<n>  write a new value for securebits\n"
 		   "  --iab=...      use cap_iab_from_text() to set iab\n"
-		   "  --keep=<n>     set keep-capabability bit to <n>\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"
 		   "  --is-uid=<n>   exit 1 if uid != <n>\n"
diff --git a/psx/README b/psx/README
new file mode 100644
index 0000000..c25538a
--- /dev/null
+++ b/psx/README
@@ -0,0 +1,20 @@
+Package psx provides a CGo backed API for invoking system calls in a
+way that each system call is mirrored on all pthreads of the combined
+Go/CGo runtime. Since the Go runtime treats all pthreads as
+interchangeable, a feature like this is needed to meaningfully change
+process privilege (including dropping privilege) in a Go program
+running on Linux. This package is required by:
+
+   "kernel.org/pub/linux/libs/security/libcap/cap"
+
+The functionality is implemented by a C library: libpsx, which is
+distributed with the libcap. The official release announcement site
+for libcap and libpsx is:
+
+   https://sites.google.com/site/fullycapable/
+
+Like libcap/libpsx itself, the psx package is distributed with a "you
+choose" License. Specifically: BSD three clause, or GPL2. See the
+LICENSE file.
+
+Andrew G. Morgan <morgan@kernel.org>
diff --git a/psx/include/sys/psx_syscall.h b/psx/include/sys/psx_syscall.h
index c089a88..8044fbd 100644
--- a/psx/include/sys/psx_syscall.h
+++ b/psx/include/sys/psx_syscall.h
@@ -35,7 +35,7 @@
 
 /*
  * psx_syscall performs the specified syscall on all psx registered
- * threads. The mecanism by which this occurs is much less efficient
+ * threads. The mechanism by which this occurs is much less efficient
  * than a standard system call on Linux, so it should only be used
  * when POSIX semantics are required to change process relevant
  * security state.
diff --git a/psx/psx.c b/psx/psx.c
index cabd342..b494072 100644
--- a/psx/psx.c
+++ b/psx/psx.c
@@ -29,7 +29,7 @@
 #include <sys/syscall.h>
 
 /*
- * psx_load_syscalls() is weakly defined so we can have it overriden
+ * psx_load_syscalls() is weakly defined so we can have it overridden
  * by libpsx if it is linked. Specifically, when libcap calls
  * psx_load_sycalls it will override their defaut values. As can be
  * seen here this present function is a no-op. However, if libpsx is
@@ -272,7 +272,7 @@
      * The only way we can get here is if state is _PSX_INFORK and was
      * previously _PSX_IDLE. However, none of the registered threads
      * exist in this newly minted child process, so we have to reset
-     * the tracking structure to avoid any confusion. We also skuttle
+     * the tracking structure to avoid any confusion. We also scuttle
      * any chance of the PSX API working on more than one thread in
      * the child by leaving the state as _PSX_INFORK. We do support
      * all psx_syscall()s by reverting to them being direct in the
@@ -343,7 +343,7 @@
 }
 
 /*
- * _psx_start_fn is a trampolene for the intended start function, it
+ * _psx_start_fn is a trampoline for the intended start function, it
  * is called blocked (_PSX_CREATE), but releases the block before
  * calling starter->fn. Before releasing the block, the TLS specific
  * attributes are initialized for use by the interrupt handler under
diff --git a/psx/psx.go b/psx/psx.go
index eb18ff4..7eaad55 100644
--- a/psx/psx.go
+++ b/psx/psx.go
@@ -1,39 +1,64 @@
 // Package psx provides support for system calls that are run
 // simultanously on all pthreads.
 //
+// This property can be used to work around a lack of native Go
+// support for such a feature. Something that is the subject of:
+//
+//   https://github.com/golang/go/issues/1435
+//
 // The package works via CGo wrappers for system call functions that
-// call the C libpsx functions of these names. This ensures that the
-// system calls execute symultaneously on all the pthreads of the Go
-// (and CGo) combined runtime. Since Go's runtime freely migrates code
-// execution between pthreads, support of this type is required for
-// any successful attempt to fully drop or modify user privilege of a
-// Go program under Linux. More info on how privilege works can be
-// found here:
+// call the C [lib]psx functions of these names. This ensures that the
+// system calls execute simultaneously on all the pthreads of the Go
+// (and CGo) combined runtime.
+//
+// The psx support works in the following way: the pthread that is
+// first asked to execute the syscall does so, and determines if it
+// succeeds or fails. If it fails, it returns immediately without
+// attempting the syscall on other pthreads. If the initial attempt
+// succeeds, however, then the runtime is stopped in order for the
+// same system call to be performed on all the remaining pthreads of
+// the runtime. Once all pthreads have completed the syscall, the
+// return codes are those obtained by the first pthread's invocation
+// of the syscall.
+//
+// Note, there is no need to use this variant of syscall where the
+// syscalls only read state from the kernel. However, since Go's
+// runtime freely migrates code execution between pthreads, support of
+// this type is required for any successful attempt to fully drop or
+// modify the privilege of a running Go program under Linux.
+//
+// More info on how Linux privilege works can be found here:
 //
 //    https://sites.google.com/site/fullycapable
 //
-// Correct compilation of this package may require an extra step:
+// WARNING: Correct compilation of this package may require an extra
+// step:
 //
 // If your Go compiler is older than go1.15, a workaround may be
 // required to be able to link this package. In order to do what it
-// needs to, this package employs some unusual linking flags. You will
+// needs to this package employs some unusual linking flags. You will
 // need to do this for any Go toolchain that that does not include
 // this patch:
 //
 //    https://go-review.googlesource.com/c/go/+/236139/
 //
 // As of the time of writing, that is all release tags prior to
-// go1.15beta1 .
+// go1.15rc1 .
 //
 // The workaround is to build with the following CGO_LDFLAGS_ALLOW
 // in effect:
 //
 //    export CGO_LDFLAGS_ALLOW="-Wl,-?-wrap[=,][^-.@][^,]*"
 //
+//
 // Copyright (c) 2019,20 Andrew G. Morgan <morgan@kernel.org>
+//
+// The psx package is licensed with a (you choose) BSD 3-clause or
+// GPL2. See LICENSE file for details.
 package psx // import "kernel.org/pub/linux/libs/security/libcap/psx"
 
 import (
+	"runtime"
 	"syscall"
 )
 
@@ -43,27 +68,54 @@
 // #include <errno.h>
 // #include <sys/psx_syscall.h>
 //
-// long __errno_too() { return errno ; }
+// long __errno_too(long set_errno) {
+//     long v = errno;
+//     if (set_errno >= 0) {
+//       errno = set_errno;
+//     }
+//     return v;
+// }
 import "C"
 
+// setErrno returns the current C.errno value and, if v >= 0, sets the
+// CGo errno for a random pthread to value v. If you want some
+// consistency, this needs to be called from runtime.LockOSThread()
+// code. This function is only defined for testing purposes. The psx.c
+// code should properly handle the case that a non-zero errno is saved
+// and restored independently of what these Syscall[36]() functions
+// observe.
+func setErrno(v int) int {
+	return int(C.__errno_too(C.long(v)))
+}
+
 // Syscall3 performs a 3 argument syscall using the libpsx C function
-// psx_syscall3().
+// psx_syscall3(). Syscall3 differs from syscall.[Raw]Syscall()
+// insofar as it is simultaneously executed on every pthread of the
+// combined Go and CGo runtimes.
 func Syscall3(syscallnr, arg1, arg2, arg3 uintptr) (uintptr, uintptr, syscall.Errno) {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
 	v := C.psx_syscall3(C.long(syscallnr), C.long(arg1), C.long(arg2), C.long(arg3))
 	var errno syscall.Errno
 	if v < 0 {
-		errno = syscall.Errno(C.__errno_too())
+		errno = syscall.Errno(C.__errno_too(-1))
 	}
 	return uintptr(v), uintptr(v), errno
 }
 
 // Syscall6 performs a 6 argument syscall using the libpsx C function
-// psx_syscall6()
+// psx_syscall6(). Syscall6 differs from syscall.[Raw]Syscall6() insofar as
+// it is simultaneously executed on every pthread of the combined Go
+// and CGo runtimes.
 func Syscall6(syscallnr, arg1, arg2, arg3, arg4, arg5, arg6 uintptr) (uintptr, uintptr, syscall.Errno) {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
 	v := C.psx_syscall6(C.long(syscallnr), C.long(arg1), C.long(arg2), C.long(arg3), C.long(arg4), C.long(arg5), C.long(arg6))
 	var errno syscall.Errno
 	if v < 0 {
-		errno = syscall.Errno(C.__errno_too())
+		errno = syscall.Errno(C.__errno_too(-1))
 	}
 	return uintptr(v), uintptr(v), errno
 }
diff --git a/psx/psx_test.go b/psx/psx_test.go
index 0e29732..ae6ccd2 100644
--- a/psx/psx_test.go
+++ b/psx/psx_test.go
@@ -1,6 +1,7 @@
 package psx
 
 import (
+	"runtime"
 	"syscall"
 	"testing"
 )
@@ -32,3 +33,34 @@
 		t.Errorf("malformed capget did not return -1, got=%d", got)
 	}
 }
+
+// The man page for errno indicates that it is never set to zero, so
+// validate that it retains its value over a successful Syscall[36]()
+// and is overwritten on a failing syscall.
+func TestErrno(t *testing.T) {
+	// This testing is much easier if we don't have to guess which
+	// thread is running this Go code.
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	// Start from a known bad state and clean up afterwards.
+	setErrno(int(syscall.EPERM))
+	defer setErrno(0)
+
+	v3, _, errno := Syscall3(syscall.SYS_GETUID, 0, 0, 0)
+	if errno != 0 {
+		t.Fatalf("psx getuid failed: %v", errno)
+	}
+	v6, _, errno := Syscall6(syscall.SYS_GETUID, 0, 0, 0, 0, 0, 0)
+	if errno != 0 {
+		t.Fatalf("psx getuid failed: %v", errno)
+	}
+
+	if v3 != v6 {
+		t.Errorf("psx getuid failed to match v3=%d, v6=%d", v3, v6)
+	}
+
+	if v := setErrno(-1); v != int(syscall.EPERM) {
+		t.Errorf("psx changes prevailing errno got=%v(%d) want=%v", syscall.Errno(v), v, syscall.EPERM)
+	}
+}