aboutsummaryrefslogtreecommitdiff
path: root/depends/libcap
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2024-02-10 19:05:02 +0100
committerdec05eba <dec05eba@protonmail.com>2024-02-11 02:11:41 +0100
commit667a6b3b1bc20516d1bf7d8a4611cd3a4d3f3bc6 (patch)
tree2770b29323939cec51670dd0d1aebd39a8041914 /depends/libcap
Initial commit, done
Diffstat (limited to 'depends/libcap')
-rw-r--r--depends/libcap/Make.Rules201
-rw-r--r--depends/libcap/libcap/.gitignore15
-rw-r--r--depends/libcap/libcap/Makefile235
-rw-r--r--depends/libcap/libcap/_makenames.c90
-rw-r--r--depends/libcap/libcap/cap_alloc.c307
-rw-r--r--depends/libcap/libcap/cap_extint.c207
-rw-r--r--depends/libcap/libcap/cap_file.c399
-rw-r--r--depends/libcap/libcap/cap_flag.c369
-rw-r--r--depends/libcap/libcap/cap_names.header5
-rw-r--r--depends/libcap/libcap/cap_proc.c1122
-rw-r--r--depends/libcap/libcap/cap_test.c299
-rw-r--r--depends/libcap/libcap/cap_text.c770
-rw-r--r--depends/libcap/libcap/empty.c1
-rw-r--r--depends/libcap/libcap/execable.c64
-rw-r--r--depends/libcap/libcap/execable.h112
-rw-r--r--depends/libcap/libcap/include/sys/.gitignore1
-rw-r--r--depends/libcap/libcap/include/sys/capability.h255
-rw-r--r--depends/libcap/libcap/include/sys/securebits.h22
-rw-r--r--depends/libcap/libcap/include/uapi/linux/capability.h427
-rw-r--r--depends/libcap/libcap/include/uapi/linux/prctl.h200
-rw-r--r--depends/libcap/libcap/include/uapi/linux/securebits.h60
-rw-r--r--depends/libcap/libcap/libcap.h319
-rw-r--r--depends/libcap/libcap/libcap.pc.in11
-rw-r--r--depends/libcap/libcap/libpsx.pc.in11
-rw-r--r--depends/libcap/libcap/psx_exec.c15
25 files changed, 5517 insertions, 0 deletions
diff --git a/depends/libcap/Make.Rules b/depends/libcap/Make.Rules
new file mode 100644
index 0000000..721fc7a
--- /dev/null
+++ b/depends/libcap/Make.Rules
@@ -0,0 +1,201 @@
+# Common version number defines for libcap
+LIBTITLE=libcap
+VERSION=2
+MINOR=69
+
+#
+## Optional prefixes:
+#
+
+# common 'packaging' directory
+
+FAKEROOT=$(DESTDIR)
+
+# Autoconf-style prefixes are activated when $(prefix) is defined.
+# Otherwise binaries and libraries are installed in /{lib,sbin}/,
+# header files in /usr/include/ and documentation in /usr/man/man?/.
+# These choices are motivated by the fact that getcap and setcap are
+# administrative operations that could be needed to recover a system.
+
+ifndef lib
+lib=$(shell ldd /usr/bin/ld|grep -E "ld-linux|ld.so"|cut -d/ -f2)
+endif
+
+ifndef sbin
+sbin=sbin
+endif
+
+ifdef sbindir
+sbin=$(sbindir)
+endif
+
+ifdef prefix
+exec_prefix=$(prefix)
+lib_prefix=$(exec_prefix)
+inc_prefix=$(lib_prefix)
+man_prefix=$(prefix)/share
+else
+prefix=/usr
+exec_prefix=
+lib_prefix=$(exec_prefix)
+inc_prefix=$(prefix)
+man_prefix=$(prefix)/share
+endif
+
+# Target directories
+
+MANDIR=$(man_prefix)/man
+SBINDIR=$(exec_prefix)/$(sbin)
+INCDIR=$(inc_prefix)/include
+LIBDIR=$(lib_prefix)/$(lib)
+PKGCONFIGDIR=$(LIBDIR)/pkgconfig
+GOPKGDIR=$(prefix)/share/gocode/src
+
+# From here on out, the Go module packages should always remain
+# backwardly compatible. I will only resort to using major version 2
+# etc if Go's syntax dramatically changes in a backwards incompatible
+# manner. (Let's hope not. If that happens, I'll also drop deprecated
+# API functions.)
+GOMAJOR=1
+
+# Compilation specifics
+
+KERNEL_HEADERS := $(topdir)/libcap/include/uapi
+LIBCAP_INCLUDES = -I$(KERNEL_HEADERS) -I$(topdir)/libcap/include
+DEFINES := -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+SYSTEM_HEADERS = /usr/include
+
+SUDO := sudo
+CC := $(CROSS_COMPILE)gcc
+LD := $(CC) -Wl,-x -shared
+AR := $(CROSS_COMPILE)ar
+RANLIB := $(CROSS_COMPILE)ranlib
+OBJCOPY := $(CROSS_COMPILE)objcopy
+
+# Reference:
+# CPPFLAGS used for building .o files from .c & .h files
+# CFLAGS used when building libraries from .o, .c and .h files
+
+DEBUG = # -g -DDEBUG
+WARNINGS=-Wall -Wwrite-strings -Wpointer-arith -Wcast-qual -Wcast-align \
+ -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs \
+ -Winline -Wshadow -Wunreachable-code
+COPTS ?= -O2
+CFLAGS ?= $(COPTS) $(DEBUG)
+CFLAGS += $(WARNINGS)
+CPPFLAGS += -Dlinux $(DEFINES) $(LIBCAP_INCLUDES)
+LDFLAGS ?= # -g
+
+BUILD_CC ?= $(CC)
+BUILD_LD ?= $(BUILD_CC) -Wl,-x -shared
+BUILD_COPTS ?= $(COPTS)
+BUILD_CFLAGS ?= $(BUILD_COPTS)
+BUILD_CPPFLAGS += -Dlinux $(WARNINGS) $(DEBUG) $(DEFINES) $(LIBCAP_INCLUDES)
+BUILD_LDFLAGS ?= $(LDFLAGS)
+BUILD_SED ?= sed
+BUILD_GREP ?= grep
+BUILD_EGREP ?= $(BUILD_GREP) -E
+BUILD_FGREP ?= $(BUILD_GREP) -F
+
+# Plan to eventually redefine BUILD_GPERF to be the actual gperf tool
+# alias as per above. Typical distributions are upto a year behind
+# HEAD so we'll not do that before 2023-01-01.
+ifdef BUILD_GPERF
+$(error BUILD_GPERF is now reserved, please use USE_GPERF=yes or no instead)
+endif
+
+USE_GPERF ?= $(shell which gperf >/dev/null 2>/dev/null && echo yes)
+
+LIBCAPLIB := -L$(topdir)/libcap -lcap
+PSXLINKFLAGS := -lpthread -Wl,-wrap,pthread_create
+LIBPSXLIB := -L$(topdir)/libcap -lpsx $(PSXLINKFLAGS)
+
+INCS=$(topdir)/libcap/include/sys/capability.h
+INDENT := $(shell if [ -n "$$(which indent 2>/dev/null)" ]; then echo "| indent -kr" ; fi)
+
+# SHARED tracks whether or not the SHARED libraries (libcap.so,
+# libpsx.so and pam_cap.so) are built. (Some environments don't
+# support shared libraries.)
+SHARED ?= yes
+# DYNAMIC controls how capsh etc are linked - to shared or static libraries
+# Force enabled with "make DYNAMIC=yes ...".
+DYNAMIC := $(shell if [ ! -d "$(topdir)/.git" ]; then echo $(SHARED); else echo no ; fi)
+
+PAM_CAP ?= $(shell if [ -f /usr/include/security/pam_modules.h ]; then echo $(SHARED) ; else echo no ; fi)
+
+# If your system does not support pthreads, override this as "no".
+#
+# make PTHREADS=no ...
+#
+# This implies no Go support and no C/C++ libpsx build. Why might you
+# need libpsx for non-Go use? Tl;dr for POSIX semantics security:
+#
+# https://sites.google.com/site/fullycapable/who-ordered-libpsx
+#
+PTHREADS ?= yes
+
+ifeq ($(PTHREADS),yes)
+GO ?= go
+GOLANG ?= $(shell if [ -n "$(shell $(GO) version 2>/dev/null)" ]; then echo yes ; else echo no ; fi)
+ifeq ($(GOLANG),yes)
+GOROOT ?= $(shell $(GO) env GOROOT)
+GOCGO ?= $(shell if [ "$(shell $(GO) env CGO_ENABLED)" = 1 ]; then echo yes ; else echo no ; fi)
+GOOSARCH ?= $(shell $(GO) env GOHOSTOS)_$(shell $(GO) env GOHOSTARCH)
+CGO_REQUIRED := $(shell $(topdir)/go/cgo-required.sh $(GO))
+ifeq ($(CGO_REQUIRED),1)
+# Strictly speaking go1.15 doesn't need this, but 1.16 is when the
+# real golang support arrives for non-cgo support, so drop the last
+# vestige of legacy workarounds then.
+CGO_LDFLAGS_ALLOW := CGO_LDFLAGS_ALLOW="-Wl,-?-wrap[=,][^-.@][^,]*"
+endif
+CGO_CFLAGS := $(LIBCAP_INCLUDES)
+CGO_LDFLAGS := -L$(topdir)/libcap
+GO_BUILD_FLAGS :=
+endif
+endif
+
+# If you want capsh to launch with something other than /bin/bash
+# build like this:
+#
+# make CAPSH_SHELL='-DSHELL=\"/bin/sh\"'
+#
+# or undefine the following:
+#CAPSH_SHELL := '-DSHELL="/bin/sh"'
+
+# When installing setcap, you can arrange for the installation process
+# to set its inheritable bit to be able to place capabilities on files.
+# It can be used in conjunction with pam_cap (associated with su and
+# certain users say) to make it useful for specially blessed users.
+#
+# make RAISE_SETFCAP=yes install
+#
+# This is now defaulted to no because some distributions started
+# shipping with all users blessed with full inheritable sets which
+# makes no sense whatsoever!
+#
+# Indeed, it looked alarmingly like these distributions were recreating
+# the environment for what became known as the sendmail-capabilities
+# bug from 2000:
+#
+# https://sites.google.com/site/fullycapable/Home/thesendmailcapabilitiesissue
+#
+# they are also nullifying the difference between a p-bit and an i-bit.
+#
+# Folk really should read this document, which explains there is a really
+# important difference being lost here:
+#
+# https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/33528.pdf
+#
+# In the context of this tree, on such such systems, a yes setting will
+# guarantee that every user, by default, is able to bless any binary with
+# any capability - a ready made local exploit mechanism.
+RAISE_SETFCAP := no
+
+# If set to yes, this will cause the go "web" demo app to force the needed p
+# bit to be able to bind to port 80 without running as root.
+RAISE_GO_FILECAP := no
+
+# Global cleanup stuff
+
+LOCALCLEAN=rm -f *~ core
+DISTCLEAN=@find . \( -name '*.orig' -o -name '*.rej' \) | xargs rm -f
diff --git a/depends/libcap/libcap/.gitignore b/depends/libcap/libcap/.gitignore
new file mode 100644
index 0000000..a0771d4
--- /dev/null
+++ b/depends/libcap/libcap/.gitignore
@@ -0,0 +1,15 @@
+cap_names.h
+cap_names.list.h
+_caps_output.gperf
+libcap.a
+libcap.so*
+libpsx.a
+libpsx.so*
+_makenames
+cap_test
+libcap.pc
+libpsx.pc
+empty
+loader.txt
+cap_magic.o
+psx_magic.o
diff --git a/depends/libcap/libcap/Makefile b/depends/libcap/libcap/Makefile
new file mode 100644
index 0000000..f5dde3e
--- /dev/null
+++ b/depends/libcap/libcap/Makefile
@@ -0,0 +1,235 @@
+#
+# defines
+#
+topdir=$(shell pwd)/..
+include ../Make.Rules
+#
+# Library version
+#
+CAPLIBNAME=$(LIBTITLE).so
+STACAPLIBNAME=$(LIBTITLE).a
+#
+PSXTITLE=libpsx
+PSXLIBNAME=$(PSXTITLE).so
+STAPSXLIBNAME=$(PSXTITLE).a
+
+CAPFILES=cap_alloc cap_proc cap_extint cap_flag cap_text cap_file
+CAPMAGICOBJ=cap_magic.o
+PSXFILES=../psx/psx
+PSXMAGICOBJ=psx_magic.o
+
+# Always build libcap sources this way:
+CFLAGS += -fPIC
+
+# The linker magic needed to build a dynamic library as independently
+# executable
+MAGIC=-Wl,-e,__so_start
+
+INCLS=libcap.h cap_names.h $(INCS)
+GPERF_OUTPUT = _caps_output.gperf
+
+CAPOBJS=$(addsuffix .o, $(CAPFILES))
+MAJCAPLIBNAME=$(CAPLIBNAME).$(VERSION)
+MINCAPLIBNAME=$(MAJCAPLIBNAME).$(MINOR)
+
+PSXOBJS=$(addsuffix .o, $(PSXFILES))
+MAJPSXLIBNAME=$(PSXLIBNAME).$(VERSION)
+MINPSXLIBNAME=$(MAJPSXLIBNAME).$(MINOR)
+
+all: pcs $(STACAPLIBNAME)
+ifeq ($(SHARED),yes)
+ $(MAKE) $(CAPLIBNAME)
+endif
+ifeq ($(PTHREADS),yes)
+ $(MAKE) $(STAPSXLIBNAME)
+ifeq ($(SHARED),yes)
+ $(MAKE) $(PSXLIBNAME)
+endif
+endif
+
+pcs: $(LIBTITLE).pc
+ifeq ($(PTHREADS),yes)
+ $(MAKE) $(PSXTITLE).pc
+endif
+
+ifeq ($(USE_GPERF),yes)
+USE_GPERF_OUTPUT = $(GPERF_OUTPUT)
+INCLUDE_GPERF_OUTPUT = -DINCLUDE_GPERF_OUTPUT='"$(GPERF_OUTPUT)"'
+endif
+
+$(LIBTITLE).pc: $(LIBTITLE).pc.in
+ $(BUILD_SED) -e 's,@prefix@,$(prefix),' \
+ -e 's,@exec_prefix@,$(exec_prefix),' \
+ -e 's,@libdir@,$(LIBDIR),' \
+ -e 's,@includedir@,$(inc_prefix)/include,' \
+ -e 's,@VERSION@,$(VERSION).$(MINOR),' \
+ -e 's,@deps@,$(DEPS),' \
+ $< >$@
+
+$(PSXTITLE).pc: $(PSXTITLE).pc.in
+ $(BUILD_SED) -e 's,@prefix@,$(prefix),' \
+ -e 's,@exec_prefix@,$(exec_prefix),' \
+ -e 's,@libdir@,$(LIBDIR),' \
+ -e 's,@includedir@,$(inc_prefix)/include,' \
+ -e 's,@VERSION@,$(VERSION).$(MINOR),' \
+ -e 's,@deps@,$(DEPS),' \
+ $< >$@
+
+_makenames: _makenames.c cap_names.list.h
+ $(BUILD_CC) $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< -o $@
+
+cap_names.h: _makenames
+ ./_makenames > cap_names.h
+
+$(GPERF_OUTPUT): cap_names.list.h cap_names.header Makefile
+ (cat cap_names.header ; $(BUILD_SED) -e 's/[\{\}"]//g' -e 's/,$$//' cap_names.list.h) | gperf --ignore-case --language=ANSI-C --readonly --null-strings --global-table --hash-function-name=__cap_hash_name --lookup-function-name="__cap_lookup_name" -c -t -m20 $(INDENT) > $@
+ $(BUILD_SED) -e 's/unsigned int len/size_t len/' -i $@
+
+# Intention is that libcap keeps up with torvalds' tree, as reflected
+# by this maintained version of the kernel header. libcap dynamically
+# trims the meaning of "all" capabilities down to that of the running
+# kernel as of 2.30. That is, all production kernels should be equal
+# to or behind libcap.
+#
+# Note "./libcap.so --summary" should explain how the built libcap.so
+# compares to the running kernel.
+UAPI_HEADER := $(topdir)/libcap/include/uapi/linux/capability.h
+cap_names.list.h: Makefile $(UAPI_HEADER)
+ @echo "=> making $@ from $(UAPI_HEADER)"
+ $(BUILD_EGREP) '^#define\s+CAP_([^\s]+)\s+[0-9]+\s*$$' include/uapi/linux/capability.h | $(BUILD_SED) -e 's/^#define\s\+/{"/' -e 's/\s*$$/},/' -e 's/\s\+/",/' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' > $@
+
+$(STACAPLIBNAME): $(CAPOBJS)
+ $(AR) rcs $@ $^
+ $(RANLIB) $@
+
+$(STAPSXLIBNAME): $(PSXOBJS) include/sys/psx_syscall.h
+ $(AR) rcs $@ $(PSXOBJS)
+ $(RANLIB) $@
+
+ifeq ($(SHARED),yes)
+
+empty: empty.c
+ $(CC) -o $@ $<
+
+loader.txt: empty
+ $(OBJCOPY) --dump-section .interp=$@ $< /dev/null
+
+cap_magic.o: execable.h execable.c loader.txt libcap.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DLIBRARY_VERSION=\"$(LIBTITLE)-$(VERSION).$(MINOR)\" -DSHARED_LOADER=\"$(shell cat loader.txt)\" -include ./libcap.h -c execable.c -o $@
+
+$(CAPLIBNAME) $(MAJCAPLIBNAME) $(MINCAPLIBNAME): $(CAPOBJS) $(CAPMAGICOBJ)
+ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(MAJCAPLIBNAME) -o $(MINCAPLIBNAME) $^ $(MAGIC)
+ ln -sf $(MINCAPLIBNAME) $(MAJCAPLIBNAME)
+ ln -sf $(MAJCAPLIBNAME) $(CAPLIBNAME)
+
+psx_magic.o: execable.h psx_exec.c loader.txt
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DLIBRARY_VERSION=\"$(PSXTITLE)-$(VERSION).$(MINOR)\" -DSHARED_LOADER=\"$(shell cat loader.txt)\" -c psx_exec.c -o $@
+
+$(PSXLIBNAME) $(MAJPSXLIBNAME) $(MINPSXLIBNAME): $(PSXOBJS) include/sys/psx_syscall.h $(PSXMAGICOBJ)
+ $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(MAJPSXLIBNAME) -o $(MINPSXLIBNAME) $(PSXOBJS) $(PSXMAGICOBJ) $(MAGIC) $(PSXLINKFLAGS)
+ ln -sf $(MINPSXLIBNAME) $(MAJPSXLIBNAME)
+ ln -sf $(MAJPSXLIBNAME) $(PSXLIBNAME)
+endif
+
+%.o: %.c $(INCLS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+cap_text.o: cap_text.c $(USE_GPERF_OUTPUT) $(INCLS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDE_GPERF_OUTPUT) -c $< -o $@
+
+cap_test: cap_test.c $(INCLS) $(CAPOBJS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $< $(CAPOBJS) -o $@
+
+libcapsotest: $(CAPLIBNAME)
+ ./$(CAPLIBNAME)
+ ./$(CAPLIBNAME) --usage
+ ./$(CAPLIBNAME) --help
+ ./$(CAPLIBNAME) --summary
+
+libpsxsotest: $(PSXLIBNAME)
+ ./$(PSXLIBNAME)
+
+test: cap_test
+ ./cap_test
+ifeq ($(SHARED),yes)
+ $(MAKE) libcapsotest
+ifeq ($(PTHREADS),yes)
+ $(MAKE) libpsxsotest
+endif
+endif
+
+sudotest:
+ @echo no sudotests for libcap
+
+install: install-static
+ifeq ($(SHARED),yes)
+ $(MAKE) install-shared
+endif
+
+install-static: install-static-cap
+ifeq ($(PTHREADS),yes)
+ $(MAKE) install-static-psx
+endif
+
+install-shared: install-shared-cap
+ifeq ($(PTHREADS),yes)
+ $(MAKE) install-shared-psx
+endif
+
+install-cap: install-static-cap
+ifeq ($(SHARED),yes)
+ $(MAKE) install-shared-cap
+endif
+
+install-psx: install-static-psx
+ifeq ($(SHARED),yes)
+ $(MAKE) install-shared-psx
+endif
+
+install-static-cap: install-common-cap $(STACAPLIBNAME)
+ install -m 0644 $(STACAPLIBNAME) $(FAKEROOT)$(LIBDIR)/$(STACAPLIBNAME)
+
+install-shared-cap: install-common-cap $(MINCAPLIBNAME)
+ install -m 0755 $(MINCAPLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MINCAPLIBNAME)
+ ln -sf $(MINCAPLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MAJCAPLIBNAME)
+ ln -sf $(MAJCAPLIBNAME) $(FAKEROOT)$(LIBDIR)/$(CAPLIBNAME)
+ifeq ($(FAKEROOT),)
+ -/sbin/ldconfig
+endif
+
+install-static-psx: install-common-psx $(STAPSXLIBNAME)
+ install -m 0644 $(STAPSXLIBNAME) $(FAKEROOT)$(LIBDIR)/$(STAPSXLIBNAME)
+
+install-shared-psx: install-common-psx $(MINPSXLIBNAME)
+ install -m 0755 $(MINPSXLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MINPSXLIBNAME)
+ ln -sf $(MINPSXLIBNAME) $(FAKEROOT)$(LIBDIR)/$(MAJPSXLIBNAME)
+ ln -sf $(MAJPSXLIBNAME) $(FAKEROOT)$(LIBDIR)/$(PSXLIBNAME)
+ifeq ($(FAKEROOT),)
+ -/sbin/ldconfig
+endif
+
+install-common-cap: install-common $(LIBTITLE).pc
+ install -m 0644 include/sys/capability.h $(FAKEROOT)$(INCDIR)/sys
+ install -m 0644 $(LIBTITLE).pc $(FAKEROOT)$(PKGCONFIGDIR)/$(LIBTITLE).pc
+
+include/sys/psx_syscall.h: ../psx/psx_syscall.h
+ rm -f $@
+ ln -s ../../../psx/psx_syscall.h $@
+
+install-common-psx: install-common $(PSXTITLE).pc include/sys/psx_syscall.h
+ install -m 0644 include/sys/psx_syscall.h $(FAKEROOT)$(INCDIR)/sys
+ install -m 0644 $(PSXTITLE).pc $(FAKEROOT)$(PKGCONFIGDIR)/$(PSXTITLE).pc
+
+install-common:
+ mkdir -p -m 0755 $(FAKEROOT)$(INCDIR)/sys
+ mkdir -p -m 0755 $(FAKEROOT)$(PKGCONFIGDIR)
+ mkdir -p -m 0755 $(FAKEROOT)$(LIBDIR)
+
+clean:
+ $(LOCALCLEAN)
+ rm -f $(CAPOBJS) $(CAPLIBNAME)* $(STACAPLIBNAME) $(LIBTITLE).pc
+ rm -f $(PSXOBJS) $(PSXLIBNAME)* $(STAPSXLIBNAME) $(PSXTITLE).pc
+ rm -f cap_names.h cap_names.list.h _makenames $(GPERF_OUTPUT) cap_test
+ rm -f include/sys/psx_syscall.h
+ rm -f $(CAPMAGICOBJ) $(PSXMAGICOBJ) empty loader.txt
+ cd include/sys && $(LOCALCLEAN)
diff --git a/depends/libcap/libcap/_makenames.c b/depends/libcap/libcap/_makenames.c
new file mode 100644
index 0000000..30eb080
--- /dev/null
+++ b/depends/libcap/libcap/_makenames.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997-8,2020 Andrew G. Morgan <morgan@kernel.org>
+ *
+ * This is a file to make the capability <-> string mappings for
+ * libcap.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * #include 'sed' generated array
+ */
+
+struct {
+ const char *name;
+ int index;
+} const list[] = {
+#include "cap_names.list.h"
+ {NULL, -1}
+};
+
+/*
+ * recalloc uses realloc to grow some memory but it resets the
+ * indicated extended empty space.
+ */
+static void *recalloc(void *p, int was, int is) {
+ char *n = realloc(p, is);
+ if (!n) {
+ fputs("out of memory", stderr);
+ exit(1);
+ }
+ memset(n+was, 0, is-was);
+ return n;
+}
+
+int main(void)
+{
+ int i, maxcaps=0, maxlength=0;
+ const char **pointers = NULL;
+ int pointers_avail = 0;
+
+ for ( i=0; list[i].index >= 0 && list[i].name; ++i ) {
+ if (maxcaps <= list[i].index) {
+ maxcaps = list[i].index + 1;
+ }
+ if (pointers == NULL || list[i].index >= pointers_avail) {
+ int was = pointers_avail * sizeof(char *);
+ pointers_avail = 2 * list[i].index + 1;
+ pointers = recalloc(pointers, was, pointers_avail * sizeof(char *));
+ if (pointers == NULL) {
+ perror("unable to continue");
+ exit(1);
+ }
+ }
+ pointers[list[i].index] = list[i].name;
+ int n = strlen(list[i].name);
+ if (n > maxlength) {
+ maxlength = n;
+ }
+ }
+
+ printf("/*\n"
+ " * DO NOT EDIT: this file is generated automatically from\n"
+ " *\n"
+ " * <uapi/linux/capability.h>\n"
+ " */\n\n"
+ "#define __CAP_BITS %d\n"
+ "#define __CAP_NAME_SIZE %d\n"
+ "\n"
+ "#ifdef LIBCAP_PLEASE_INCLUDE_ARRAY\n"
+ "#define LIBCAP_CAP_NAMES { \\\n", maxcaps, maxlength+1);
+
+ for (i=0; i<maxcaps; ++i) {
+ if (pointers[i]) {
+ printf(" /* %d */\t\"%s\", \\\n", i, pointers[i]);
+ } else {
+ printf(" /* %d */\tNULL,\t\t/* - presently unused */ \\\n", i);
+ }
+ }
+
+ printf(" }\n"
+ "#endif /* LIBCAP_PLEASE_INCLUDE_ARRAY */\n"
+ "\n"
+ "/* END OF FILE */\n");
+
+ free(pointers);
+ exit(0);
+}
diff --git a/depends/libcap/libcap/cap_alloc.c b/depends/libcap/libcap/cap_alloc.c
new file mode 100644
index 0000000..504abd2
--- /dev/null
+++ b/depends/libcap/libcap/cap_alloc.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1997-8,2019,2021 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file deals with allocation and deallocation of internal
+ * capability sets as specified by POSIX.1e (formerlly, POSIX 6).
+ */
+
+#include "libcap.h"
+
+/*
+ * Make start up atomic.
+ */
+static __u8 __libcap_mutex;
+
+/*
+ * These get set via the pre-main() executed constructor function below it.
+ */
+static cap_value_t _cap_max_bits;
+
+__attribute__((visibility ("hidden")))
+__attribute__((constructor (300))) void _libcap_initialize(void)
+{
+ int errno_saved = errno;
+ _cap_mu_lock(&__libcap_mutex);
+ if (!_cap_max_bits) {
+ cap_set_syscall(NULL, NULL);
+ _binary_search(_cap_max_bits, cap_get_bound, 0, __CAP_MAXBITS,
+ __CAP_BITS);
+ }
+ _cap_mu_unlock(&__libcap_mutex);
+ errno = errno_saved;
+}
+
+cap_value_t cap_max_bits(void)
+{
+ return _cap_max_bits;
+}
+
+/*
+ * capability allocation is all done in terms of this structure.
+ */
+struct _cap_alloc_s {
+ __u32 magic;
+ __u32 size;
+ union {
+ struct _cap_struct set;
+ struct cap_iab_s iab;
+ struct cap_launch_s launcher;
+ } u;
+};
+
+/*
+ * Obtain a blank set of capabilities
+ */
+cap_t cap_init(void)
+{
+ struct _cap_alloc_s *raw_data;
+ cap_t result;
+
+ raw_data = calloc(1, sizeof(struct _cap_alloc_s));
+ if (raw_data == NULL) {
+ _cap_debug("out of memory");
+ errno = ENOMEM;
+ return NULL;
+ }
+ raw_data->magic = CAP_T_MAGIC;
+ raw_data->size = sizeof(struct _cap_alloc_s);
+
+ result = &raw_data->u.set;
+ result->head.version = _LIBCAP_CAPABILITY_VERSION;
+ capget(&result->head, NULL); /* load the kernel-capability version */
+
+ switch (result->head.version) {
+#ifdef _LINUX_CAPABILITY_VERSION_1
+ case _LINUX_CAPABILITY_VERSION_1:
+ break;
+#endif
+#ifdef _LINUX_CAPABILITY_VERSION_2
+ case _LINUX_CAPABILITY_VERSION_2:
+ break;
+#endif
+#ifdef _LINUX_CAPABILITY_VERSION_3
+ case _LINUX_CAPABILITY_VERSION_3:
+ break;
+#endif
+ default: /* No idea what to do */
+ cap_free(result);
+ result = NULL;
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * This is an internal library function to duplicate a string and
+ * tag the result as something cap_free can handle.
+ */
+__attribute__((visibility ("hidden"))) char *_libcap_strdup(const char *old)
+{
+ struct _cap_alloc_s *header;
+ char *raw_data;
+ size_t len;
+
+ if (old == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ len = strlen(old);
+ if ((len & 0x3fffffff) != len) {
+ _cap_debug("len is too long for libcap to manage");
+ errno = EINVAL;
+ return NULL;
+ }
+ len += 1 + 2*sizeof(__u32);
+ if (len < sizeof(struct _cap_alloc_s)) {
+ len = sizeof(struct _cap_alloc_s);
+ }
+
+ raw_data = calloc(1, len);
+ if (raw_data == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ header = (void *) raw_data;
+ header->magic = CAP_S_MAGIC;
+ header->size = (__u32) len;
+
+ raw_data += 2*sizeof(__u32);
+ strcpy(raw_data, old);
+ return raw_data;
+}
+
+/*
+ * This function duplicates an internal capability set with
+ * calloc()'d memory. It is the responsibility of the user to call
+ * cap_free() to liberate it.
+ */
+cap_t cap_dup(cap_t cap_d)
+{
+ cap_t result;
+
+ if (!good_cap_t(cap_d)) {
+ _cap_debug("bad argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ result = cap_init();
+ if (result == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+
+ _cap_mu_lock(&cap_d->mutex);
+ memcpy(result, cap_d, sizeof(*cap_d));
+ _cap_mu_unlock(&cap_d->mutex);
+ _cap_mu_unlock(&result->mutex);
+
+ return result;
+}
+
+cap_iab_t cap_iab_init(void)
+{
+ struct _cap_alloc_s *base = calloc(1, sizeof(struct _cap_alloc_s));
+ if (base == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+ base->magic = CAP_IAB_MAGIC;
+ base->size = sizeof(struct _cap_alloc_s);
+ return &base->u.iab;
+}
+
+/*
+ * This function duplicates an internal iab tuple with calloc()'d
+ * memory. It is the responsibility of the user to call cap_free() to
+ * liberate it.
+ */
+cap_iab_t cap_iab_dup(cap_iab_t iab)
+{
+ cap_iab_t result;
+
+ if (!good_cap_iab_t(iab)) {
+ _cap_debug("bad argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ result = cap_iab_init();
+ if (result == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+
+ _cap_mu_lock(&iab->mutex);
+ memcpy(result, iab, sizeof(*iab));
+ _cap_mu_unlock(&iab->mutex);
+ _cap_mu_unlock(&result->mutex);
+
+ return result;
+}
+
+/*
+ * cap_new_launcher allocates some memory for a launcher and
+ * initializes it. To actually launch a program with this launcher,
+ * use cap_launch(). By default, the launcher is a no-op from a
+ * security perspective and will act just as fork()/execve()
+ * would. Use cap_launcher_setuid() etc to override this.
+ */
+cap_launch_t cap_new_launcher(const char *arg0, const char * const *argv,
+ const char * const *envp)
+{
+ struct _cap_alloc_s *data = calloc(1, sizeof(struct _cap_alloc_s));
+ if (data == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+ data->magic = CAP_LAUNCH_MAGIC;
+ data->size = sizeof(struct _cap_alloc_s);
+
+ struct cap_launch_s *attr = &data->u.launcher;
+ attr->arg0 = arg0;
+ attr->argv = argv;
+ attr->envp = envp;
+ return attr;
+}
+
+/*
+ * cap_func_launcher allocates some memory for a launcher and
+ * initializes it. The purpose of this launcher, unlike one created
+ * with cap_new_launcher(), is to execute some function code from a
+ * forked copy of the program. The forked process will exit when the
+ * callback function, func, returns.
+ */
+cap_launch_t cap_func_launcher(int (callback_fn)(void *detail))
+{
+ struct _cap_alloc_s *data = calloc(1, sizeof(struct _cap_alloc_s));
+ if (data == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+ data->magic = CAP_LAUNCH_MAGIC;
+ data->size = sizeof(struct _cap_alloc_s);
+
+ struct cap_launch_s *attr = &data->u.launcher;
+ attr->custom_setup_fn = callback_fn;
+ return attr;
+}
+
+/*
+ * Scrub and then liberate the recognized allocated object.
+ */
+int cap_free(void *data_p)
+{
+ if (!data_p) {
+ return 0;
+ }
+
+ /* confirm alignment */
+ if ((sizeof(uintptr_t)-1) & (uintptr_t) data_p) {
+ _cap_debug("whatever we're cap_free()ing it isn't aligned right: %p",
+ data_p);
+ errno = EINVAL;
+ return -1;
+ }
+
+ void *base = (void *) (-2 + (__u32 *) data_p);
+ struct _cap_alloc_s *data = base;
+ switch (data->magic) {
+ case CAP_T_MAGIC:
+ _cap_mu_lock(&data->u.set.mutex);
+ break;
+ case CAP_S_MAGIC:
+ case CAP_IAB_MAGIC:
+ break;
+ case CAP_LAUNCH_MAGIC:
+ if (data->u.launcher.iab != NULL) {
+ _cap_mu_unlock(&data->u.launcher.iab->mutex);
+ if (cap_free(data->u.launcher.iab) != 0) {
+ return -1;
+ }
+ }
+ data->u.launcher.iab = NULL;
+ if (cap_free(data->u.launcher.chroot) != 0) {
+ return -1;
+ }
+ data->u.launcher.chroot = NULL;
+ break;
+ default:
+ _cap_debug("don't recognize what we're supposed to liberate");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * operate here with respect to base, to avoid tangling with the
+ * automated buffer overflow detection.
+ */
+ memset(base, 0, data->size);
+ free(base);
+ data_p = NULL;
+ data = NULL;
+ base = NULL;
+ return 0;
+}
diff --git a/depends/libcap/libcap/cap_extint.c b/depends/libcap/libcap/cap_extint.c
new file mode 100644
index 0000000..462cc65
--- /dev/null
+++ b/depends/libcap/libcap/cap_extint.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1997-8,2021 Andrew G. Morgan <morgan@kernel.org>
+ *
+ * This file deals with exchanging internal and external
+ * representations of capability sets.
+ */
+
+#include "libcap.h"
+
+/*
+ * External representation for capabilities. (exported as a fixed
+ * length)
+ */
+#define CAP_EXT_MAGIC "\220\302\001\121"
+#define CAP_EXT_MAGIC_SIZE 4
+const static __u8 external_magic[CAP_EXT_MAGIC_SIZE+1] = CAP_EXT_MAGIC;
+
+/*
+ * This is the largest size libcap can currently export.
+ * cap_size() may return something smaller depending on the
+ * content of its argument cap_t.
+ */
+struct cap_ext_struct {
+ __u8 magic[CAP_EXT_MAGIC_SIZE];
+ __u8 length_of_capset;
+ /*
+ * note, we arrange these so the caps are stacked with byte-size
+ * resolution
+ */
+ __u8 bytes[CAP_SET_SIZE][NUMBER_OF_CAP_SETS];
+};
+
+/*
+ * minimum exported flag size: libcap2 has always exported with flags
+ * this size.
+ */
+static size_t _libcap_min_ext_flag_size = CAP_SET_SIZE < 8 ? CAP_SET_SIZE : 8;
+
+static ssize_t _cap_size_locked(cap_t cap_d)
+{
+ size_t j, used;
+ for (j=used=0; j<CAP_SET_SIZE; j+=sizeof(__u32)) {
+ int i;
+ __u32 val = 0;
+ for (i=0; i<NUMBER_OF_CAP_SETS; ++i) {
+ val |= cap_d->u[j/sizeof(__u32)].flat[i];
+ }
+ if (val == 0) {
+ continue;
+ }
+ if (val > 0x0000ffff) {
+ if (val > 0x00ffffff) {
+ used = j+4;
+ } else {
+ used = j+3;
+ }
+ } else if (val > 0x000000ff) {
+ used = j+2;
+ } else {
+ used = j+1;
+ }
+ }
+ if (used < _libcap_min_ext_flag_size) {
+ used = _libcap_min_ext_flag_size;
+ }
+ return (ssize_t)(CAP_EXT_MAGIC_SIZE + 1+ NUMBER_OF_CAP_SETS * used);
+}
+
+/*
+ * return size of external capability set
+ */
+ssize_t cap_size(cap_t cap_d)
+{
+ size_t used;
+ if (!good_cap_t(cap_d)) {
+ return ssizeof(struct cap_ext_struct);
+ }
+ _cap_mu_lock(&cap_d->mutex);
+ used = _cap_size_locked(cap_d);
+ _cap_mu_unlock(&cap_d->mutex);
+ return used;
+}
+
+/*
+ * Copy the internal (cap_d) capability set into an external
+ * representation. The external representation is portable to other
+ * Linux architectures.
+ */
+
+ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length)
+{
+ struct cap_ext_struct *result = (struct cap_ext_struct *) cap_ext;
+ ssize_t csz, len_set;
+ int i;
+
+ /* valid arguments? */
+ if (!good_cap_t(cap_d) || cap_ext == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ _cap_mu_lock(&cap_d->mutex);
+ csz = _cap_size_locked(cap_d);
+ if (csz > length) {
+ errno = EINVAL;
+ _cap_mu_unlock_return(&cap_d->mutex, -1);
+ }
+ len_set = (csz - (CAP_EXT_MAGIC_SIZE+1))/NUMBER_OF_CAP_SETS;
+
+ /* fill external capability set */
+ memcpy(&result->magic, external_magic, CAP_EXT_MAGIC_SIZE);
+ result->length_of_capset = len_set;
+
+ for (i=0; i<NUMBER_OF_CAP_SETS; ++i) {
+ size_t j;
+ for (j=0; j<len_set; ) {
+ __u32 val;
+
+ val = cap_d->u[j/sizeof(__u32)].flat[i];
+
+ result->bytes[j++][i] = val & 0xFF;
+ if (j < len_set) {
+ result->bytes[j++][i] = (val >>= 8) & 0xFF;
+ }
+ if (j < len_set) {
+ result->bytes[j++][i] = (val >>= 8) & 0xFF;
+ }
+ if (j < len_set) {
+ result->bytes[j++][i] = (val >> 8) & 0xFF;
+ }
+ }
+ }
+
+ /* All done: return length of external representation */
+ _cap_mu_unlock_return(&cap_d->mutex, csz);
+}
+
+/*
+ * Import an external representation to produce an internal rep.
+ * the internal rep should be liberated with cap_free().
+ *
+ * Note, this function assumes that cap_ext has a valid length. That
+ * is, feeding garbage to this function will likely crash the program.
+ */
+cap_t cap_copy_int(const void *cap_ext)
+{
+ const struct cap_ext_struct *export =
+ (const struct cap_ext_struct *) cap_ext;
+ cap_t cap_d;
+ int set, blen;
+
+ /* Does the external representation make sense? */
+ if ((export == NULL)
+ || memcmp(export->magic, external_magic, CAP_EXT_MAGIC_SIZE)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Obtain a new internal capability set */
+ if (!(cap_d = cap_init()))
+ return NULL;
+
+ blen = export->length_of_capset;
+ for (set=0; set<NUMBER_OF_CAP_SETS; ++set) {
+ unsigned blk;
+ int bno = 0;
+ for (blk=0; blk<(CAP_SET_SIZE/sizeof(__u32)); ++blk) {
+ __u32 val = 0;
+
+ if (bno != blen)
+ val = export->bytes[bno++][set];
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 8;
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 16;
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 24;
+
+ cap_d->u[blk].flat[set] = val;
+ }
+ }
+
+ /* all done */
+ return cap_d;
+}
+
+/*
+ * This function is the same as cap_copy_int() although it requires an
+ * extra argument that is the length of the cap_ext data. Before
+ * running cap_copy_int() the function validates that length is
+ * consistent with the stated length. It returns NULL on error.
+ */
+cap_t cap_copy_int_check(const void *cap_ext, ssize_t length)
+{
+ const struct cap_ext_struct *export =
+ (const struct cap_ext_struct *) cap_ext;
+
+ if (length < 1+CAP_EXT_MAGIC_SIZE) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (length < 1+CAP_EXT_MAGIC_SIZE + export->length_of_capset * NUMBER_OF_CAP_SETS) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return cap_copy_int(cap_ext);
+}
diff --git a/depends/libcap/libcap/cap_file.c b/depends/libcap/libcap/cap_file.c
new file mode 100644
index 0000000..0bc07f7
--- /dev/null
+++ b/depends/libcap/libcap/cap_file.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 1997,2007,2016 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file deals with getting/setting capabilities from/on files.
+ */
+
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <byteswap.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/*
+ * We hardcode the prototypes for the Linux system calls here since
+ * there are no libcap library APIs that expose the user to these
+ * details, and that way we don't need to force clients to link any
+ * other libraries to access them.
+ */
+extern ssize_t getxattr(const char *, const char *, void *, size_t);
+extern ssize_t fgetxattr(int, const char *, void *, size_t);
+extern int setxattr(const char *, const char *, const void *, size_t, int);
+extern int fsetxattr(int, const char *, const void *, size_t, int);
+extern int removexattr(const char *, const char *);
+extern int fremovexattr(int, const char *);
+
+/*
+ * This public API was moved to include/uapi/linux/xattr.h . For just
+ * these definitions, it isn't really worth managing this in our build
+ * system with yet another copy of a header file. We just, provide
+ * fallback definitions here.
+ */
+#ifndef XATTR_CAPS_SUFFIX
+#define XATTR_CAPS_SUFFIX "capability"
+#endif
+#ifndef XATTR_SECURITY_PREFIX
+#define XATTR_SECURITY_PREFIX "security."
+#endif
+#ifndef XATTR_NAME_CAPS
+#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
+#endif
+
+#include "libcap.h"
+
+#ifdef VFS_CAP_U32
+
+#if VFS_CAP_U32 != __CAP_BLKS
+# error VFS representation of capabilities is not the same size as kernel
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define FIXUP_32BITS(x) bswap_32(x)
+#else
+#define FIXUP_32BITS(x) (x)
+#endif
+
+static cap_t _fcaps_load(struct vfs_ns_cap_data *rawvfscap, cap_t result,
+ int bytes)
+{
+ __u32 magic_etc;
+ unsigned tocopy, i;
+
+ magic_etc = FIXUP_32BITS(rawvfscap->magic_etc);
+ switch (magic_etc & VFS_CAP_REVISION_MASK) {
+ case VFS_CAP_REVISION_1:
+ tocopy = VFS_CAP_U32_1;
+ bytes -= XATTR_CAPS_SZ_1;
+ break;
+
+ case VFS_CAP_REVISION_2:
+ tocopy = VFS_CAP_U32_2;
+ bytes -= XATTR_CAPS_SZ_2;
+ break;
+
+ case VFS_CAP_REVISION_3:
+ tocopy = VFS_CAP_U32_3;
+ bytes -= XATTR_CAPS_SZ_3;
+ result->rootid = FIXUP_32BITS(rawvfscap->rootid);
+ break;
+
+ default:
+ cap_free(result);
+ result = NULL;
+ return result;
+ }
+
+ /*
+ * Verify that we loaded exactly the right number of bytes
+ */
+ if (bytes != 0) {
+ cap_free(result);
+ result = NULL;
+ return result;
+ }
+
+ for (i=0; i < tocopy; i++) {
+ result->u[i].flat[CAP_INHERITABLE]
+ = FIXUP_32BITS(rawvfscap->data[i].inheritable);
+ result->u[i].flat[CAP_PERMITTED]
+ = FIXUP_32BITS(rawvfscap->data[i].permitted);
+ if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
+ result->u[i].flat[CAP_EFFECTIVE]
+ = result->u[i].flat[CAP_INHERITABLE]
+ | result->u[i].flat[CAP_PERMITTED];
+ }
+ }
+ while (i < __CAP_BLKS) {
+ result->u[i].flat[CAP_INHERITABLE]
+ = result->u[i].flat[CAP_PERMITTED]
+ = result->u[i].flat[CAP_EFFECTIVE] = 0;
+ i++;
+ }
+
+ return result;
+}
+
+static int _fcaps_save(struct vfs_ns_cap_data *rawvfscap, cap_t cap_d,
+ int *bytes_p)
+{
+ __u32 eff_not_zero, magic;
+ unsigned tocopy, i;
+
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&cap_d->mutex);
+
+ switch (cap_d->head.version) {
+ case _LINUX_CAPABILITY_VERSION_1:
+ magic = VFS_CAP_REVISION_1;
+ tocopy = VFS_CAP_U32_1;
+ *bytes_p = XATTR_CAPS_SZ_1;
+ break;
+
+ case _LINUX_CAPABILITY_VERSION_2:
+ case _LINUX_CAPABILITY_VERSION_3:
+ magic = VFS_CAP_REVISION_2;
+ tocopy = VFS_CAP_U32_2;
+ *bytes_p = XATTR_CAPS_SZ_2;
+ break;
+
+ default:
+ errno = EINVAL;
+ _cap_mu_unlock_return(&cap_d->mutex, -1);
+ }
+
+ if (cap_d->rootid != 0) {
+ if (cap_d->head.version < _LINUX_CAPABILITY_VERSION_3) {
+ _cap_debug("namespaces with non-0 rootid unsupported by kernel");
+ errno = EINVAL;
+ _cap_mu_unlock_return(&cap_d->mutex, -1);
+ }
+ magic = VFS_CAP_REVISION_3;
+ tocopy = VFS_CAP_U32_3;
+ *bytes_p = XATTR_CAPS_SZ_3;
+ rawvfscap->rootid = FIXUP_32BITS(cap_d->rootid);
+ }
+
+ _cap_debug("setting named file capabilities");
+
+ for (eff_not_zero = 0, i = 0; i < tocopy; i++) {
+ eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE];
+ }
+ while (i < __CAP_BLKS) {
+ if ((cap_d->u[i].flat[CAP_EFFECTIVE]
+ || cap_d->u[i].flat[CAP_INHERITABLE]
+ || cap_d->u[i].flat[CAP_PERMITTED])) {
+ /*
+ * System does not support these capabilities
+ */
+ errno = EINVAL;
+ _cap_mu_unlock_return(&cap_d->mutex, -1);
+ }
+ i++;
+ }
+
+ for (i=0; i < tocopy; i++) {
+ rawvfscap->data[i].permitted
+ = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]);
+ rawvfscap->data[i].inheritable
+ = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]);
+
+ if (eff_not_zero
+ && ((~(cap_d->u[i].flat[CAP_EFFECTIVE]))
+ & (cap_d->u[i].flat[CAP_PERMITTED]
+ | cap_d->u[i].flat[CAP_INHERITABLE]))) {
+ errno = EINVAL;
+ _cap_mu_unlock_return(&cap_d->mutex, -1);
+ }
+ }
+
+ if (eff_not_zero == 0) {
+ rawvfscap->magic_etc = FIXUP_32BITS(magic);
+ } else {
+ rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE);
+ }
+
+ _cap_mu_unlock_return(&cap_d->mutex, 0); /* success */
+}
+
+/*
+ * Get the capabilities of an open file, as specified by its file
+ * descriptor.
+ */
+
+cap_t cap_get_fd(int fildes)
+{
+ cap_t result;
+
+ /* allocate a new capability set */
+ result = cap_init();
+ if (result) {
+ struct vfs_ns_cap_data rawvfscap;
+ int sizeofcaps;
+
+ _cap_debug("getting fildes capabilities");
+
+ /* fill the capability sets via a system call */
+ sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS,
+ &rawvfscap, sizeof(rawvfscap));
+ if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
+ cap_free(result);
+ result = NULL;
+ } else {
+ result = _fcaps_load(&rawvfscap, result, sizeofcaps);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Get the capabilities from a named file.
+ */
+
+cap_t cap_get_file(const char *filename)
+{
+ cap_t result;
+
+ /* allocate a new capability set */
+ result = cap_init();
+ if (result) {
+ struct vfs_ns_cap_data rawvfscap;
+ int sizeofcaps;
+
+ _cap_debug("getting filename capabilities");
+
+ /* fill the capability sets via a system call */
+ sizeofcaps = getxattr(filename, XATTR_NAME_CAPS,
+ &rawvfscap, sizeof(rawvfscap));
+ if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
+ cap_free(result);
+ result = NULL;
+ } else {
+ result = _fcaps_load(&rawvfscap, result, sizeofcaps);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Get rootid as seen in the current user namespace for the file capability
+ * sets.
+ */
+
+uid_t cap_get_nsowner(cap_t cap_d)
+{
+ uid_t nsowner;
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&cap_d->mutex);
+ nsowner = cap_d->rootid;
+ _cap_mu_unlock(&cap_d->mutex);
+ return nsowner;
+}
+
+/*
+ * Set the capabilities of an open file, as specified by its file
+ * descriptor.
+ */
+
+int cap_set_fd(int fildes, cap_t cap_d)
+{
+ struct vfs_ns_cap_data rawvfscap;
+ int sizeofcaps;
+ struct stat buf;
+
+ if (fstat(fildes, &buf) != 0) {
+ _cap_debug("unable to stat file descriptor %d", fildes);
+ return -1;
+ }
+ if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
+ _cap_debug("file descriptor %d for non-regular file", fildes);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (cap_d == NULL) {
+ _cap_debug("deleting fildes capabilities");
+ return fremovexattr(fildes, XATTR_NAME_CAPS);
+ } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
+ return -1;
+ }
+
+ _cap_debug("setting fildes capabilities");
+
+ return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
+}
+
+/*
+ * Set the capabilities of a named file.
+ */
+
+int cap_set_file(const char *filename, cap_t cap_d)
+{
+ struct vfs_ns_cap_data rawvfscap;
+ int sizeofcaps;
+ struct stat buf;
+
+ if (lstat(filename, &buf) != 0) {
+ _cap_debug("unable to stat file [%s]", filename);
+ return -1;
+ }
+ if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
+ _cap_debug("file [%s] is not a regular file", filename);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (cap_d == NULL) {
+ _cap_debug("removing filename capabilities");
+ return removexattr(filename, XATTR_NAME_CAPS);
+ } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
+ return -1;
+ }
+
+ _cap_debug("setting filename capabilities");
+ return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
+}
+
+/*
+ * Set nsowner for the file capability set.
+ */
+int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
+{
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&cap_d->mutex);
+ cap_d->rootid = rootuid;
+ _cap_mu_unlock_return(&cap_d->mutex, 0);
+}
+
+#else /* ie. ndef VFS_CAP_U32 */
+
+cap_t cap_get_fd(int fildes)
+{
+ errno = EINVAL;
+ return NULL;
+}
+
+cap_t cap_get_file(const char *filename)
+{
+ errno = EINVAL;
+ return NULL;
+}
+
+uid_t cap_get_nsowner(cap_t cap_d)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int cap_set_fd(int fildes, cap_t cap_d)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int cap_set_file(const char *filename, cap_t cap_d)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+#endif /* def VFS_CAP_U32 */
diff --git a/depends/libcap/libcap/cap_flag.c b/depends/libcap/libcap/cap_flag.c
new file mode 100644
index 0000000..94afd1e
--- /dev/null
+++ b/depends/libcap/libcap/cap_flag.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 1997-8,2008,20-21 Andrew G. Morgan <morgan@kernel.org>
+ *
+ * This file deals with flipping of capabilities on internal
+ * capability sets as specified by POSIX.1e (formerlly, POSIX 6).
+ *
+ * It also contains similar code for bit flipping cap_iab_t values.
+ */
+
+#include "libcap.h"
+
+/*
+ * Return the state of a specified capability flag. The state is
+ * returned as the contents of *raised. The capability is from one of
+ * the sets stored in cap_d as specified by set and value
+ */
+int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set,
+ cap_flag_value_t *raised)
+{
+ /*
+ * Do we have a set and a place to store its value?
+ * Is it a known capability?
+ */
+
+ if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_MAXBITS
+ && set >= 0 && set < NUMBER_OF_CAP_SETS) {
+ _cap_mu_lock(&cap_d->mutex);
+ *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR;
+ _cap_mu_unlock(&cap_d->mutex);
+ return 0;
+ } else {
+ _cap_debug("invalid arguments");
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+/*
+ * raise/lower a selection of capabilities
+ */
+
+int cap_set_flag(cap_t cap_d, cap_flag_t set,
+ int no_values, const cap_value_t *array_values,
+ cap_flag_value_t raise)
+{
+ /*
+ * Do we have a set and a place to store its value?
+ * Is it a known capability?
+ */
+
+ if (good_cap_t(cap_d) && no_values > 0 && no_values < __CAP_MAXBITS
+ && (set >= 0) && (set < NUMBER_OF_CAP_SETS)
+ && (raise == CAP_SET || raise == CAP_CLEAR) ) {
+ int i;
+ _cap_mu_lock(&cap_d->mutex);
+ for (i=0; i<no_values; ++i) {
+ if (array_values[i] < 0 || array_values[i] >= __CAP_MAXBITS) {
+ _cap_debug("weird capability (%d) - skipped", array_values[i]);
+ } else {
+ int value = array_values[i];
+
+ if (raise == CAP_SET) {
+ cap_d->raise_cap(value,set);
+ } else {
+ cap_d->lower_cap(value,set);
+ }
+ }
+ }
+ _cap_mu_unlock(&cap_d->mutex);
+ return 0;
+ } else {
+ _cap_debug("invalid arguments");
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+/*
+ * Reset the capability to be empty (nothing raised)
+ */
+
+int cap_clear(cap_t cap_d)
+{
+ if (good_cap_t(cap_d)) {
+ _cap_mu_lock(&cap_d->mutex);
+ memset(&(cap_d->u), 0, sizeof(cap_d->u));
+ _cap_mu_unlock(&cap_d->mutex);
+ return 0;
+ } else {
+ _cap_debug("invalid pointer");
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+/*
+ * Reset the all of the capability bits for one of the flag sets
+ */
+
+int cap_clear_flag(cap_t cap_d, cap_flag_t flag)
+{
+ switch (flag) {
+ case CAP_EFFECTIVE:
+ case CAP_PERMITTED:
+ case CAP_INHERITABLE:
+ if (good_cap_t(cap_d)) {
+ unsigned i;
+
+ _cap_mu_lock(&cap_d->mutex);
+ for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
+ cap_d->u[i].flat[flag] = 0;
+ }
+ _cap_mu_unlock(&cap_d->mutex);
+ return 0;
+ }
+ /*
+ * fall through
+ */
+
+ default:
+ _cap_debug("invalid pointer");
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+/*
+ * Compare two capability sets
+ */
+int cap_compare(cap_t a, cap_t b)
+{
+ unsigned i;
+ int result;
+
+ if (!(good_cap_t(a) && good_cap_t(b))) {
+ _cap_debug("invalid arguments");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * To avoid a deadlock corner case, we operate on an unlocked
+ * private copy of b
+ */
+ b = cap_dup(b);
+ if (b == NULL) {
+ return -1;
+ }
+ _cap_mu_lock(&a->mutex);
+ for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) {
+ result |=
+ ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE])
+ ? LIBCAP_EFF : 0)
+ | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE])
+ ? LIBCAP_INH : 0)
+ | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED])
+ ? LIBCAP_PER : 0);
+ }
+ _cap_mu_unlock(&a->mutex);
+ cap_free(b);
+ return result;
+}
+
+/*
+ * cap_fill_flag copies a bit-vector of capability state in one cap_t from one
+ * flag to another flag of another cap_t.
+ */
+int cap_fill_flag(cap_t cap_d, cap_flag_t to, cap_t ref, cap_flag_t from)
+{
+ int i;
+ cap_t orig;
+
+ if (!good_cap_t(cap_d) || !good_cap_t(ref)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (to < CAP_EFFECTIVE || to > CAP_INHERITABLE ||
+ from < CAP_EFFECTIVE || from > CAP_INHERITABLE) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ orig = cap_dup(ref);
+ if (orig == NULL) {
+ return -1;
+ }
+
+ _cap_mu_lock(&cap_d->mutex);
+ for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
+ cap_d->u[i].flat[to] = orig->u[i].flat[from];
+ }
+ _cap_mu_unlock(&cap_d->mutex);
+
+ cap_free(orig);
+ return 0;
+}
+
+/*
+ * cap_fill copies a bit-vector of capability state in a cap_t from
+ * one flag to another.
+ */
+int cap_fill(cap_t cap_d, cap_flag_t to, cap_flag_t from)
+{
+ return cap_fill_flag(cap_d, to, cap_d, from);
+}
+
+/*
+ * cap_iab_get_vector reads the single bit value from an IAB vector set.
+ */
+cap_flag_value_t cap_iab_get_vector(cap_iab_t iab, cap_iab_vector_t vec,
+ cap_value_t bit)
+{
+ if (!good_cap_iab_t(iab) || bit >= cap_max_bits()) {
+ return 0;
+ }
+
+ unsigned o = (bit >> 5);
+ __u32 mask = 1u << (bit & 31);
+ cap_flag_value_t ret;
+
+ _cap_mu_lock(&iab->mutex);
+ switch (vec) {
+ case CAP_IAB_INH:
+ ret = !!(iab->i[o] & mask);
+ break;
+ case CAP_IAB_AMB:
+ ret = !!(iab->a[o] & mask);
+ break;
+ case CAP_IAB_BOUND:
+ ret = !!(iab->nb[o] & mask);
+ break;
+ default:
+ ret = 0;
+ }
+ _cap_mu_unlock(&iab->mutex);
+
+ return ret;
+}
+
+/*
+ * cap_iab_set_vector sets the bits in an IAB to the value
+ * raised. Note, setting A implies setting I too, lowering I implies
+ * lowering A too. The B bits are, however, independently settable.
+ */
+int cap_iab_set_vector(cap_iab_t iab, cap_iab_vector_t vec, cap_value_t bit,
+ cap_flag_value_t raised)
+{
+ if (!good_cap_iab_t(iab) || (raised >> 1) || bit >= cap_max_bits()) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ unsigned o = (bit >> 5);
+ __u32 on = 1u << (bit & 31);
+ __u32 mask = ~on;
+
+ _cap_mu_lock(&iab->mutex);
+ switch (vec) {
+ case CAP_IAB_INH:
+ iab->i[o] = (iab->i[o] & mask) | (raised ? on : 0);
+ iab->a[o] &= iab->i[o];
+ break;
+ case CAP_IAB_AMB:
+ iab->a[o] = (iab->a[o] & mask) | (raised ? on : 0);
+ iab->i[o] |= iab->a[o];
+ break;
+ case CAP_IAB_BOUND:
+ iab->nb[o] = (iab->nb[o] & mask) | (raised ? on : 0);
+ break;
+ default:
+ errno = EINVAL;
+ _cap_mu_unlock_return(&iab->mutex, -1);
+ }
+
+ _cap_mu_unlock(&iab->mutex);
+ return 0;
+}
+
+/*
+ * cap_iab_fill copies a bit-vector of capability state from a cap_t
+ * to a cap_iab_t. Note, because the bounding bits in an iab are to be
+ * dropped when applied, the copying process, when to a CAP_IAB_BOUND
+ * vector involves inverting the bits. Also, adjusting I will mask
+ * bits in A, and adjusting A may implicitly raise bits in I.
+ */
+int cap_iab_fill(cap_iab_t iab, cap_iab_vector_t vec,
+ cap_t cap_d, cap_flag_t flag)
+{
+ int i, ret = 0;
+
+ if (!good_cap_t(cap_d) || !good_cap_iab_t(iab)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch (flag) {
+ case CAP_EFFECTIVE:
+ case CAP_INHERITABLE:
+ case CAP_PERMITTED:
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Make a private copy so we don't need to hold two locks at once
+ * avoiding a recipe for a deadlock.
+ */
+ cap_d = cap_dup(cap_d);
+ if (cap_d == NULL) {
+ return -1;
+ }
+
+ _cap_mu_lock(&iab->mutex);
+ for (i = 0; !ret && i < _LIBCAP_CAPABILITY_U32S; i++) {
+ switch (vec) {
+ case CAP_IAB_INH:
+ iab->i[i] = cap_d->u[i].flat[flag];
+ iab->a[i] &= iab->i[i];
+ break;
+ case CAP_IAB_AMB:
+ iab->a[i] = cap_d->u[i].flat[flag];
+ iab->i[i] |= cap_d->u[i].flat[flag];
+ break;
+ case CAP_IAB_BOUND:
+ iab->nb[i] = ~cap_d->u[i].flat[flag];
+ break;
+ default:
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ }
+ _cap_mu_unlock(&iab->mutex);
+
+ cap_free(cap_d);
+ return ret;
+}
+
+/*
+ * cap_iab_compare compares two iab tuples.
+ */
+int cap_iab_compare(cap_iab_t a, cap_iab_t b)
+{
+ int j, result;
+ if (!(good_cap_iab_t(a) && good_cap_iab_t(b))) {
+ _cap_debug("invalid arguments");
+ errno = EINVAL;
+ return -1;
+ }
+ b = cap_iab_dup(b);
+ if (b == NULL) {
+ return -1;
+ }
+
+ _cap_mu_lock(&a->mutex);
+ for (j=0, result=0; j<_LIBCAP_CAPABILITY_U32S; j++) {
+ result |=
+ (a->i[j] == b->i[j] ? 0 : (1 << CAP_IAB_INH)) |
+ (a->a[j] == b->a[j] ? 0 : (1 << CAP_IAB_AMB)) |
+ (a->nb[j] == b->nb[j] ? 0 : (1 << CAP_IAB_BOUND));
+ }
+ _cap_mu_unlock(&a->mutex);
+ cap_free(b);
+
+ return result;
+}
diff --git a/depends/libcap/libcap/cap_names.header b/depends/libcap/libcap/cap_names.header
new file mode 100644
index 0000000..8d64f64
--- /dev/null
+++ b/depends/libcap/libcap/cap_names.header
@@ -0,0 +1,5 @@
+struct __cap_token_s { const char *name; int index; };
+%{
+const struct __cap_token_s *__cap_lookup_name(const char *, size_t);
+%}
+%%
diff --git a/depends/libcap/libcap/cap_proc.c b/depends/libcap/libcap/cap_proc.c
new file mode 100644
index 0000000..24bc274
--- /dev/null
+++ b/depends/libcap/libcap/cap_proc.c
@@ -0,0 +1,1122 @@
+/*
+ * Copyright (c) 1997-8,2007,11,19-21 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file deals with getting and setting capabilities on processes.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <errno.h>
+#include <fcntl.h> /* Obtain O_* constant definitions */
+#include <grp.h>
+#include <sys/prctl.h>
+#include <sys/securebits.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "libcap.h"
+
+/*
+ * libcap uses this abstraction for all system calls that change
+ * kernel managed capability state. This permits the user to redirect
+ * it for testing and also to better implement posix semantics when
+ * using pthreads.
+ */
+
+static long int _cap_syscall3(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3)
+{
+ return syscall(syscall_nr, arg1, arg2, arg3);
+}
+
+static long int _cap_syscall6(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5, long int arg6)
+{
+ return syscall(syscall_nr, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+/*
+ * to keep the structure of the code conceptually similar in C and Go
+ * implementations, we introduce this abstraction for invoking state
+ * writing system calls. In psx+pthreaded code, the fork
+ * implementation provided by nptl ensures that we can consistently
+ * use the multithreaded syscalls even in the child after a fork().
+ */
+struct syscaller_s {
+ long int (*three)(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3);
+ long int (*six)(long int syscall_nr,
+ long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5, long int arg6);
+};
+
+/* use this syscaller for multi-threaded code */
+static struct syscaller_s multithread = {
+ .three = _cap_syscall3,
+ .six = _cap_syscall6
+};
+
+/* use this syscaller for single-threaded code */
+static struct syscaller_s singlethread = {
+ .three = _cap_syscall3,
+ .six = _cap_syscall6
+};
+
+/*
+ * This gets reset to 0 if we are *not* linked with libpsx.
+ */
+static int _libcap_overrode_syscalls = 1;
+
+/*
+ * 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.
+ * As can be seen here this present function is mostly a
+ * no-op. However, if libpsx is linked, the one present in that
+ * library (not being weak) will replace this one and the
+ * _libcap_overrode_syscalls value isn't forced to zero.
+ *
+ * Note: we hardcode the prototype for the psx_load_syscalls()
+ * function here so the compiler isn't worried. If we force the build
+ * to include the header, we are close to requiring the optional
+ * libpsx to be linked.
+ */
+void psx_load_syscalls(long int (**syscall_fn)(long int,
+ long int, long int, long int),
+ long int (**syscall6_fn)(long int,
+ long int, long int, long int,
+ long int, long int, long int));
+
+__attribute__((weak))
+void psx_load_syscalls(long int (**syscall_fn)(long int,
+ long int, long int, long int),
+ long int (**syscall6_fn)(long int,
+ long int, long int, long int,
+ long int, long int, long int))
+{
+ _libcap_overrode_syscalls = 0;
+}
+
+/*
+ * cap_set_syscall overrides the state setting syscalls that libcap does.
+ * Generally, you don't need to call this manually: libcap tries hard to
+ * set things up appropriately.
+ */
+void cap_set_syscall(long int (*new_syscall)(long int,
+ long int, long int, long int),
+ long int (*new_syscall6)(long int, long int,
+ long int, long int,
+ long int, long int,
+ long int)) {
+ if (new_syscall == NULL) {
+ psx_load_syscalls(&multithread.three, &multithread.six);
+ } else {
+ multithread.three = new_syscall;
+ multithread.six = new_syscall6;
+ }
+}
+
+static int _libcap_capset(struct syscaller_s *sc,
+ cap_user_header_t header, const cap_user_data_t data)
+{
+ if (_libcap_overrode_syscalls) {
+ return sc->three(SYS_capset, (long int) header, (long int) data, 0);
+ }
+ return capset(header, data);
+}
+
+static int _libcap_wprctl3(struct syscaller_s *sc,
+ long int pr_cmd, long int arg1, long int arg2)
+{
+ if (_libcap_overrode_syscalls) {
+ int result;
+ result = sc->three(SYS_prctl, pr_cmd, arg1, arg2);
+ if (result >= 0) {
+ return result;
+ }
+ errno = -result;
+ return -1;
+ }
+ return prctl(pr_cmd, arg1, arg2, 0, 0, 0);
+}
+
+static int _libcap_wprctl6(struct syscaller_s *sc,
+ long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5)
+{
+ if (_libcap_overrode_syscalls) {
+ int result;
+ result = sc->six(SYS_prctl, pr_cmd, arg1, arg2, arg3, arg4, arg5);
+ if (result >= 0) {
+ return result;
+ }
+ errno = -result;
+ return -1;
+ }
+ return prctl(pr_cmd, arg1, arg2, arg3, arg4, arg5);
+}
+
+/*
+ * cap_get_proc obtains the capability set for the current process.
+ */
+cap_t cap_get_proc(void)
+{
+ cap_t result;
+
+ /* allocate a new capability set */
+ result = cap_init();
+ if (result) {
+ _cap_debug("getting current process' capabilities");
+
+ /* fill the capability sets via a system call */
+ if (capget(&result->head, &result->u[0].set)) {
+ cap_free(result);
+ result = NULL;
+ }
+ }
+
+ return result;
+}
+
+static int _cap_set_proc(struct syscaller_s *sc, cap_t cap_d) {
+ int retval;
+
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ _cap_debug("setting process capabilities");
+ _cap_mu_lock(&cap_d->mutex);
+ retval = _libcap_capset(sc, &cap_d->head, &cap_d->u[0].set);
+ _cap_mu_unlock(&cap_d->mutex);
+
+ return retval;
+}
+
+int cap_set_proc(cap_t cap_d)
+{
+ return _cap_set_proc(&multithread, cap_d);
+}
+
+/* the following two functions are not required by POSIX */
+
+/* read the caps on a specific process */
+
+int capgetp(pid_t pid, cap_t cap_d)
+{
+ int error;
+
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ _cap_debug("getting process capabilities for proc %d", pid);
+
+ _cap_mu_lock(&cap_d->mutex);
+ cap_d->head.pid = pid;
+ error = capget(&cap_d->head, &cap_d->u[0].set);
+ cap_d->head.pid = 0;
+ _cap_mu_unlock(&cap_d->mutex);
+
+ return error;
+}
+
+/* allocate space for and return capabilities of target process */
+
+cap_t cap_get_pid(pid_t pid)
+{
+ cap_t result;
+
+ result = cap_init();
+ if (result) {
+ if (capgetp(pid, result) != 0) {
+ int my_errno;
+
+ my_errno = errno;
+ cap_free(result);
+ errno = my_errno;
+ result = NULL;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * set the caps on a specific process/pg etc.. The kernel has long
+ * since deprecated this asynchronous interface. DON'T EXPECT THIS TO
+ * EVER WORK AGAIN.
+ */
+
+int capsetp(pid_t pid, cap_t cap_d)
+{
+ int error;
+
+ if (!good_cap_t(cap_d)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ _cap_debug("setting process capabilities for proc %d", pid);
+ _cap_mu_lock(&cap_d->mutex);
+ cap_d->head.pid = pid;
+ error = capset(&cap_d->head, &cap_d->u[0].set);
+ cap_d->head.version = _LIBCAP_CAPABILITY_VERSION;
+ cap_d->head.pid = 0;
+ _cap_mu_unlock(&cap_d->mutex);
+
+ return error;
+}
+
+/* the kernel api requires unsigned long arguments */
+#define pr_arg(x) ((unsigned long) x)
+
+/* get a capability from the bounding set */
+
+int cap_get_bound(cap_value_t cap)
+{
+ return prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0));
+}
+
+static int _cap_drop_bound(struct syscaller_s *sc, cap_value_t cap)
+{
+ return _libcap_wprctl3(sc, PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0));
+}
+
+/* drop a capability from the bounding set */
+
+int cap_drop_bound(cap_value_t cap) {
+ return _cap_drop_bound(&multithread, cap);
+}
+
+/* get a capability from the ambient set */
+
+int cap_get_ambient(cap_value_t cap)
+{
+ int result;
+ result = prctl(PR_CAP_AMBIENT, pr_arg(PR_CAP_AMBIENT_IS_SET),
+ pr_arg(cap), pr_arg(0), pr_arg(0));
+ if (result < 0) {
+ errno = -result;
+ return -1;
+ }
+ return result;
+}
+
+static int _cap_set_ambient(struct syscaller_s *sc,
+ cap_value_t cap, cap_flag_value_t set)
+{
+ int val;
+ switch (set) {
+ case CAP_SET:
+ val = PR_CAP_AMBIENT_RAISE;
+ break;
+ case CAP_CLEAR:
+ val = PR_CAP_AMBIENT_LOWER;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ return _libcap_wprctl6(sc, PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
+ pr_arg(0), pr_arg(0), pr_arg(0));
+}
+
+/*
+ * cap_set_ambient modifies a single ambient capability value.
+ */
+int cap_set_ambient(cap_value_t cap, cap_flag_value_t set)
+{
+ return _cap_set_ambient(&multithread, cap, set);
+}
+
+static int _cap_reset_ambient(struct syscaller_s *sc)
+{
+ int olderrno = errno;
+ cap_value_t c;
+ int result = 0;
+
+ for (c = 0; !result; c++) {
+ result = cap_get_ambient(c);
+ if (result == -1) {
+ errno = olderrno;
+ return 0;
+ }
+ }
+
+ return _libcap_wprctl6(sc, PR_CAP_AMBIENT,
+ pr_arg(PR_CAP_AMBIENT_CLEAR_ALL),
+ pr_arg(0), pr_arg(0), pr_arg(0), pr_arg(0));
+}
+
+/*
+ * cap_reset_ambient erases all ambient capabilities - this reads the
+ * ambient caps before performing the erase to workaround the corner
+ * case where the set is empty already but the ambient cap API is
+ * locked.
+ */
+int cap_reset_ambient(void)
+{
+ return _cap_reset_ambient(&multithread);
+}
+
+/*
+ * Read the security mode of the current process.
+ */
+unsigned cap_get_secbits(void)
+{
+ return (unsigned) prctl(PR_GET_SECUREBITS, pr_arg(0), pr_arg(0));
+}
+
+static int _cap_set_secbits(struct syscaller_s *sc, unsigned bits)
+{
+ return _libcap_wprctl3(sc, PR_SET_SECUREBITS, bits, 0);
+}
+
+/*
+ * Set the secbits of the current process.
+ */
+int cap_set_secbits(unsigned bits)
+{
+ return _cap_set_secbits(&multithread, bits);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * cap_prctl performs a prctl() 6 argument call on the current
+ * thread. Use cap_prctlw() if you want to perform a POSIX semantics
+ * prctl() system call.
+ */
+int cap_prctl(long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5)
+{
+ return prctl(pr_cmd, arg1, arg2, arg3, arg4, arg5);
+}
+
+/*
+ * cap_prctlw performs a POSIX semantics prctl() call. That is a 6 arg
+ * prctl() call that executes on all available threads when libpsx is
+ * linked. The suffix 'w' refers to the fact one only ever needs to
+ * invoke this is if the call will write some kernel state.
+ */
+int cap_prctlw(long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5)
+{
+ return _libcap_wprctl6(&multithread, pr_cmd, arg1, arg2, arg3, arg4, arg5);
+}
+
+/*
+ * Some predefined constants
+ */
+#define CAP_SECURED_BITS_BASIC \
+ (SECBIT_NOROOT | SECBIT_NOROOT_LOCKED | \
+ SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED | \
+ SECBIT_KEEP_CAPS_LOCKED)
+
+#define CAP_SECURED_BITS_AMBIENT (CAP_SECURED_BITS_BASIC | \
+ SECBIT_NO_CAP_AMBIENT_RAISE | SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED)
+
+static cap_value_t raise_cap_setpcap[] = {CAP_SETPCAP};
+
+static int _cap_set_mode(struct syscaller_s *sc, cap_mode_t flavor)
+{
+ int ret;
+ unsigned secbits = CAP_SECURED_BITS_AMBIENT;
+ cap_t working = cap_get_proc();
+
+ if (working == NULL) {
+ _cap_debug("getting current process' capabilities failed");
+ return -1;
+ }
+
+ ret = cap_set_flag(working, CAP_EFFECTIVE, 1, raise_cap_setpcap, CAP_SET) |
+ _cap_set_proc(sc, working);
+ if (ret == 0) {
+ cap_flag_t c;
+
+ switch (flavor) {
+ case CAP_MODE_NOPRIV:
+ /* fall through */
+ case CAP_MODE_PURE1E_INIT:
+ (void) cap_clear_flag(working, CAP_INHERITABLE);
+ /* fall through */
+ case CAP_MODE_PURE1E:
+ if (!CAP_AMBIENT_SUPPORTED()) {
+ secbits = CAP_SECURED_BITS_BASIC;
+ } else {
+ ret = _cap_reset_ambient(sc);
+ if (ret) {
+ break; /* ambient dropping failed */
+ }
+ }
+ ret = _cap_set_secbits(sc, secbits);
+ if (flavor != CAP_MODE_NOPRIV) {
+ break;
+ }
+
+ /* just for "case CAP_MODE_NOPRIV:" */
+
+ for (c = 0; cap_get_bound(c) >= 0; c++) {
+ (void) _cap_drop_bound(sc, c);
+ }
+ (void) cap_clear_flag(working, CAP_PERMITTED);
+
+ /* for good measure */
+ _cap_set_no_new_privs(sc);
+ break;
+ case CAP_MODE_HYBRID:
+ ret = _cap_set_secbits(sc, 0);
+ break;
+ default:
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ }
+
+ (void) cap_clear_flag(working, CAP_EFFECTIVE);
+ ret = _cap_set_proc(sc, working) | ret;
+ (void) cap_free(working);
+ return ret;
+}
+
+/*
+ * cap_set_mode locks the overarching capability framework of the
+ * present process and thus its children to a predefined flavor. Once
+ * 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
+ * at least the CAP_EFFECTIVE flags for the current process.
+ */
+int cap_set_mode(cap_mode_t flavor)
+{
+ return _cap_set_mode(&multithread, flavor);
+}
+
+/*
+ * cap_get_mode attempts to determine what the current capability mode
+ * is. If it can find no match in the libcap pre-defined modes, it
+ * returns CAP_MODE_UNCERTAIN.
+ */
+cap_mode_t cap_get_mode(void)
+{
+ unsigned secbits = cap_get_secbits();
+
+ if (secbits == 0) {
+ return CAP_MODE_HYBRID;
+ }
+ if ((secbits & CAP_SECURED_BITS_BASIC) != CAP_SECURED_BITS_BASIC) {
+ return CAP_MODE_UNCERTAIN;
+ }
+
+ /* validate ambient is not set */
+ int olderrno = errno;
+ int ret = 0, cf;
+ cap_value_t c;
+ for (c = 0; !ret; c++) {
+ ret = cap_get_ambient(c);
+ if (ret == -1) {
+ errno = olderrno;
+ if (c && secbits != CAP_SECURED_BITS_AMBIENT) {
+ return CAP_MODE_UNCERTAIN;
+ }
+ ret = 0;
+ break;
+ }
+ if (ret) {
+ return CAP_MODE_UNCERTAIN;
+ }
+ }
+
+ /*
+ * Explore how capabilities differ from empty.
+ */
+ cap_t working = cap_get_proc();
+ cap_t empty = cap_init();
+ if (working == NULL || empty == NULL) {
+ _cap_debug("working=%p, empty=%p - need both non-NULL", working, empty);
+ ret = -1;
+ } else {
+ cf = cap_compare(empty, working);
+ }
+ cap_free(empty);
+ cap_free(working);
+ if (ret != 0) {
+ return CAP_MODE_UNCERTAIN;
+ }
+
+ if (CAP_DIFFERS(cf, CAP_INHERITABLE)) {
+ return CAP_MODE_PURE1E;
+ }
+ if (CAP_DIFFERS(cf, CAP_PERMITTED) || CAP_DIFFERS(cf, CAP_EFFECTIVE)) {
+ return CAP_MODE_PURE1E_INIT;
+ }
+
+ for (c = 0; ; c++) {
+ int v = cap_get_bound(c);
+ if (v == -1) {
+ break;
+ }
+ if (v) {
+ return CAP_MODE_PURE1E_INIT;
+ }
+ }
+
+ return CAP_MODE_NOPRIV;
+}
+
+static int _cap_setuid(struct syscaller_s *sc, uid_t uid)
+{
+ const cap_value_t raise_cap_setuid[] = {CAP_SETUID};
+ cap_t working = cap_get_proc();
+ if (working == NULL) {
+ return -1;
+ }
+
+ (void) cap_set_flag(working, CAP_EFFECTIVE,
+ 1, raise_cap_setuid, CAP_SET);
+ /*
+ * Note, we are cognizant of not using glibc's setuid in the case
+ * that we've modified the way libcap is doing setting
+ * syscalls. This is because prctl needs to be working in a POSIX
+ * compliant way for the code below to work, so we are either
+ * all-broken or not-broken and don't allow for "sort of working".
+ */
+ (void) _libcap_wprctl3(sc, PR_SET_KEEPCAPS, 1, 0);
+ int ret = _cap_set_proc(sc, working);
+ if (ret == 0) {
+ if (_libcap_overrode_syscalls) {
+ ret = sc->three(SYS_setuid, (long int) uid, 0, 0);
+ if (ret < 0) {
+ errno = -ret;
+ ret = -1;
+ }
+ } else {
+ ret = setuid(uid);
+ }
+ }
+ int olderrno = errno;
+ (void) _libcap_wprctl3(sc, PR_SET_KEEPCAPS, 0, 0);
+ (void) cap_clear_flag(working, CAP_EFFECTIVE);
+ (void) _cap_set_proc(sc, working);
+ (void) cap_free(working);
+
+ errno = olderrno;
+ return ret;
+}
+
+/*
+ * cap_setuid attempts to set the uid of the process without dropping
+ * any permitted capabilities in the process. A side effect of a call
+ * to this function is that the effective set will be cleared by the
+ * time the function returns.
+ */
+int cap_setuid(uid_t uid)
+{
+ return _cap_setuid(&multithread, uid);
+}
+
+#if defined(__arm__) || defined(__i386__) || \
+ defined(__i486__) || defined(__i586__) || defined(__i686__)
+#define sys_setgroups_variant SYS_setgroups32
+#else
+#define sys_setgroups_variant SYS_setgroups
+#endif
+
+static int _cap_setgroups(struct syscaller_s *sc,
+ gid_t gid, size_t ngroups, const gid_t groups[])
+{
+ const cap_value_t raise_cap_setgid[] = {CAP_SETGID};
+ cap_t working = cap_get_proc();
+ if (working == NULL) {
+ return -1;
+ }
+
+ (void) cap_set_flag(working, CAP_EFFECTIVE,
+ 1, raise_cap_setgid, CAP_SET);
+ /*
+ * Note, we are cognizant of not using glibc's setgid etc in the
+ * case that we've modified the way libcap is doing setting
+ * syscalls. This is because prctl needs to be working in a POSIX
+ * compliant way for the other functions of this file so we are
+ * all-broken or not-broken and don't allow for "sort of working".
+ */
+ int ret = _cap_set_proc(sc, working);
+ if (_libcap_overrode_syscalls) {
+ if (ret == 0) {
+ ret = sc->three(SYS_setgid, (long int) gid, 0, 0);
+ }
+ if (ret == 0) {
+ ret = sc->three(sys_setgroups_variant, (long int) ngroups,
+ (long int) groups, 0);
+ }
+ if (ret < 0) {
+ errno = -ret;
+ ret = -1;
+ }
+ } else {
+ if (ret == 0) {
+ ret = setgid(gid);
+ }
+ if (ret == 0) {
+ ret = setgroups(ngroups, groups);
+ }
+ }
+ int olderrno = errno;
+
+ (void) cap_clear_flag(working, CAP_EFFECTIVE);
+ (void) _cap_set_proc(sc, working);
+ (void) cap_free(working);
+
+ errno = olderrno;
+ return ret;
+}
+
+/*
+ * cap_setgroups combines setting the gid with changing the set of
+ * supplemental groups for a user into one call that raises the needed
+ * capabilities to do it for the duration of the call. A side effect
+ * of a call to this function is that the effective set will be
+ * cleared by the time the function returns.
+ */
+int cap_setgroups(gid_t gid, size_t ngroups, const gid_t groups[])
+{
+ return _cap_setgroups(&multithread, gid, ngroups, groups);
+}
+
+/*
+ * cap_iab_get_proc returns a cap_iab_t value initialized by the
+ * current process state related to these iab bits.
+ */
+cap_iab_t cap_iab_get_proc(void)
+{
+ cap_iab_t iab;
+ cap_t current;
+
+ iab = cap_iab_init();
+ if (iab == NULL) {
+ _cap_debug("no memory for IAB tuple");
+ return NULL;
+ }
+
+ current = cap_get_proc();
+ if (current == NULL) {
+ _cap_debug("no memory for cap_t");
+ cap_free(iab);
+ return NULL;
+ }
+
+ cap_iab_fill(iab, CAP_IAB_INH, current, CAP_INHERITABLE);
+ cap_free(current);
+
+ cap_value_t c;
+ for (c = cap_max_bits(); c; ) {
+ --c;
+ int o = c >> 5;
+ __u32 mask = 1U << (c & 31);
+ if (cap_get_bound(c) == 0) {
+ iab->nb[o] |= mask;
+ }
+ if (cap_get_ambient(c) == 1) {
+ iab->a[o] |= mask;
+ }
+ }
+ return iab;
+}
+
+/*
+ * _cap_iab_set_proc sets the iab collection using the requested syscaller.
+ * The iab value is locked by the caller.
+ */
+static int _cap_iab_set_proc(struct syscaller_s *sc, cap_iab_t iab)
+{
+ int ret, i, raising = 0;
+ cap_value_t c;
+ cap_t working, temp = cap_get_proc();
+
+ if (temp == NULL) {
+ return -1;
+ }
+
+ for (i = 0; i < _LIBCAP_CAPABILITY_U32S; i++) {
+ __u32 newI = iab->i[i];
+ __u32 oldIP = temp->u[i].flat[CAP_INHERITABLE] |
+ temp->u[i].flat[CAP_PERMITTED];
+ raising |= (newI & ~oldIP) | iab->a[i] | iab->nb[i];
+ temp->u[i].flat[CAP_INHERITABLE] = newI;
+
+ }
+
+ working = cap_dup(temp);
+ if (working == NULL) {
+ ret = -1;
+ goto defer;
+ }
+ if (raising) {
+ ret = cap_set_flag(working, CAP_EFFECTIVE,
+ 1, raise_cap_setpcap, CAP_SET);
+ if (ret) {
+ goto defer;
+ }
+ }
+ if ((ret = _cap_set_proc(sc, working))) {
+ goto defer;
+ }
+ if ((ret = _cap_reset_ambient(sc))) {
+ goto done;
+ }
+
+ for (c = cap_max_bits(); c-- != 0; ) {
+ unsigned offset = c >> 5;
+ __u32 mask = 1U << (c & 31);
+ if (iab->a[offset] & mask) {
+ ret = _cap_set_ambient(sc, c, CAP_SET);
+ if (ret) {
+ goto done;
+ }
+ }
+ if (iab->nb[offset] & mask) {
+ /* drop the bounding bit */
+ ret = _cap_drop_bound(sc, c);
+ if (ret) {
+ goto done;
+ }
+ }
+ }
+
+done:
+ (void) cap_set_proc(temp);
+
+defer:
+ cap_free(working);
+ cap_free(temp);
+
+ return ret;
+}
+
+/*
+ * cap_iab_set_proc sets the iab capability vectors of the current
+ * process.
+ */
+int cap_iab_set_proc(cap_iab_t iab)
+{
+ int retval;
+ if (!good_cap_iab_t(iab)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&iab->mutex);
+ retval = _cap_iab_set_proc(&multithread, iab);
+ _cap_mu_unlock(&iab->mutex);
+ return retval;
+}
+
+/*
+ * cap_launcher_callback primes the launcher with a callback that will
+ * be invoked after the fork() but before any privilege has changed
+ * and before the execve(). This can be used to augment the state of
+ * the child process within the cap_launch() process. You can cancel
+ * any callback associated with a launcher by calling this function
+ * with a callback_fn value NULL.
+ *
+ * If the callback function returns anything other than 0, it is
+ * considered to have failed and the launch will be aborted - further,
+ * errno will be communicated to the parent.
+ */
+int cap_launcher_callback(cap_launch_t attr, int (callback_fn)(void *detail))
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+ attr->custom_setup_fn = callback_fn;
+ _cap_mu_unlock(&attr->mutex);
+ return 0;
+}
+
+/*
+ * cap_launcher_setuid primes the launcher to attempt a change of uid.
+ */
+int cap_launcher_setuid(cap_launch_t attr, uid_t uid)
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+ attr->uid = uid;
+ attr->change_uids = 1;
+ _cap_mu_unlock(&attr->mutex);
+ return 0;
+}
+
+/*
+ * cap_launcher_setgroups primes the launcher to attempt a change of
+ * gid and groups.
+ */
+int cap_launcher_setgroups(cap_launch_t attr, gid_t gid,
+ int ngroups, const gid_t *groups)
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+ attr->gid = gid;
+ attr->ngroups = ngroups;
+ attr->groups = groups;
+ attr->change_gids = 1;
+ _cap_mu_unlock(&attr->mutex);
+ return 0;
+}
+
+/*
+ * cap_launcher_set_mode primes the launcher to attempt a change of
+ * mode.
+ */
+int cap_launcher_set_mode(cap_launch_t attr, cap_mode_t flavor)
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+ attr->mode = flavor;
+ attr->change_mode = 1;
+ _cap_mu_unlock(&attr->mutex);
+ return 0;
+}
+
+/*
+ * cap_launcher_set_iab primes the launcher to attempt to change the
+ * IAB values of the launched child. The launcher locks iab while it
+ * is owned by the launcher: this prevents the user from
+ * asynchronously changing its value while it is associated with the
+ * launcher.
+ */
+cap_iab_t cap_launcher_set_iab(cap_launch_t attr, cap_iab_t iab)
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ _cap_mu_lock(&attr->mutex);
+ cap_iab_t old = attr->iab;
+ attr->iab = iab;
+ if (old != NULL) {
+ _cap_mu_unlock(&old->mutex);
+ }
+ if (iab != NULL) {
+ _cap_mu_lock(&iab->mutex);
+ }
+ _cap_mu_unlock(&attr->mutex);
+ return old;
+}
+
+/*
+ * cap_launcher_set_chroot sets the intended chroot for the launched
+ * child.
+ */
+int cap_launcher_set_chroot(cap_launch_t attr, const char *chroot)
+{
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+ attr->chroot = _libcap_strdup(chroot);
+ _cap_mu_unlock(&attr->mutex);
+ return 0;
+}
+
+static int _cap_chroot(struct syscaller_s *sc, const char *root)
+{
+ const cap_value_t raise_cap_sys_chroot[] = {CAP_SYS_CHROOT};
+ cap_t working = cap_get_proc();
+ if (working == NULL) {
+ return -1;
+ }
+
+ (void) cap_set_flag(working, CAP_EFFECTIVE,
+ 1, raise_cap_sys_chroot, CAP_SET);
+ int ret = _cap_set_proc(sc, working);
+ if (ret == 0) {
+ if (_libcap_overrode_syscalls) {
+ ret = sc->three(SYS_chroot, (long int) root, 0, 0);
+ if (ret < 0) {
+ errno = -ret;
+ ret = -1;
+ }
+ } else {
+ ret = chroot(root);
+ }
+ if (ret == 0) {
+ ret = chdir("/");
+ }
+ }
+ int olderrno = errno;
+ (void) cap_clear_flag(working, CAP_EFFECTIVE);
+ (void) _cap_set_proc(sc, working);
+ (void) cap_free(working);
+
+ errno = olderrno;
+ return ret;
+}
+
+/*
+ * _cap_launch is invoked in the forked child, it cannot return but is
+ * required to exit, if the execve fails. It will write the errno
+ * value for any failure over the filedescriptor, fd, and exit with
+ * status 1.
+ */
+__attribute__ ((noreturn))
+static void _cap_launch(int fd, cap_launch_t attr, void *detail) {
+ struct syscaller_s *sc = &singlethread;
+ int my_errno;
+
+ if (attr->custom_setup_fn && attr->custom_setup_fn(detail)) {
+ goto defer;
+ }
+ if (attr->arg0 == NULL) {
+ /* handle the successful cap_func_launcher completion */
+ exit(0);
+ }
+
+ if (attr->change_uids && _cap_setuid(sc, attr->uid)) {
+ goto defer;
+ }
+ if (attr->change_gids &&
+ _cap_setgroups(sc, attr->gid, attr->ngroups, attr->groups)) {
+ goto defer;
+ }
+ if (attr->change_mode && _cap_set_mode(sc, attr->mode)) {
+ goto defer;
+ }
+ if (attr->iab && _cap_iab_set_proc(sc, attr->iab)) {
+ goto defer;
+ }
+ if (attr->chroot != NULL && _cap_chroot(sc, attr->chroot)) {
+ goto defer;
+ }
+
+ /*
+ * Some type wrangling to work around what the kernel API really
+ * means: not "const char **".
+ */
+ const void *temp_args = attr->argv;
+ const void *temp_envp = attr->envp;
+
+ execve(attr->arg0, temp_args, temp_envp);
+ /* if the exec worked, execution will not reach here */
+
+defer:
+ /*
+ * getting here means an error has occurred and errno is
+ * communicated to the parent
+ */
+ my_errno = errno;
+ for (;;) {
+ int n = write(fd, &my_errno, sizeof(my_errno));
+ if (n < 0 && errno == EAGAIN) {
+ continue;
+ }
+ break;
+ }
+ close(fd);
+ exit(1);
+}
+
+/*
+ * cap_launch performs a wrapped fork+(callback and/or exec) that
+ * works in both an unthreaded environment and also where libcap is
+ * linked with psx+pthreads. The function supports dropping privilege
+ * in the forked thread, but retaining privilege in the parent
+ * thread(s).
+ *
+ * When applying the IAB vector inside the fork, since the ambient set
+ * is fragile with respect to changes in I or P, the function
+ * carefully orders setting of these inheritable characteristics, to
+ * make sure they stick.
+ *
+ * This function will return an error of -1 setting errno if the
+ * launch failed.
+ */
+pid_t cap_launch(cap_launch_t attr, void *detail) {
+ int my_errno;
+ int ps[2];
+ pid_t child;
+
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+ _cap_mu_lock(&attr->mutex);
+
+ /* The launch must have a purpose */
+ if (attr->custom_setup_fn == NULL &&
+ (attr->arg0 == NULL || attr->argv == NULL)) {
+ errno = EINVAL;
+ _cap_mu_unlock_return(&attr->mutex, -1);
+ }
+
+ if (pipe2(ps, O_CLOEXEC) != 0) {
+ _cap_mu_unlock_return(&attr->mutex, -1);
+ }
+
+ child = fork();
+ my_errno = errno;
+
+ if (!child) {
+ close(ps[0]);
+ prctl(PR_SET_NAME, "cap-launcher", 0, 0, 0);
+ _cap_launch(ps[1], attr, detail);
+ /* no return from above function */
+ }
+
+ /* child has its own copy, and parent no longer needs it locked. */
+ _cap_mu_unlock(&attr->mutex);
+ close(ps[1]);
+ if (child < 0) {
+ goto defer;
+ }
+
+ /*
+ * Extend this function's return codes to include setup failures
+ * in the child.
+ */
+ for (;;) {
+ int ignored;
+ int n = read(ps[0], &my_errno, sizeof(my_errno));
+ if (n == 0) {
+ goto defer;
+ }
+ if (n < 0 && errno == EAGAIN) {
+ continue;
+ }
+ waitpid(child, &ignored, 0);
+ child = -1;
+ my_errno = ECHILD;
+ break;
+ }
+
+defer:
+ close(ps[0]);
+ errno = my_errno;
+ return child;
+}
diff --git a/depends/libcap/libcap/cap_test.c b/depends/libcap/libcap/cap_test.c
new file mode 100644
index 0000000..68b6a13
--- /dev/null
+++ b/depends/libcap/libcap/cap_test.c
@@ -0,0 +1,299 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "libcap.h"
+
+static cap_value_t top;
+
+static int cf(cap_value_t x)
+{
+ return top - x - 1;
+}
+
+static int test_cap_bits(void)
+{
+ static cap_value_t vs[] = {
+ 5, 6, 11, 12, 15, 16, 17, 38, 41, 63, 64, __CAP_MAXBITS+3, 0, -1
+ };
+ int failed = 0;
+ cap_value_t i;
+ for (i = 0; vs[i] >= 0; i++) {
+ cap_value_t ans;
+
+ top = vs[i];
+ _binary_search(ans, cf, 0, __CAP_MAXBITS, -1);
+ if (ans != top) {
+ if (top == 0 && ans == -1) {
+ continue;
+ }
+ if (top > __CAP_MAXBITS && ans == -1) {
+ continue;
+ }
+ printf("test_cap_bits miscompared [%d] top=%d - got=%d\n",
+ i, top, ans);
+ failed = -1;
+ }
+ }
+ return failed;
+}
+
+static int test_cap_flags(void)
+{
+ cap_t c, d;
+ cap_flag_t f = CAP_INHERITABLE, t;
+ cap_value_t v;
+ int retval = 0;
+
+ c = cap_init();
+ if (c == NULL) {
+ printf("test_flags failed to allocate a set\n");
+ return -1;
+ }
+ if (cap_compare(c, NULL) != -1) {
+ printf("compare to NULL should give invalid\n");
+ return -1;
+ }
+ if (cap_compare(NULL, c) != -1) {
+ printf("compare with NULL should give invalid\n");
+ return -1;
+ }
+
+ for (v = 0; v < __CAP_MAXBITS; v += 3) {
+ if (cap_set_flag(c, CAP_INHERITABLE, 1, &v, CAP_SET)) {
+ printf("unable to set inheritable bit %d\n", v);
+ retval = -1;
+ goto drop_c;
+ }
+ }
+
+ d = cap_dup(c);
+ for (t = CAP_EFFECTIVE; t <= CAP_INHERITABLE; t++) {
+ if (cap_fill(c, t, f)) {
+ printf("cap_fill failed %d -> %d\n", f, t);
+ retval = -1;
+ goto drop_d;
+ }
+ if (cap_clear_flag(c, f)) {
+ printf("cap_fill unable to clear flag %d\n", f);
+ retval = -1;
+ goto drop_d;
+ }
+ f = t;
+ }
+ if (cap_compare(c, d)) {
+ printf("permuted cap_fill()ing failed to perform net no-op\n");
+ retval = -1;
+ }
+ if (cap_fill_flag(NULL, CAP_EFFECTIVE, c, CAP_INHERITABLE) == 0) {
+ printf("filling NULL flag should fail\n");
+ retval = -1;
+ }
+ if (cap_fill_flag(d, CAP_PERMITTED, c, CAP_INHERITABLE) != 0) {
+ perror("filling PERMITEED flag should work");
+ retval = -1;
+ }
+ if (cap_fill_flag(c, CAP_PERMITTED, d, CAP_PERMITTED) != 0) {
+ perror("filling PERMITTED flag from another cap_t should work");
+ retval = -1;
+ }
+ if (cap_compare(c, d)) {
+ printf("permuted cap_fill()ing failed to perform net no-op\n");
+ retval = -1;
+ }
+
+drop_d:
+ if (cap_free(d) != 0) {
+ perror("failed to free d");
+ retval = -1;
+ }
+drop_c:
+ if (cap_free(c) != 0) {
+ perror("failed to free c");
+ retval = -1;
+ }
+ return retval;
+}
+
+static int test_short_bits(void)
+{
+ int result = 0;
+ char *tmp;
+ int n = asprintf(&tmp, "%d", __CAP_MAXBITS);
+ if (n <= 0) {
+ return -1;
+ }
+ if (strlen(tmp) > __CAP_NAME_SIZE) {
+ printf("cap_to_text buffer size reservation needs fixing (%ld > %d)\n",
+ (long int)strlen(tmp), __CAP_NAME_SIZE);
+ result = -1;
+ }
+ free(tmp);
+ return result;
+}
+
+static int noop(void *data)
+{
+ return -1;
+}
+
+static int test_alloc(void)
+{
+ int retval = 0;
+ cap_t c;
+ cap_iab_t iab;
+ cap_launch_t launcher;
+ char *old_root;
+
+ printf("test_alloc\n");
+ fflush(stdout);
+
+ c = cap_init();
+ if (c == NULL) {
+ perror("failed to allocate a cap_t");
+ fflush(stderr);
+ return -1;
+ }
+
+ iab = cap_iab_init();
+ if (iab == NULL) {
+ perror("failed to allocate a cap_iab_t");
+ fflush(stderr);
+ retval = -1;
+ goto drop_c;
+ }
+
+ launcher = cap_func_launcher(noop);
+ if (launcher == NULL) {
+ perror("failde to allocate a launcher");
+ fflush(stderr);
+ retval = -1;
+ goto drop_iab;
+ }
+
+ cap_launcher_set_chroot(launcher, "/tmp");
+ if (cap_launcher_set_iab(launcher, iab) != NULL) {
+ printf("unable to replace iab in launcher\n");
+ fflush(stdout);
+ retval = -1;
+ goto drop_iab;
+ }
+
+ iab = cap_launcher_set_iab(launcher, cap_iab_init());
+ if (iab == NULL) {
+ printf("unable to recover iab in launcher\n");
+ fflush(stdout);
+ retval = -1;
+ goto drop_launcher;
+ }
+
+ old_root = cap_proc_root("blah");
+ if (old_root != NULL) {
+ printf("bad initial proc_root [%s]\n", old_root);
+ fflush(stdout);
+ retval = -1;
+ }
+ if (cap_free(old_root)) {
+ perror("unable to free old proc root");
+ fflush(stderr);
+ retval = -1;
+ }
+ if (retval) {
+ goto drop_launcher;
+ }
+ old_root = cap_proc_root("/proc");
+ if (strcmp(old_root, "blah") != 0) {
+ printf("bad proc_root value [%s]\n", old_root);
+ fflush(stdout);
+ retval = -1;
+ }
+ if (cap_free(old_root)) {
+ perror("unable to free replacement proc root");
+ fflush(stderr);
+ retval = -1;
+ }
+ if (retval) {
+ goto drop_launcher;
+ }
+
+drop_launcher:
+ printf("test_alloc: drop_launcher\n");
+ fflush(stdout);
+ if (cap_free(launcher)) {
+ perror("failed to free launcher");
+ fflush(stderr);
+ retval = -1;
+ }
+
+drop_iab:
+ printf("test_alloc: drop_iab\n");
+ fflush(stdout);
+ if (!cap_free(2+(__u32 *) iab)) {
+ printf("unable to recognize bad cap_iab_t pointer\n");
+ fflush(stdout);
+ retval = -1;
+ }
+ if (cap_free(iab)) {
+ perror("failed to free iab");
+ fflush(stderr);
+ retval = -1;
+ }
+
+drop_c:
+ printf("test_alloc: drop_cap\n");
+ fflush(stdout);
+ if (!cap_free(1+(__u32 *) c)) {
+ printf("unable to recognize bad cap_t pointer\n");
+ fflush(stdout);
+ retval = -1;
+ }
+ if (cap_free(c)) {
+ perror("failed to free c");
+ fflush(stderr);
+ retval = -1;
+ }
+ return retval;
+}
+
+static int test_prctl(void)
+{
+ int ret, retval=0;
+ errno = 0;
+ ret = cap_get_bound((cap_value_t) -1);
+ if (ret != -1) {
+ printf("cap_get_bound(-1) did not return error: %d\n", ret);
+ retval = -1;
+ } else if (errno != EINVAL) {
+ perror("cap_get_bound(-1) errno != EINVAL");
+ retval = -1;
+ }
+ return retval;
+}
+
+int main(int argc, char **argv) {
+ int result = 0;
+
+ printf("test_cap_bits: being called\n");
+ fflush(stdout);
+ result = test_cap_bits() | result;
+ printf("test_cap_flags: being called\n");
+ fflush(stdout);
+ result = test_cap_flags() | result;
+ printf("test_short_bits: being called\n");
+ fflush(stdout);
+ result = test_short_bits() | result;
+ printf("test_alloc: being called\n");
+ fflush(stdout);
+ result = test_alloc() | result;
+ printf("test_prctl: being called\n");
+ fflush(stdout);
+ result = test_prctl() | result;
+ printf("tested\n");
+ fflush(stdout);
+
+ if (result) {
+ printf("cap_test FAILED\n");
+ exit(1);
+ }
+ printf("cap_test PASS\n");
+ exit(0);
+}
diff --git a/depends/libcap/libcap/cap_text.c b/depends/libcap/libcap/cap_text.c
new file mode 100644
index 0000000..7566bd8
--- /dev/null
+++ b/depends/libcap/libcap/cap_text.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright (c) 1997-8,2007-8,2019,2021 Andrew G Morgan <morgan@kernel.org>
+ * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk>
+ *
+ * This file deals with exchanging internal and textual
+ * representations of capability sets.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+
+#define LIBCAP_PLEASE_INCLUDE_ARRAY
+#include "libcap.h"
+
+static char const *_cap_names[__CAP_BITS] = LIBCAP_CAP_NAMES;
+
+#include <ctype.h>
+#include <limits.h>
+
+#ifdef INCLUDE_GPERF_OUTPUT
+/* we need to include it after #define _GNU_SOURCE is set */
+#include INCLUDE_GPERF_OUTPUT
+#endif
+
+/* Maximum output text length */
+#define CAP_TEXT_SIZE (__CAP_NAME_SIZE * __CAP_MAXBITS)
+
+/*
+ * Parse a textual representation of capabilities, returning an internal
+ * representation.
+ */
+
+#define raise_cap_mask(flat, c) (flat)[CAP_TO_INDEX(c)] |= CAP_TO_MASK(c)
+
+static void setbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks)
+{
+ int n;
+ for (n = blks; n--; ) {
+ a->u[n].flat[set] |= b[n];
+ }
+}
+
+static void clrbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks)
+{
+ int n;
+ for (n = blks; n--; )
+ a->u[n].flat[set] &= ~b[n];
+}
+
+static char const *namcmp(char const *str, char const *nam)
+{
+ while (*nam && tolower((unsigned char)*str) == *nam) {
+ str++;
+ nam++;
+ }
+ if (*nam || isalnum((unsigned char)*str) || *str == '_')
+ return NULL;
+ return str;
+}
+
+/*
+ * forceall forces all of the kernel named capabilities to be assigned
+ * the masked value, and zeroed otherwise. Note, if the kernel is ahead
+ * of libcap, the upper bits will be referred to by number.
+ */
+static void forceall(__u32 *flat, __u32 value, unsigned blks)
+{
+ unsigned n;
+ cap_value_t cmb = cap_max_bits();
+ for (n = blks; n--; ) {
+ unsigned base = 32*n;
+ __u32 mask = 0;
+ if (cmb >= base + 32) {
+ mask = ~0;
+ } else if (cmb > base) {
+ mask = (unsigned) ((1ULL << (cmb % 32)) - 1);
+ }
+ flat[n] = value & mask;
+ }
+
+ return;
+}
+
+static int lookupname(char const **strp)
+{
+ union {
+ char const *constp;
+ char *p;
+ } str;
+
+ str.constp = *strp;
+ if (isdigit(*str.constp)) {
+ unsigned long n = strtoul(str.constp, &str.p, 0);
+ if (n >= __CAP_MAXBITS)
+ return -1;
+ *strp = str.constp;
+ return n;
+ } else {
+ int c;
+ size_t len;
+
+ for (len=0; (c = str.constp[len]); ++len) {
+ if (!(isalpha(c) || (c == '_'))) {
+ break;
+ }
+ }
+
+#ifdef GPERF_DOWNCASE
+ const struct __cap_token_s *token_info;
+
+ token_info = __cap_lookup_name(str.constp, len);
+ if (token_info != NULL) {
+ *strp = str.constp + len;
+ return token_info->index;
+ }
+#else /* ie., ndef GPERF_DOWNCASE */
+ char const *s;
+ unsigned n = cap_max_bits();
+ if (n > __CAP_BITS) {
+ n = __CAP_BITS;
+ }
+ while (n--) {
+ if (_cap_names[n] && (s = namcmp(str.constp, _cap_names[n]))) {
+ *strp = s;
+ return n;
+ }
+ }
+#endif /* def GPERF_DOWNCASE */
+
+ return -1; /* No definition available */
+ }
+}
+
+cap_t cap_from_text(const char *str)
+{
+ cap_t res;
+ int n;
+ unsigned cap_blks;
+
+ if (str == NULL) {
+ _cap_debug("bad argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (!(res = cap_init()))
+ return NULL;
+
+ switch (res->head.version) {
+ case _LINUX_CAPABILITY_VERSION_1:
+ cap_blks = _LINUX_CAPABILITY_U32S_1;
+ break;
+ case _LINUX_CAPABILITY_VERSION_2:
+ cap_blks = _LINUX_CAPABILITY_U32S_2;
+ break;
+ case _LINUX_CAPABILITY_VERSION_3:
+ cap_blks = _LINUX_CAPABILITY_U32S_3;
+ break;
+ default:
+ cap_free(res);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ _cap_debug("%s", str);
+
+ for (;;) {
+ __u32 list[__CAP_BLKS];
+ char op;
+ int flags = 0, listed=0;
+
+ memset(list, 0, sizeof(__u32)*__CAP_BLKS);
+
+ /* skip leading spaces */
+ while (isspace((unsigned char)*str))
+ str++;
+ if (!*str) {
+ _cap_debugcap("e = ", *res, CAP_EFFECTIVE);
+ _cap_debugcap("i = ", *res, CAP_INHERITABLE);
+ _cap_debugcap("p = ", *res, CAP_PERMITTED);
+
+ return res;
+ }
+
+ /* identify caps specified by this clause */
+ if (isalnum((unsigned char)*str) || *str == '_') {
+ for (;;) {
+ if (namcmp(str, "all")) {
+ str += 3;
+ forceall(list, ~0, cap_blks);
+ } else {
+ n = lookupname(&str);
+ if (n == -1)
+ goto bad;
+ raise_cap_mask(list, n);
+ }
+ if (*str != ',')
+ break;
+ if (!isalnum((unsigned char)*++str) && *str != '_')
+ goto bad;
+ }
+ listed = 1;
+ } else if (*str == '+' || *str == '-') {
+ goto bad; /* require a list of capabilities */
+ } else {
+ forceall(list, ~0, cap_blks);
+ }
+
+ /* identify first operation on list of capabilities */
+ op = *str++;
+ if (op == '=' && (*str == '+' || *str == '-')) {
+ if (!listed)
+ goto bad;
+ op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */
+ } else if (op != '+' && op != '-' && op != '=')
+ goto bad;
+
+ /* cycle through list of actions */
+ do {
+ _cap_debug("next char = '%c'", *str);
+ if (*str && !isspace(*str)) {
+ switch (*str++) { /* Effective, Inheritable, Permitted */
+ case 'e':
+ flags |= LIBCAP_EFF;
+ break;
+ case 'i':
+ flags |= LIBCAP_INH;
+ break;
+ case 'p':
+ flags |= LIBCAP_PER;
+ break;
+ default:
+ goto bad;
+ }
+ } else if (op != '=') {
+ _cap_debug("only '=' can be followed by space");
+ goto bad;
+ }
+
+ _cap_debug("how to read?");
+ switch (op) { /* how do we interpret the caps? */
+ case '=':
+ case 'P': /* =+ */
+ case 'M': /* =- */
+ clrbits(res, list, CAP_EFFECTIVE, cap_blks);
+ clrbits(res, list, CAP_PERMITTED, cap_blks);
+ clrbits(res, list, CAP_INHERITABLE, cap_blks);
+ if (op == 'M')
+ goto minus;
+ /* fall through */
+ case '+':
+ if (flags & LIBCAP_EFF)
+ setbits(res, list, CAP_EFFECTIVE, cap_blks);
+ if (flags & LIBCAP_PER)
+ setbits(res, list, CAP_PERMITTED, cap_blks);
+ if (flags & LIBCAP_INH)
+ setbits(res, list, CAP_INHERITABLE, cap_blks);
+ break;
+ case '-':
+ minus:
+ if (flags & LIBCAP_EFF)
+ clrbits(res, list, CAP_EFFECTIVE, cap_blks);
+ if (flags & LIBCAP_PER)
+ clrbits(res, list, CAP_PERMITTED, cap_blks);
+ if (flags & LIBCAP_INH)
+ clrbits(res, list, CAP_INHERITABLE, cap_blks);
+ break;
+ }
+
+ /* new directive? */
+ if (*str == '+' || *str == '-') {
+ if (!listed) {
+ _cap_debug("for + & - must list capabilities");
+ goto bad;
+ }
+ flags = 0; /* reset the flags */
+ op = *str++;
+ if (!isalpha(*str))
+ goto bad;
+ }
+ } while (*str && !isspace(*str));
+ _cap_debug("next clause");
+ }
+
+bad:
+ cap_free(res);
+ res = NULL;
+ errno = EINVAL;
+ return res;
+}
+
+/*
+ * lookup a capability name and return its numerical value
+ */
+int cap_from_name(const char *name, cap_value_t *value_p)
+{
+ int n;
+
+ if (((n = lookupname(&name)) >= 0) && (value_p != NULL)) {
+ *value_p = (unsigned) n;
+ }
+ return -(n < 0);
+}
+
+/*
+ * Convert a single capability index number into a string representation
+ */
+char *cap_to_name(cap_value_t cap)
+{
+ char *tmp, *result;
+
+ if ((cap >= 0) && (cap < __CAP_BITS)) {
+ return _libcap_strdup(_cap_names[cap]);
+ }
+ if (asprintf(&tmp, "%u", cap) <= 0) {
+ _cap_debug("asprintf filed");
+ return NULL;
+ }
+
+ result = _libcap_strdup(tmp);
+ free(tmp);
+ return result;
+}
+
+/*
+ * Convert an internal representation to a textual one. The textual
+ * representation is stored in static memory. It will be overwritten
+ * on the next occasion that this function is called.
+ */
+
+static int getstateflags(cap_t caps, int capno)
+{
+ int f = 0;
+
+ if (isset_cap(caps, capno, CAP_EFFECTIVE)) {
+ f |= LIBCAP_EFF;
+ }
+ if (isset_cap(caps, capno, CAP_PERMITTED)) {
+ f |= LIBCAP_PER;
+ }
+ if (isset_cap(caps, capno, CAP_INHERITABLE)) {
+ f |= LIBCAP_INH;
+ }
+
+ return f;
+}
+
+/*
+ * This code assumes that the longest named capability is longer than
+ * the decimal text representation of __CAP_MAXBITS. This is very true
+ * at the time of writing and likely to remain so. However, we have
+ * a test in cap_text to validate it at build time.
+ */
+#define CAP_TEXT_BUFFER_ZONE 100
+
+char *cap_to_text(cap_t caps, ssize_t *length_p)
+{
+ char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
+ char *p, *base;
+ int histo[8];
+ int m, t;
+ unsigned n;
+
+ /* Check arguments */
+ if (!good_cap_t(caps)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ _cap_debugcap("e = ", *caps, CAP_EFFECTIVE);
+ _cap_debugcap("i = ", *caps, CAP_INHERITABLE);
+ _cap_debugcap("p = ", *caps, CAP_PERMITTED);
+
+ memset(histo, 0, sizeof(histo));
+
+ /* default prevailing state to the named bits */
+ cap_value_t cmb = cap_max_bits();
+ for (n = 0; n < cmb; n++)
+ histo[getstateflags(caps, n)]++;
+
+ /* find which combination of capability sets shares the most bits
+ we bias to preferring non-set (m=0) with the >= 0 test. Failing
+ to do this causes strange things to happen with older systems
+ that don't know about bits 32+. */
+ for (m=t=7; t--; )
+ if (histo[t] >= histo[m])
+ 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" : "",
+ (m & LIBCAP_PER) ? "p" : "" ) + buf;
+
+ for (t = 8; t--; ) {
+ if (t == m || !histo[t]) {
+ continue;
+ }
+ *p++ = ' ';
+ for (n = 0; n < cmb; n++) {
+ if (getstateflags(caps, n) == t) {
+ char *this_cap_name = cap_to_name(n);
+ if (this_cap_name == NULL) {
+ return NULL;
+ }
+ if ((strlen(this_cap_name) + (p - buf)) > CAP_TEXT_SIZE) {
+ cap_free(this_cap_name);
+ errno = ERANGE;
+ return NULL;
+ }
+ p += sprintf(p, "%s,", this_cap_name);
+ cap_free(this_cap_name);
+ }
+ }
+ p--;
+ n = t & ~m;
+ if (n) {
+ 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" : "");
+ }
+ n = ~t & m;
+ if (n) {
+ p += sprintf(p, "-%s%s%s",
+ (n & LIBCAP_EFF) ? "e" : "",
+ (n & LIBCAP_INH) ? "i" : "",
+ (n & LIBCAP_PER) ? "p" : "");
+ }
+ if (p - buf > CAP_TEXT_SIZE) {
+ errno = ERANGE;
+ return NULL;
+ }
+ }
+
+ /* capture remaining unnamed bits - which must all be +. */
+ memset(histo, 0, sizeof(histo));
+ for (n = cmb; n < __CAP_MAXBITS; n++)
+ histo[getstateflags(caps, n)]++;
+
+ for (t = 8; t-- > 1; ) {
+ if (!histo[t]) {
+ continue;
+ }
+ *p++ = ' ';
+ for (n = cmb; n < __CAP_MAXBITS; n++) {
+ if (getstateflags(caps, n) == t) {
+ char *this_cap_name = cap_to_name(n);
+ if (this_cap_name == NULL) {
+ return NULL;
+ }
+ if ((strlen(this_cap_name) + (p - buf)) > CAP_TEXT_SIZE) {
+ cap_free(this_cap_name);
+ errno = ERANGE;
+ return NULL;
+ }
+ p += sprintf(p, "%s,", this_cap_name);
+ cap_free(this_cap_name);
+ }
+ }
+ p--;
+ p += sprintf(p, "+%s%s%s",
+ (t & LIBCAP_EFF) ? "e" : "",
+ (t & LIBCAP_INH) ? "i" : "",
+ (t & LIBCAP_PER) ? "p" : "");
+ if (p - buf > CAP_TEXT_SIZE) {
+ errno = ERANGE;
+ return NULL;
+ }
+ }
+
+ _cap_debug("%s", base);
+ if (length_p) {
+ *length_p = p - base;
+ }
+
+ return (_libcap_strdup(base));
+}
+
+/*
+ * cap_mode_name returns a text token naming the specified mode.
+ */
+const char *cap_mode_name(cap_mode_t flavor) {
+ switch (flavor) {
+ case CAP_MODE_NOPRIV:
+ return "NOPRIV";
+ case CAP_MODE_PURE1E_INIT:
+ return "PURE1E_INIT";
+ case CAP_MODE_PURE1E:
+ return "PURE1E";
+ case CAP_MODE_UNCERTAIN:
+ return "UNCERTAIN";
+ case CAP_MODE_HYBRID:
+ return "HYBRID";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/*
+ * cap_iab_to_text serializes an iab into a canonical text
+ * representation.
+ */
+char *cap_iab_to_text(cap_iab_t iab)
+{
+ char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
+ char *p = buf;
+ cap_value_t c, cmb = cap_max_bits();
+ int first = 1;
+
+ if (good_cap_iab_t(iab)) {
+ _cap_mu_lock(&iab->mutex);
+ for (c = 0; c < cmb; c++) {
+ int keep = 0;
+ int o = c >> 5;
+ __u32 bit = 1U << (c & 31);
+ __u32 ib = iab->i[o] & bit;
+ __u32 ab = iab->a[o] & bit;
+ __u32 nbb = iab->nb[o] & bit;
+ if (!(nbb | ab | ib)) {
+ continue;
+ }
+ if (!first) {
+ *p++ = ',';
+ }
+ if (nbb) {
+ *p++ = '!';
+ keep = 1;
+ }
+ if (ab) {
+ *p++ = '^';
+ keep = 1;
+ } else if (nbb && ib) {
+ *p++ = '%';
+ }
+ if (keep || ib) {
+ if (c < __CAP_BITS) {
+ strcpy(p, _cap_names[c]);
+ } else {
+ sprintf(p, "%u", c);
+ }
+ p += strlen(p);
+ first = 0;
+ }
+ }
+ _cap_mu_unlock(&iab->mutex);
+ }
+ *p = '\0';
+ return _libcap_strdup(buf);
+}
+
+cap_iab_t cap_iab_from_text(const char *text)
+{
+ cap_iab_t iab = cap_iab_init();
+ if (iab == NULL) {
+ return iab;
+ }
+ if (text != NULL) {
+ unsigned flags;
+ for (flags = 0; *text; text++) {
+ /* consume prefixes */
+ switch (*text) {
+ case '!':
+ flags |= LIBCAP_IAB_NB_FLAG;
+ continue;
+ case '^':
+ flags |= LIBCAP_IAB_IA_FLAG;
+ continue;
+ case '%':
+ flags |= LIBCAP_IAB_I_FLAG;
+ continue;
+ default:
+ break;
+ }
+ if (!flags) {
+ flags = LIBCAP_IAB_I_FLAG;
+ }
+
+ /* consume cap name */
+ cap_value_t c = lookupname(&text);
+ if (c == -1) {
+ goto cleanup;
+ }
+ unsigned o = c >> 5;
+ __u32 mask = 1U << (c & 31);
+ if (flags & LIBCAP_IAB_I_FLAG) {
+ iab->i[o] |= mask;
+ }
+ if (flags & LIBCAP_IAB_A_FLAG) {
+ iab->a[o] |= mask;
+ }
+ if (flags & LIBCAP_IAB_NB_FLAG) {
+ iab->nb[o] |= mask;
+ }
+
+ /* rest should be end or comma */
+ if (*text == '\0') {
+ break;
+ }
+ if (*text != ',') {
+ goto cleanup;
+ }
+ flags = 0;
+ }
+ }
+ return iab;
+
+cleanup:
+ cap_free(iab);
+ errno = EINVAL;
+ return NULL;
+}
+
+static __u32 _parse_hex32(const char *c)
+{
+ int i;
+ __u32 v = 0;
+ for (i=0; i < 8; i++, c++) {
+ v <<= 4;
+ if (*c == 0 || *c < '0') {
+ return 0;
+ } else if (*c <= '9') {
+ v += *c - '0';
+ } else if (*c > 'f') {
+ return 0;
+ } else if (*c >= 'a') {
+ v += *c + 10 - 'a';
+ } else if (*c < 'A') {
+ return 0;
+ } else if (*c <= 'F') {
+ v += *c + 10 - 'A';
+ } else {
+ return 0;
+ }
+ }
+ return v;
+}
+
+/*
+ * _parse_vec_string converts the hex dumps in /proc/<pid>/current into
+ * an array of u32s - masked as per the forceall() mask.
+ */
+static __u32 _parse_vec_string(__u32 *vals, const char *c, int invert)
+{
+ int i;
+ int words = strlen(c)/8;
+ if (words > _LIBCAP_CAPABILITY_U32S) {
+ return 0;
+ }
+ forceall(vals, ~0, words);
+ for (i = 0; i < words; i++) {
+ __u32 val = _parse_hex32(c+8*(words-1-i));
+ if (invert) {
+ val = ~val;
+ }
+ vals[i] &= val;
+ }
+ return ~0;
+}
+
+/*
+ * libcap believes this is the root of the mounted "/proc"
+ * filesystem. (NULL == "/proc".)
+ */
+static char *_cap_proc_dir;
+
+/*
+ * If the constructor is called (see cap_alloc.c) then we'll need the
+ * corresponding destructor.
+ */
+__attribute__((destructor (300))) static void _cleanup_libcap(void)
+{
+ if (_cap_proc_dir == NULL) {
+ return;
+ }
+ cap_free(_cap_proc_dir);
+ _cap_proc_dir = NULL;
+}
+
+/*
+ * cap_proc_root reads and (optionally: when root != NULL) changes
+ * libcap's notion of where the "/proc" filesystem is mounted. It
+ * defaults to the value "/proc". Note, this is a global value and not
+ * considered thread safe to write - so the client should take
+ * suitable care when changing it. Further, libcap will allocate
+ * memory for storing the replacement root, and it is this memory that
+ * is returned. So, when changing the value, the caller should
+ * cap_free(the-return-value) when done with it.
+ *
+ * A return value of NULL implies the default is in effect "/proc".
+ */
+char *cap_proc_root(const char *root)
+{
+ char *old = _cap_proc_dir;
+ if (root != NULL) {
+ _cap_proc_dir = _libcap_strdup(root);
+ }
+ return old;
+}
+
+#define PROC_LINE_MAX (8 + 8*_LIBCAP_CAPABILITY_U32S + 100)
+/*
+ * cap_iab_get_pid fills an IAB tuple from the content of
+ * /proc/<pid>/status. Linux doesn't support syscall access to the
+ * needed information, so we parse it out of that file.
+ */
+cap_iab_t cap_iab_get_pid(pid_t pid)
+{
+ cap_iab_t iab;
+ char *path;
+ FILE *file;
+ char line[PROC_LINE_MAX];
+ const char *proc_root = _cap_proc_dir;
+
+ if (proc_root == NULL) {
+ proc_root = "/proc";
+ }
+ if (asprintf(&path, "%s/%d/status", proc_root, pid) <= 0) {
+ return NULL;
+ }
+ file = fopen(path, "r");
+ free(path);
+ if (file == NULL) {
+ return NULL;
+ }
+
+ iab = cap_iab_init();
+ uint ok = 0;
+ if (iab != NULL) {
+ while (fgets(line, PROC_LINE_MAX-1, file) != NULL) {
+ if (strncmp("Cap", line, 3) != 0) {
+ continue;
+ }
+ if (strncmp("Inh:\t", line+3, 5) == 0) {
+ ok = (_parse_vec_string(iab->i, line+8, 0) &
+ LIBCAP_IAB_I_FLAG) | ok;
+ continue;
+ }
+ if (strncmp("Bnd:\t", line+3, 5) == 0) {
+ ok = (_parse_vec_string(iab->nb, line+8, 1) &
+ LIBCAP_IAB_NB_FLAG) | ok;
+ continue;
+ }
+ if (strncmp("Amb:\t", line+3, 5) == 0) {
+ ok = (_parse_vec_string(iab->a, line+8, 0) &
+ LIBCAP_IAB_A_FLAG) | ok;
+ continue;
+ }
+ }
+ }
+ if (ok != (LIBCAP_IAB_IA_FLAG | LIBCAP_IAB_NB_FLAG)) {
+ cap_free(iab);
+ iab = NULL;
+ }
+ fclose(file);
+ return iab;
+}
diff --git a/depends/libcap/libcap/empty.c b/depends/libcap/libcap/empty.c
new file mode 100644
index 0000000..0314ff1
--- /dev/null
+++ b/depends/libcap/libcap/empty.c
@@ -0,0 +1 @@
+int main(int argc, char **argv) { return 0; }
diff --git a/depends/libcap/libcap/execable.c b/depends/libcap/libcap/execable.c
new file mode 100644
index 0000000..9f7062e
--- /dev/null
+++ b/depends/libcap/libcap/execable.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/capability.h>
+
+#include "execable.h"
+
+static void usage(int status)
+{
+ printf("\nusage: libcap.so [--help|--usage|--summary]\n");
+ exit(status);
+}
+
+static void summary(void)
+{
+ cap_value_t bits = cap_max_bits(), c;
+ cap_mode_t mode = cap_get_mode();
+
+ printf("\nCurrent mode: %s\n", cap_mode_name(mode));
+ printf("Number of cap values known to: this libcap=%d, running kernel=%d\n",
+ CAP_LAST_CAP+1, bits);
+
+ if (bits > CAP_LAST_CAP+1) {
+ printf("=> Consider upgrading libcap to name:");
+ for (c = CAP_LAST_CAP+1; c < bits; c++) {
+ printf(" %d", c);
+ }
+ } else if (bits < CAP_LAST_CAP+1) {
+ printf("=> Newer kernels also provide support for:");
+ for (c = bits; c <= CAP_LAST_CAP; c++) {
+ char *name = cap_to_name(c);
+ printf(" %s", name);
+ cap_free(name);
+ }
+ } else {
+ return;
+ }
+ printf("\n");
+}
+
+SO_MAIN(int argc, char **argv)
+{
+ int i;
+ const char *cmd = "This library";
+
+ if (argv != NULL && argv[0] != NULL) {
+ cmd = argv[0];
+ }
+ printf("%s is the shared library version: " LIBRARY_VERSION ".\n"
+ "See the License file for distribution information.\n"
+ "More information on this library is available from:\n"
+ "\n"
+ " https://sites.google.com/site/fullycapable/\n", cmd);
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "--usage") || !strcmp(argv[i], "--help")) {
+ usage(0);
+ }
+ if (!strcmp(argv[i], "--summary")) {
+ summary();
+ continue;
+ }
+ usage(1);
+ }
+}
diff --git a/depends/libcap/libcap/execable.h b/depends/libcap/libcap/execable.h
new file mode 100644
index 0000000..7a2d247
--- /dev/null
+++ b/depends/libcap/libcap/execable.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021 Andrew G. Morgan <morgan@kernel.org>
+ *
+ * Some header magic to help make a shared object run-able as a stand
+ * alone executable binary.
+ *
+ * This is a slightly more sophisticated implementation than the
+ * answer I posted here:
+ *
+ * https://stackoverflow.com/a/68339111/14760867
+ *
+ * Compile your shared library with:
+ *
+ * -DSHARED_LOADER="\"ld-linux...\"" (loader for your target system)
+ * ...
+ * --entry=__so_start
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __EXECABLE_H
+#error "only include execable.h once"
+#endif
+#define __EXECABLE_H
+
+const char __execable_dl_loader[] __attribute((section(".interp"))) =
+ SHARED_LOADER ;
+
+static void __execable_parse_args(int *argc_p, char ***argv_p)
+{
+ int argc = 0;
+ char **argv = NULL;
+ FILE *f = fopen("/proc/self/cmdline", "rb");
+ if (f != NULL) {
+ char *mem = NULL, *p;
+ size_t size = 32, offset;
+ for (offset=0; ; size *= 2) {
+ char *new_mem = realloc(mem, size+1);
+ if (new_mem == NULL) {
+ perror("unable to parse arguments");
+ if (mem != NULL) {
+ free(mem);
+ }
+ exit(1);
+ }
+ mem = new_mem;
+ offset += fread(mem+offset, 1, size-offset, f);
+ if (offset < size) {
+ size = offset;
+ mem[size] = '\0';
+ break;
+ }
+ }
+ fclose(f);
+ for (argc=1, p=mem+size-2; p >= mem; p--) {
+ argc += (*p == '\0');
+ }
+ argv = calloc(argc+1, sizeof(char *));
+ if (argv == NULL) {
+ perror("failed to allocate memory for argv");
+ free(mem);
+ exit(1);
+ }
+ for (p=mem, argc=0, offset=0; offset < size; argc++) {
+ argv[argc] = mem+offset;
+ offset += strlen(mem+offset)+1;
+ }
+ }
+ *argc_p = argc;
+ *argv_p = argv;
+}
+
+/*
+ * Linux x86 ABI requires the stack be 16 byte aligned. Keep things
+ * simple and just force it.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+#define __SO_FORCE_ARG_ALIGNMENT __attribute__((force_align_arg_pointer))
+#else
+#define __SO_FORCE_ARG_ALIGNMENT
+#endif /* def some x86 */
+
+/*
+ * Permit the compiler to override this one.
+ */
+#ifndef EXECABLE_INITIALIZE
+#define EXECABLE_INITIALIZE do { } while(0)
+#endif /* ndef EXECABLE_INITIALIZE */
+
+/*
+ * Note, to avoid any runtime confusion, SO_MAIN is a void static
+ * function.
+ */
+#define SO_MAIN \
+static void __execable_main(int, char**); \
+__attribute__((visibility ("hidden"))) \
+void __so_start(void); \
+__SO_FORCE_ARG_ALIGNMENT \
+void __so_start(void) \
+{ \
+ int argc; \
+ char **argv; \
+ __execable_parse_args(&argc, &argv); \
+ EXECABLE_INITIALIZE; \
+ __execable_main(argc, argv); \
+ if (argc != 0) { \
+ free(argv[0]); \
+ free(argv); \
+ } \
+ exit(0); \
+} \
+static void __execable_main
diff --git a/depends/libcap/libcap/include/sys/.gitignore b/depends/libcap/libcap/include/sys/.gitignore
new file mode 100644
index 0000000..595fc39
--- /dev/null
+++ b/depends/libcap/libcap/include/sys/.gitignore
@@ -0,0 +1 @@
+psx_syscall.h
diff --git a/depends/libcap/libcap/include/sys/capability.h b/depends/libcap/libcap/include/sys/capability.h
new file mode 100644
index 0000000..2db9972
--- /dev/null
+++ b/depends/libcap/libcap/include/sys/capability.h
@@ -0,0 +1,255 @@
+/*
+ * <sys/capability.h>
+ *
+ * Copyright (C) 1997 Aleph One
+ * Copyright (C) 1997,8, 2008,19-22 Andrew G. Morgan <morgan@kernel.org>
+ *
+ * defunct POSIX.1e Standard: 25.2 Capabilities <sys/capability.h>
+ */
+
+#ifndef _SYS_CAPABILITY_H
+#define _SYS_CAPABILITY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Provide a programmatic way to #ifdef around features.
+ */
+#define LIBCAP_MAJOR 2
+#define LIBCAP_MINOR 69
+
+/*
+ * This file complements the kernel file by providing prototype
+ * information for the user library.
+ */
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#ifndef __user
+#define __user
+#endif
+#include <linux/capability.h>
+
+/*
+ * POSIX capability types
+ */
+
+/*
+ * Opaque capability handle (defined internally by libcap)
+ * internal capability representation
+ */
+typedef struct _cap_struct *cap_t;
+
+/* "external" capability representation is a (void *) */
+
+/*
+ * This is the type used to identify capabilities
+ */
+
+typedef int cap_value_t;
+
+/*
+ * libcap initialized first unnamed capability of the running kernel.
+ * capsh includes a runtime test to flag when this is larger than
+ * what is known to libcap... Time for a new libcap release!
+ */
+extern cap_value_t cap_max_bits(void);
+
+/*
+ * cap_proc_root reads and (optionally: when root != NULL) changes
+ * libcap's notion of where the "/proc" filesystem is mounted. When
+ * the return value is NULL, it should be interpreted as the
+ * value "/proc".
+ *
+ * Note, this is a global value and not considered thread safe to
+ * write - so the client should take suitable care when changing
+ * it.
+ *
+ * Further, libcap will allocate a memory copy for storing the
+ * replacement root, and it is this kind of memory that is returned.
+ * So, when changing the value, the caller should
+ * cap_free(the-return-value) else cause a memory leak.
+ *
+ * Note, the library uses a destructor to clean up the live allocated
+ * value of the working setting.
+ */
+extern char *cap_proc_root(const char *root);
+
+/*
+ * Set identifiers
+ */
+typedef enum {
+ CAP_EFFECTIVE = 0, /* Specifies the effective flag */
+ CAP_PERMITTED = 1, /* Specifies the permitted flag */
+ CAP_INHERITABLE = 2 /* Specifies the inheritable flag */
+} cap_flag_t;
+
+typedef enum {
+ CAP_IAB_INH = 2,
+ CAP_IAB_AMB = 3,
+ CAP_IAB_BOUND = 4
+} cap_iab_vector_t;
+
+/*
+ * An opaque generalization of the inheritable bits that includes both
+ * what ambient bits to raise and what bounding bits to *lower* (aka
+ * drop). None of these bits once set, using cap_iab_set(), affect
+ * the running process but are consulted, through the execve() system
+ * call, by the kernel. Note, the ambient bits ('A') of the running
+ * process are fragile with respect to other aspects of the "posix"
+ * (cap_t) operations: most importantly, 'A' cannot ever hold bits not
+ * present in the intersection of 'pI' and 'pP'. The kernel
+ * immediately drops all ambient caps whenever such a situation
+ * arises. Typically, the ambient bits are used to support a naive
+ * capability inheritance model - at odds with the POSIX (sic) model
+ * of inheritance where inherited (pI) capabilities need to also be
+ * wanted by the executed binary (fI) in order to become raised
+ * through exec.
+ */
+typedef struct cap_iab_s *cap_iab_t;
+
+/*
+ * These are the states available to each capability
+ */
+typedef enum {
+ CAP_CLEAR=0, /* The flag is cleared/disabled */
+ CAP_SET=1 /* The flag is set/enabled */
+} cap_flag_value_t;
+
+/*
+ * User-space capability manipulation routines
+ */
+typedef unsigned cap_mode_t;
+#define CAP_MODE_UNCERTAIN ((cap_mode_t) 0)
+#define CAP_MODE_NOPRIV ((cap_mode_t) 1)
+#define CAP_MODE_PURE1E_INIT ((cap_mode_t) 2)
+#define CAP_MODE_PURE1E ((cap_mode_t) 3)
+#define CAP_MODE_HYBRID ((cap_mode_t) 4)
+
+/* libcap/cap_alloc.c */
+extern cap_t cap_dup(cap_t);
+extern int cap_free(void *);
+extern cap_t cap_init(void);
+extern cap_iab_t cap_iab_dup(cap_iab_t);
+extern cap_iab_t cap_iab_init(void);
+
+/* libcap/cap_flag.c */
+extern int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *);
+extern int cap_set_flag(cap_t, cap_flag_t, int, const cap_value_t *,
+ cap_flag_value_t);
+extern int cap_clear(cap_t);
+extern int cap_clear_flag(cap_t, cap_flag_t);
+extern int cap_fill_flag(cap_t cap_d, cap_flag_t to,
+ cap_t ref, cap_flag_t from);
+extern int cap_fill(cap_t, cap_flag_t, cap_flag_t);
+
+#define CAP_DIFFERS(result, flag) (((result) & (1 << (flag))) != 0)
+extern int cap_compare(cap_t, cap_t);
+#define CAP_IAB_DIFFERS(result, vector) (((result) & (1 << (vector))) != 0)
+extern int cap_iab_compare(cap_iab_t, cap_iab_t);
+
+extern cap_flag_value_t cap_iab_get_vector(cap_iab_t, cap_iab_vector_t,
+ cap_value_t);
+extern int cap_iab_set_vector(cap_iab_t, cap_iab_vector_t, cap_value_t,
+ cap_flag_value_t);
+extern int cap_iab_fill(cap_iab_t, cap_iab_vector_t, cap_t, cap_flag_t);
+
+/* libcap/cap_file.c */
+extern cap_t cap_get_fd(int);
+extern cap_t cap_get_file(const char *);
+extern uid_t cap_get_nsowner(cap_t);
+extern int cap_set_fd(int, cap_t);
+extern int cap_set_file(const char *, cap_t);
+extern int cap_set_nsowner(cap_t, uid_t);
+
+/* libcap/cap_proc.c */
+extern cap_t cap_get_proc(void);
+extern cap_t cap_get_pid(pid_t);
+extern int cap_set_proc(cap_t);
+
+extern int cap_get_bound(cap_value_t);
+extern int cap_drop_bound(cap_value_t);
+#define CAP_IS_SUPPORTED(cap) (cap_get_bound(cap) >= 0)
+
+extern int cap_get_ambient(cap_value_t);
+extern int cap_set_ambient(cap_value_t, cap_flag_value_t);
+extern int cap_reset_ambient(void);
+#define CAP_AMBIENT_SUPPORTED() (cap_get_ambient(CAP_CHOWN) >= 0)
+
+/* libcap/cap_extint.c */
+extern ssize_t cap_size(cap_t cap_d);
+extern ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length);
+extern cap_t cap_copy_int(const void *cap_ext);
+extern cap_t cap_copy_int_check(const void *cap_ext, ssize_t length);
+
+/* libcap/cap_text.c */
+extern cap_t cap_from_text(const char *);
+extern char * cap_to_text(cap_t, ssize_t *);
+extern int cap_from_name(const char *, cap_value_t *);
+extern char * cap_to_name(cap_value_t);
+
+extern char * cap_iab_to_text(cap_iab_t iab);
+extern cap_iab_t cap_iab_from_text(const char *text);
+
+/* libcap/cap_proc.c */
+extern void cap_set_syscall(long int (*new_syscall)(long int,
+ long int, long int, long int),
+ long int (*new_syscall6)(long int,
+ long int, long int, long int,
+ long int, long int, long int));
+
+extern int cap_set_mode(cap_mode_t flavor);
+extern cap_mode_t cap_get_mode(void);
+extern const char *cap_mode_name(cap_mode_t flavor);
+
+extern unsigned cap_get_secbits(void);
+extern int cap_set_secbits(unsigned bits);
+
+extern int cap_prctl(long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5);
+extern int cap_prctlw(long int pr_cmd, long int arg1, long int arg2,
+ long int arg3, long int arg4, long int arg5);
+extern int cap_setuid(uid_t uid);
+extern int cap_setgroups(gid_t gid, size_t ngroups, const gid_t groups[]);
+
+extern cap_iab_t cap_iab_get_proc(void);
+extern cap_iab_t cap_iab_get_pid(pid_t);
+extern int cap_iab_set_proc(cap_iab_t iab);
+
+typedef struct cap_launch_s *cap_launch_t;
+
+extern cap_launch_t cap_new_launcher(const char *arg0, const char * const *argv,
+ const char * const *envp);
+extern cap_launch_t cap_func_launcher(int (callback_fn)(void *detail));
+extern int cap_launcher_callback(cap_launch_t attr,
+ int (callback_fn)(void *detail));
+extern int cap_launcher_setuid(cap_launch_t attr, uid_t uid);
+extern int cap_launcher_setgroups(cap_launch_t attr, gid_t gid,
+ int ngroups, const gid_t *groups);
+extern int cap_launcher_set_mode(cap_launch_t attr, cap_mode_t flavor);
+extern cap_iab_t cap_launcher_set_iab(cap_launch_t attr, cap_iab_t iab);
+extern int cap_launcher_set_chroot(cap_launch_t attr, const char *chroot);
+extern pid_t cap_launch(cap_launch_t attr, void *detail);
+
+/*
+ * system calls - look to libc for function to system call
+ * mapping. Note, libcap does not use capset directly, but permits the
+ * cap_set_syscall() to redirect the system call function.
+ */
+extern int capget(cap_user_header_t header, cap_user_data_t data);
+extern int capset(cap_user_header_t header, const cap_user_data_t data);
+
+/* deprecated - use cap_get_pid() */
+extern int capgetp(pid_t pid, cap_t cap_d);
+
+/* not valid with filesystem capability support - use cap_set_proc() */
+extern int capsetp(pid_t pid, cap_t cap_d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_CAPABILITY_H */
diff --git a/depends/libcap/libcap/include/sys/securebits.h b/depends/libcap/libcap/include/sys/securebits.h
new file mode 100644
index 0000000..14cf3c5
--- /dev/null
+++ b/depends/libcap/libcap/include/sys/securebits.h
@@ -0,0 +1,22 @@
+/*
+ * <sys/securebits.h>
+ * Copyright (C) 2010 Serge Hallyn <serue@us.ibm.com>
+ */
+
+#ifndef _SYS_SECUREBITS_H
+#define _SYS_SECUREBITS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __user
+#define __user
+#endif
+#include <linux/securebits.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SECUREBITS_H */
diff --git a/depends/libcap/libcap/include/uapi/linux/capability.h b/depends/libcap/libcap/include/uapi/linux/capability.h
new file mode 100644
index 0000000..56c9180
--- /dev/null
+++ b/depends/libcap/libcap/include/uapi/linux/capability.h
@@ -0,0 +1,427 @@
+/*
+ * This is <linux/capability.h>
+ *
+ * Andrew G. Morgan <morgan@kernel.org>
+ * Alexander Kjeldaas <astor@guardian.no>
+ * with help from Aleph1, Roland Buresund and Andrew Main.
+ *
+ * See here for the libcap library ("POSIX draft" compliance):
+ *
+ * https://git.kernel.org/pub/scm/libs/libcap/libcap.git/refs/
+ * http://www.kernel.org/pub/linux/libs/security/linux-privs/
+ */
+
+#ifndef _UAPI_LINUX_CAPABILITY_H
+#define _UAPI_LINUX_CAPABILITY_H
+
+#include <stdint.h>
+#define __u32 uint32_t
+#define __le32 __u32
+
+/* User-level do most of the mapping between kernel and user
+ capabilities based on the version tag given by the kernel. The
+ kernel might be somewhat backwards compatible, but don't bet on
+ it. */
+
+/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to
+ a set of three capability sets. The transposition of 3*the
+ following structure to such a composite is better handled in a user
+ library since the draft standard requires the use of malloc/free
+ etc.. */
+
+#define _LINUX_CAPABILITY_VERSION_1 0x19980330
+#define _LINUX_CAPABILITY_U32S_1 1
+
+#define _LINUX_CAPABILITY_VERSION_2 0x20071026 /* deprecated - use v3 */
+#define _LINUX_CAPABILITY_U32S_2 2
+
+#define _LINUX_CAPABILITY_VERSION_3 0x20080522
+#define _LINUX_CAPABILITY_U32S_3 2
+
+typedef struct __user_cap_header_struct {
+ __u32 version;
+ int pid;
+} *cap_user_header_t;
+
+typedef struct __user_cap_data_struct {
+ __u32 effective;
+ __u32 permitted;
+ __u32 inheritable;
+} *cap_user_data_t;
+
+
+#define VFS_CAP_REVISION_MASK 0xFF000000
+#define VFS_CAP_REVISION_SHIFT 24
+#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
+#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
+
+#define VFS_CAP_REVISION_1 0x01000000
+#define VFS_CAP_U32_1 1
+#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+
+#define VFS_CAP_REVISION_2 0x02000000
+#define VFS_CAP_U32_2 2
+#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+
+#define VFS_CAP_REVISION_3 0x03000000
+#define VFS_CAP_U32_3 VFS_CAP_U32_2
+#define XATTR_CAPS_SZ_3 (sizeof(__le32)+XATTR_CAPS_SZ_2)
+
+/*
+ * Kernel capabilities default to v2. The v3 VFS caps are only used,
+ * at present, for namespace specific filesystem capabilities.
+ */
+#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
+#define VFS_CAP_U32 VFS_CAP_U32_2
+#define VFS_CAP_REVISION VFS_CAP_REVISION_2
+
+#define _VFS_CAP_DATA_HEAD \
+ __le32 magic_etc; /* Little endian */ \
+ struct { \
+ __le32 permitted; /* Little endian */ \
+ __le32 inheritable; /* Little endian */ \
+ } data[VFS_CAP_U32]
+
+struct vfs_cap_data {
+ _VFS_CAP_DATA_HEAD;
+};
+
+struct vfs_ns_cap_data {
+ _VFS_CAP_DATA_HEAD;
+ __le32 rootid;
+};
+
+#ifndef __KERNEL__
+
+/*
+ * Backwardly compatible definition for source code - trapped in a
+ * 32-bit world. If you find you need this, please consider using
+ * libcap to untrap yourself...
+ */
+#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
+#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
+
+#endif
+
+
+/**
+ ** POSIX-draft defined capabilities.
+ **/
+
+/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
+ overrides the restriction of changing file ownership and group
+ ownership. */
+
+#define CAP_CHOWN 0
+
+/* Override all DAC access, including ACL execute access if
+ [_POSIX_ACL] is defined. Excluding DAC access covered by
+ CAP_LINUX_IMMUTABLE. */
+
+#define CAP_DAC_OVERRIDE 1
+
+/* Overrides all DAC restrictions regarding read and search on files
+ and directories, including ACL restrictions if [_POSIX_ACL] is
+ defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */
+
+#define CAP_DAC_READ_SEARCH 2
+
+/* Overrides all restrictions about allowed operations on files, where
+ file owner ID must be equal to the user ID, except where CAP_FSETID
+ is applicable. It doesn't override MAC and DAC restrictions. */
+
+#define CAP_FOWNER 3
+
+/* Overrides the following restrictions that the effective user ID
+ shall match the file owner ID when setting the S_ISUID and S_ISGID
+ bits on that file; that the effective group ID (or one of the
+ supplementary group IDs) shall match the file owner ID when setting
+ the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are
+ cleared on successful return from chown(2) (not implemented). */
+
+#define CAP_FSETID 4
+
+/* Overrides the restriction that the real or effective user ID of a
+ process sending a signal must match the real or effective user ID
+ of the process receiving the signal. */
+
+#define CAP_KILL 5
+
+/* Allows setgid(2) manipulation */
+/* Allows setgroups(2) */
+/* Allows forged gids on socket credentials passing. */
+
+#define CAP_SETGID 6
+
+/* Allows set*uid(2) manipulation (including fsuid). */
+/* Allows forged pids on socket credentials passing. */
+
+#define CAP_SETUID 7
+
+
+/**
+ ** Linux-specific capabilities
+ **/
+
+/* Without VFS support for capabilities:
+ * Transfer any capability in your permitted set to any pid,
+ * remove any capability in your permitted set from any pid
+ * With VFS support for capabilities (neither of above, but)
+ * Add any capability from current's capability bounding set
+ * to the current process' inheritable set
+ * Allow taking bits out of capability bounding set
+ * Allow modification of the securebits for a process
+ */
+
+#define CAP_SETPCAP 8
+
+/* Allow modification of S_IMMUTABLE and S_APPEND file attributes */
+
+#define CAP_LINUX_IMMUTABLE 9
+
+/* Allows binding to TCP/UDP sockets below 1024 */
+/* Allows binding to ATM VCIs below 32 */
+
+#define CAP_NET_BIND_SERVICE 10
+
+/* Allow broadcasting, listen to multicast */
+
+#define CAP_NET_BROADCAST 11
+
+/* Allow interface configuration */
+/* Allow administration of IP firewall, masquerading and accounting */
+/* Allow setting debug option on sockets */
+/* Allow modification of routing tables */
+/* Allow setting arbitrary process / process group ownership on
+ sockets */
+/* Allow binding to any address for transparent proxying (also via NET_RAW) */
+/* Allow setting TOS (type of service) */
+/* Allow setting promiscuous mode */
+/* Allow clearing driver statistics */
+/* Allow multicasting */
+/* Allow read/write of device-specific registers */
+/* Allow activation of ATM control sockets */
+
+#define CAP_NET_ADMIN 12
+
+/* Allow use of RAW sockets */
+/* Allow use of PACKET sockets */
+/* Allow binding to any address for transparent proxying (also via NET_ADMIN) */
+
+#define CAP_NET_RAW 13
+
+/* Allow locking of shared memory segments */
+/* Allow mlock and mlockall (which doesn't really have anything to do
+ with IPC) */
+
+#define CAP_IPC_LOCK 14
+
+/* Override IPC ownership checks */
+
+#define CAP_IPC_OWNER 15
+
+/* Insert and remove kernel modules - modify kernel without limit */
+#define CAP_SYS_MODULE 16
+
+/* Allow ioperm/iopl access */
+/* Allow sending USB messages to any device via /dev/bus/usb */
+
+#define CAP_SYS_RAWIO 17
+
+/* Allow use of chroot() */
+
+#define CAP_SYS_CHROOT 18
+
+/* Allow ptrace() of any process */
+
+#define CAP_SYS_PTRACE 19
+
+/* Allow configuration of process accounting */
+
+#define CAP_SYS_PACCT 20
+
+/* Allow configuration of the secure attention key */
+/* Allow administration of the random device */
+/* Allow examination and configuration of disk quotas */
+/* Allow setting the domainname */
+/* Allow setting the hostname */
+/* Allow calling bdflush() */
+/* Allow mount() and umount(), setting up new smb connection */
+/* Allow some autofs root ioctls */
+/* Allow nfsservctl */
+/* Allow VM86_REQUEST_IRQ */
+/* Allow to read/write pci config on alpha */
+/* Allow irix_prctl on mips (setstacksize) */
+/* Allow flushing all cache on m68k (sys_cacheflush) */
+/* Allow removing semaphores */
+/* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores
+ and shared memory */
+/* Allow locking/unlocking of shared memory segment */
+/* Allow turning swap on/off */
+/* Allow forged pids on socket credentials passing */
+/* Allow setting readahead and flushing buffers on block devices */
+/* Allow setting geometry in floppy driver */
+/* Allow turning DMA on/off in xd driver */
+/* Allow administration of md devices (mostly the above, but some
+ extra ioctls) */
+/* Allow tuning the ide driver */
+/* Allow access to the nvram device */
+/* Allow administration of apm_bios, serial and bttv (TV) device */
+/* Allow manufacturer commands in isdn CAPI support driver */
+/* Allow reading non-standardized portions of pci configuration space */
+/* Allow DDI debug ioctl on sbpcd driver */
+/* Allow setting up serial ports */
+/* Allow sending raw qic-117 commands */
+/* Allow enabling/disabling tagged queuing on SCSI controllers and sending
+ arbitrary SCSI commands */
+/* Allow setting encryption key on loopback filesystem */
+/* Allow setting zone reclaim policy */
+
+#define CAP_SYS_ADMIN 21
+
+/* Allow use of reboot() */
+
+#define CAP_SYS_BOOT 22
+
+/* Allow raising priority and setting priority on other (different
+ UID) processes */
+/* Allow use of FIFO and round-robin (realtime) scheduling on own
+ processes and setting the scheduling algorithm used by another
+ process. */
+/* Allow setting cpu affinity on other processes */
+
+#define CAP_SYS_NICE 23
+
+/* Override resource limits. Set resource limits. */
+/* Override quota limits. */
+/* Override reserved space on ext2 filesystem */
+/* Modify data journaling mode on ext3 filesystem (uses journaling
+ resources) */
+/* NOTE: ext2 honors fsuid when checking for resource overrides, so
+ you can override using fsuid too */
+/* Override size restrictions on IPC message queues */
+/* Allow more than 64hz interrupts from the real-time clock */
+/* Override max number of consoles on console allocation */
+/* Override max number of keymaps */
+
+#define CAP_SYS_RESOURCE 24
+
+/* Allow manipulation of system clock */
+/* Allow irix_stime on mips */
+/* Allow setting the real-time clock */
+
+#define CAP_SYS_TIME 25
+
+/* Allow configuration of tty devices */
+/* Allow vhangup() of tty */
+
+#define CAP_SYS_TTY_CONFIG 26
+
+/* Allow the privileged aspects of mknod() */
+
+#define CAP_MKNOD 27
+
+/* Allow taking of leases on files */
+
+#define CAP_LEASE 28
+
+/* Allow writing the audit log via unicast netlink socket */
+
+#define CAP_AUDIT_WRITE 29
+
+/* Allow configuration of audit via unicast netlink socket */
+
+#define CAP_AUDIT_CONTROL 30
+
+/* Set capabilities on files. */
+
+#define CAP_SETFCAP 31
+
+/* Override MAC access.
+ The base kernel enforces no MAC policy.
+ An LSM may enforce a MAC policy, and if it does and it chooses
+ to implement capability based overrides of that policy, this is
+ the capability it should use to do so. */
+
+#define CAP_MAC_OVERRIDE 32
+
+/* Allow MAC configuration or state changes.
+ The base kernel requires no MAC configuration.
+ An LSM may enforce a MAC policy, and if it does and it chooses
+ to implement capability based checks on modifications to that
+ policy or the data required to maintain it, this is the
+ capability it should use to do so. */
+
+#define CAP_MAC_ADMIN 33
+
+/* Allow configuring the kernel's syslog (printk behaviour) */
+
+#define CAP_SYSLOG 34
+
+/* Allow triggering something that will wake the system */
+
+#define CAP_WAKE_ALARM 35
+
+/* Allow preventing system suspends */
+
+#define CAP_BLOCK_SUSPEND 36
+
+/* Allow reading the audit log via multicast netlink socket */
+
+#define CAP_AUDIT_READ 37
+
+/* Allow system performance and observability privileged operations using
+ * perf_events, i915_perf and other kernel subsystems. */
+
+#define CAP_PERFMON 38
+
+/*
+ * CAP_BPF allows the following BPF operations:
+ * - Creating all types of BPF maps
+ * - Advanced verifier features
+ * - Indirect variable access
+ * - Bounded loops
+ * - BPF to BPF function calls
+ * - Scalar precision tracking
+ * - Larger complexity limits
+ * - Dead code elimination
+ * - And potentially other features
+ * - Loading BPF Type Format (BTF) data
+ * - Retrieve xlated and JITed code of BPF programs
+ * - Use bpf_spin_lock() helper
+ *
+ * CAP_PERFMON relaxes the verifier checks further:
+ * - BPF progs can use of pointer-to-integer conversions
+ * - speculation attack hardening measures are bypassed
+ * - bpf_probe_read to read arbitrary kernel memory is allowed
+ * - bpf_trace_printk to print kernel memory is allowed
+ *
+ * CAP_SYS_ADMIN is required to use bpf_probe_write_user.
+ *
+ * CAP_SYS_ADMIN is required to iterate system wide loaded
+ * programs, maps, links, BTFs and convert their IDs to file descriptors.
+ *
+ * CAP_PERFMON and CAP_BPF are required to load tracing programs.
+ * CAP_NET_ADMIN and CAP_BPF are required to load networking programs.
+ */
+
+#define CAP_BPF 39
+
+/* Allow checkpoint/restore related operations */
+/* Allow PID selection during clone3() */
+/* Allow writing to ns_last_pid */
+
+#define CAP_CHECKPOINT_RESTORE 40
+
+#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
+
+#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
+
+/*
+ * Bit location of each capability (used by user-space library and kernel)
+ */
+
+#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */
+#define CAP_TO_MASK(x) (1u << ((x) & 31)) /* mask for indexed __u32 */
+
+#endif /* _UAPI_LINUX_CAPABILITY_H */
diff --git a/depends/libcap/libcap/include/uapi/linux/prctl.h b/depends/libcap/libcap/include/uapi/linux/prctl.h
new file mode 100644
index 0000000..1b6a009
--- /dev/null
+++ b/depends/libcap/libcap/include/uapi/linux/prctl.h
@@ -0,0 +1,200 @@
+#ifndef _LINUX_PRCTL_H
+#define _LINUX_PRCTL_H
+
+#include <linux/types.h>
+
+/* Values to pass as first argument to prctl() */
+
+#define PR_SET_PDEATHSIG 1 /* Second arg is a signal */
+#define PR_GET_PDEATHSIG 2 /* Second arg is a ptr to return the signal */
+
+/* Get/set current->mm->dumpable */
+#define PR_GET_DUMPABLE 3
+#define PR_SET_DUMPABLE 4
+
+/* Get/set unaligned access control bits (if meaningful) */
+#define PR_GET_UNALIGN 5
+#define PR_SET_UNALIGN 6
+# define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */
+# define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */
+
+/* Get/set whether or not to drop capabilities on setuid() away from
+ * uid 0 (as per security/commoncap.c) */
+#define PR_GET_KEEPCAPS 7
+#define PR_SET_KEEPCAPS 8
+
+/* Get/set floating-point emulation control bits (if meaningful) */
+#define PR_GET_FPEMU 9
+#define PR_SET_FPEMU 10
+# define PR_FPEMU_NOPRINT 1 /* silently emulate fp operations accesses */
+# define PR_FPEMU_SIGFPE 2 /* don't emulate fp operations, send SIGFPE instead */
+
+/* Get/set floating-point exception mode (if meaningful) */
+#define PR_GET_FPEXC 11
+#define PR_SET_FPEXC 12
+# define PR_FP_EXC_SW_ENABLE 0x80 /* Use FPEXC for FP exception enables */
+# define PR_FP_EXC_DIV 0x010000 /* floating point divide by zero */
+# define PR_FP_EXC_OVF 0x020000 /* floating point overflow */
+# define PR_FP_EXC_UND 0x040000 /* floating point underflow */
+# define PR_FP_EXC_RES 0x080000 /* floating point inexact result */
+# define PR_FP_EXC_INV 0x100000 /* floating point invalid operation */
+# define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */
+# define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */
+# define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */
+# define PR_FP_EXC_PRECISE 3 /* precise exception mode */
+
+/* Get/set whether we use statistical process timing or accurate timestamp
+ * based process timing */
+#define PR_GET_TIMING 13
+#define PR_SET_TIMING 14
+# define PR_TIMING_STATISTICAL 0 /* Normal, traditional,
+ statistical process timing */
+# define PR_TIMING_TIMESTAMP 1 /* Accurate timestamp based
+ process timing */
+
+#define PR_SET_NAME 15 /* Set process name */
+#define PR_GET_NAME 16 /* Get process name */
+
+/* Get/set process endian */
+#define PR_GET_ENDIAN 19
+#define PR_SET_ENDIAN 20
+# define PR_ENDIAN_BIG 0
+# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
+# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */
+
+/* Get/set process seccomp mode */
+#define PR_GET_SECCOMP 21
+#define PR_SET_SECCOMP 22
+
+/* Get/set the capability bounding set (as per security/commoncap.c) */
+#define PR_CAPBSET_READ 23
+#define PR_CAPBSET_DROP 24
+
+/* Get/set the process' ability to use the timestamp counter instruction */
+#define PR_GET_TSC 25
+#define PR_SET_TSC 26
+# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
+# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
+
+/* Get/set securebits (as per security/commoncap.c) */
+#define PR_GET_SECUREBITS 27
+#define PR_SET_SECUREBITS 28
+
+/*
+ * Get/set the timerslack as used by poll/select/nanosleep
+ * A value of 0 means "use default"
+ */
+#define PR_SET_TIMERSLACK 29
+#define PR_GET_TIMERSLACK 30
+
+#define PR_TASK_PERF_EVENTS_DISABLE 31
+#define PR_TASK_PERF_EVENTS_ENABLE 32
+
+/*
+ * Set early/late kill mode for hwpoison memory corruption.
+ * This influences when the process gets killed on a memory corruption.
+ */
+#define PR_MCE_KILL 33
+# define PR_MCE_KILL_CLEAR 0
+# define PR_MCE_KILL_SET 1
+
+# define PR_MCE_KILL_LATE 0
+# define PR_MCE_KILL_EARLY 1
+# define PR_MCE_KILL_DEFAULT 2
+
+#define PR_MCE_KILL_GET 34
+
+/*
+ * Tune up process memory map specifics.
+ */
+#define PR_SET_MM 35
+# define PR_SET_MM_START_CODE 1
+# define PR_SET_MM_END_CODE 2
+# define PR_SET_MM_START_DATA 3
+# define PR_SET_MM_END_DATA 4
+# define PR_SET_MM_START_STACK 5
+# define PR_SET_MM_START_BRK 6
+# define PR_SET_MM_BRK 7
+# define PR_SET_MM_ARG_START 8
+# define PR_SET_MM_ARG_END 9
+# define PR_SET_MM_ENV_START 10
+# define PR_SET_MM_ENV_END 11
+# define PR_SET_MM_AUXV 12
+# define PR_SET_MM_EXE_FILE 13
+# define PR_SET_MM_MAP 14
+# define PR_SET_MM_MAP_SIZE 15
+
+/*
+ * This structure provides new memory descriptor
+ * map which mostly modifies /proc/pid/stat[m]
+ * output for a task. This mostly done in a
+ * sake of checkpoint/restore functionality.
+ */
+struct prctl_mm_map {
+ __u64 start_code; /* code section bounds */
+ __u64 end_code;
+ __u64 start_data; /* data section bounds */
+ __u64 end_data;
+ __u64 start_brk; /* heap for brk() syscall */
+ __u64 brk;
+ __u64 start_stack; /* stack starts at */
+ __u64 arg_start; /* command line arguments bounds */
+ __u64 arg_end;
+ __u64 env_start; /* environment variables bounds */
+ __u64 env_end;
+ __u64 *auxv; /* auxiliary vector */
+ __u32 auxv_size; /* vector size */
+ __u32 exe_fd; /* /proc/$pid/exe link file */
+};
+
+/*
+ * Set specific pid that is allowed to ptrace the current task.
+ * A value of 0 mean "no process".
+ */
+#define PR_SET_PTRACER 0x59616d61
+# define PR_SET_PTRACER_ANY ((unsigned long)-1)
+
+#define PR_SET_CHILD_SUBREAPER 36
+#define PR_GET_CHILD_SUBREAPER 37
+
+/*
+ * If no_new_privs is set, then operations that grant new privileges (i.e.
+ * execve) will either fail or not grant them. This affects suid/sgid,
+ * file capabilities, and LSMs.
+ *
+ * Operations that merely manipulate or drop existing privileges (setresuid,
+ * capset, etc.) will still work. Drop those privileges if you want them gone.
+ *
+ * Changing LSM security domain is considered a new privilege. So, for example,
+ * asking selinux for a specific new context (e.g. with runcon) will result
+ * in execve returning -EPERM.
+ *
+ * See Documentation/prctl/no_new_privs.txt for more details.
+ */
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+
+#define PR_GET_TID_ADDRESS 40
+
+#define PR_SET_THP_DISABLE 41
+#define PR_GET_THP_DISABLE 42
+
+/*
+ * Tell the kernel to start/stop helping userspace manage bounds tables.
+ */
+#define PR_MPX_ENABLE_MANAGEMENT 43
+#define PR_MPX_DISABLE_MANAGEMENT 44
+
+#define PR_SET_FP_MODE 45
+#define PR_GET_FP_MODE 46
+# define PR_FP_MODE_FR (1u << 0) /* 64b FP registers */
+# define PR_FP_MODE_FRE (1u << 1) /* 32b compatibility */
+
+/* Control the ambient capability set */
+#define PR_CAP_AMBIENT 47
+# define PR_CAP_AMBIENT_IS_SET 1
+# define PR_CAP_AMBIENT_RAISE 2
+# define PR_CAP_AMBIENT_LOWER 3
+# define PR_CAP_AMBIENT_CLEAR_ALL 4
+
+#endif /* _LINUX_PRCTL_H */
diff --git a/depends/libcap/libcap/include/uapi/linux/securebits.h b/depends/libcap/libcap/include/uapi/linux/securebits.h
new file mode 100644
index 0000000..e9b1309
--- /dev/null
+++ b/depends/libcap/libcap/include/uapi/linux/securebits.h
@@ -0,0 +1,60 @@
+#ifndef _UAPI_LINUX_SECUREBITS_H
+#define _UAPI_LINUX_SECUREBITS_H
+
+/* Each securesetting is implemented using two bits. One bit specifies
+ whether the setting is on or off. The other bit specify whether the
+ setting is locked or not. A setting which is locked cannot be
+ changed from user-level. */
+#define issecure_mask(X) (1u << (X))
+
+#define SECUREBITS_DEFAULT 0x00000000
+
+/* When set UID 0 has no special privileges. When unset, we support
+ inheritance of root-permissions and suid-root executable under
+ compatibility mode. We raise the effective and inheritable bitmasks
+ *of the executable file* if the effective uid of the new process is
+ 0. If the real uid is 0, we raise the effective (legacy) bit of the
+ executable file. */
+#define SECURE_NOROOT 0
+#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
+
+#define SECBIT_NOROOT (issecure_mask(SECURE_NOROOT))
+#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 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
+#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
+
+#define SECBIT_NO_SETUID_FIXUP (issecure_mask(SECURE_NO_SETUID_FIXUP))
+#define SECBIT_NO_SETUID_FIXUP_LOCKED \
+ (issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED))
+
+/* When set, a process can retain its capabilities even after
+ transitioning to a non-root user (the set-uid fixup suppressed by
+ bit 2). Bit-4 is cleared when a process calls exec(); setting both
+ bit 4 and 5 will create a barrier through exec that no exec()'d
+ child can use this feature again. */
+#define SECURE_KEEP_CAPS 4
+#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
+
+#define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS))
+#define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED))
+
+/* When set, a process cannot add new capabilities to its ambient set. */
+#define SECURE_NO_CAP_AMBIENT_RAISE 6
+#define SECURE_NO_CAP_AMBIENT_RAISE_LOCKED 7 /* make bit-6 immutable */
+
+#define SECBIT_NO_CAP_AMBIENT_RAISE (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE))
+#define SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED \
+ (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED))
+
+#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
+ issecure_mask(SECURE_NO_SETUID_FIXUP) | \
+ issecure_mask(SECURE_KEEP_CAPS) | \
+ issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE))
+#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
+
+#endif /* _UAPI_LINUX_SECUREBITS_H */
diff --git a/depends/libcap/libcap/libcap.h b/depends/libcap/libcap/libcap.h
new file mode 100644
index 0000000..f4a72fe
--- /dev/null
+++ b/depends/libcap/libcap/libcap.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 1997,2020 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file contains internal definitions for the various functions in
+ * this small capability library.
+ */
+
+#ifndef LIBCAP_H
+#define LIBCAP_H
+
+#include <errno.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/capability.h>
+
+#ifndef __u8
+#define __u8 uint8_t
+#endif /* __8 */
+
+#ifndef __u32
+#define __u32 uint32_t
+#endif /* __u32 */
+
+/* include the names for the caps and a definition of __CAP_BITS */
+#include "cap_names.h"
+
+#ifndef _LINUX_CAPABILITY_U32S_1
+# define _LINUX_CAPABILITY_U32S_1 1
+#endif /* ndef _LINUX_CAPABILITY_U32S_1 */
+
+/*
+ * Do we match the local kernel?
+ */
+
+#if !defined(_LINUX_CAPABILITY_VERSION)
+
+# error Kernel <linux/capability.h> does not support library
+# error file "libcap.h" --> fix and recompile libcap
+
+#elif !defined(_LINUX_CAPABILITY_VERSION_2)
+
+# warning Kernel <linux/capability.h> does not support 64-bit capabilities
+# warning and libcap is being built with no support for 64-bit capabilities
+
+# ifndef _LINUX_CAPABILITY_VERSION_1
+# define _LINUX_CAPABILITY_VERSION_1 0x19980330
+# endif
+
+# _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
+# _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
+
+#elif defined(_LINUX_CAPABILITY_VERSION_3)
+
+# if (_LINUX_CAPABILITY_VERSION_3 != 0x20080522)
+# error Kernel <linux/capability.h> v3 does not match library
+# error file "libcap.h" --> fix and recompile libcap
+# else
+# define _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
+# define _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3
+# endif
+
+#elif (_LINUX_CAPABILITY_VERSION_2 != 0x20071026)
+
+# error Kernel <linux/capability.h> does not match library
+# error file "libcap.h" --> fix and recompile libcap
+
+#else
+
+# define _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2
+# define _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2
+
+#endif
+
+#undef _LINUX_CAPABILITY_VERSION
+#undef _LINUX_CAPABILITY_U32S
+
+/*
+ * This is a pointer to a struct containing three consecutive
+ * capability sets in the order of the cap_flag_t type: the are
+ * effective,inheritable and permitted. This is the type that the
+ * user-space routines think of as 'internal' capabilities - this is
+ * the type that is passed to the kernel with the system calls related
+ * to processes.
+ */
+
+#if defined(VFS_CAP_REVISION_MASK) && !defined(VFS_CAP_U32)
+# define VFS_CAP_U32_1 1
+# define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+# define VFS_CAP_U32 VFS_CAP_U32_1
+struct _cap_vfs_cap_data {
+ __le32 magic_etc;
+ struct {
+ __le32 permitted;
+ __le32 inheritable;
+ } data[VFS_CAP_U32_1];
+};
+# define vfs_cap_data _cap_vfs_cap_data
+#endif
+
+#ifndef CAP_TO_INDEX
+# define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */
+#endif /* ndef CAP_TO_INDEX */
+
+#ifndef CAP_TO_MASK
+# define CAP_TO_MASK(x) (1 << ((x) & 31))
+#endif /* ndef CAP_TO_MASK */
+
+#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */
+#define __CAP_BLKS (_LIBCAP_CAPABILITY_U32S)
+#define CAP_SET_SIZE (__CAP_BLKS * sizeof(__u32))
+
+#define CAP_T_MAGIC 0xCA90D0
+struct _cap_struct {
+ __u8 mutex;
+ struct __user_cap_header_struct head;
+ union {
+ struct __user_cap_data_struct set;
+ __u32 flat[NUMBER_OF_CAP_SETS];
+ } u[_LIBCAP_CAPABILITY_U32S];
+ uid_t rootid;
+};
+
+/*
+ * Elementary exclusive locking primatives for situations where
+ * linking with pthreads needs it, but such linking is not common.
+ *
+ * _cap_mu_blocked(x) attempts to lock x but if already locked, returns true
+ * _cap_mu_lock(x) attempts to lock and waits until the lock is granted
+ * _cap_mu_unlock(x) unconditionally unlocks the lock
+ * _cap_mu_unlock_return(x, y) unlock lock x and return value y
+ */
+#define _cap_mu_blocked(x) \
+ __atomic_test_and_set((void *)(x), __ATOMIC_SEQ_CST)
+#define _cap_mu_lock(x) \
+ while (_cap_mu_blocked(x)) sched_yield()
+#define _cap_mu_unlock(x) \
+ __atomic_clear((void *) (x), __ATOMIC_SEQ_CST)
+#define _cap_mu_unlock_return(x, y) \
+ do { _cap_mu_unlock(x); return (y); } while (0)
+
+/* the maximum bits supportable */
+#define __CAP_MAXBITS (__CAP_BLKS * 32)
+
+/* string magic for cap_free */
+#define CAP_S_MAGIC 0xCA95D0
+
+/* iab set magic for cap_free */
+#define CAP_IAB_MAGIC 0xCA91AB
+
+/* launcher magic for cap_free */
+#define CAP_LAUNCH_MAGIC 0xCA91AC
+
+#define magic_of(x) ((x) ? *(-2 + (const __u32 *) x) : 0)
+#define good_cap_t(x) (CAP_T_MAGIC == magic_of(x))
+#define good_cap_iab_t(x) (CAP_IAB_MAGIC == magic_of(x))
+#define good_cap_launch_t(x) (CAP_LAUNCH_MAGIC == magic_of(x))
+
+/*
+ * kernel API cap set abstraction
+ */
+
+#define raise_cap(x, set) u[(x) >> 5].flat[set] |= (1u << ((x)&31))
+#define lower_cap(x, set) u[(x) >> 5].flat[set] &= ~(1u << ((x)&31))
+#define isset_cap(y, x, set) ((y)->u[(x) >> 5].flat[set] & (1u << ((x)&31)))
+
+/*
+ * These match CAP_DIFFERS() expectations
+ */
+#define LIBCAP_EFF (1 << CAP_EFFECTIVE)
+#define LIBCAP_INH (1 << CAP_INHERITABLE)
+#define LIBCAP_PER (1 << CAP_PERMITTED)
+
+/*
+ * library debugging
+ */
+#ifdef DEBUG
+
+#include <stdio.h>
+# define _cap_debug(f, x...) do { \
+ fprintf(stderr, "%s(%s:%d): ", __FUNCTION__, __FILE__, __LINE__); \
+ fprintf(stderr, f, ## x); \
+ fprintf(stderr, "\n"); \
+} while (0)
+
+# define _cap_debugcap(s, c, set) do { \
+ unsigned _cap_index; \
+ fprintf(stderr, "%s(%s:%d): %s", __FUNCTION__, __FILE__, __LINE__, s); \
+ for (_cap_index=_LIBCAP_CAPABILITY_U32S; _cap_index-- > 0; ) { \
+ fprintf(stderr, "%08x", (c).u[_cap_index].flat[set]); \
+ } \
+ fprintf(stderr, "\n"); \
+} while (0)
+
+#else /* !DEBUG */
+
+# define _cap_debug(f, x...)
+# define _cap_debugcap(s, c, set)
+
+#endif /* DEBUG */
+
+extern char *_libcap_strdup(const char *text);
+extern void _libcap_initialize(void);
+
+#define EXECABLE_INITIALIZE _libcap_initialize()
+
+/*
+ * These are semi-public prototypes, they will only be defined in
+ * <sys/capability.h> if _POSIX_SOURCE is not #define'd, so we
+ * place them here too.
+ */
+
+extern int capget(cap_user_header_t header, cap_user_data_t data);
+extern int capgetp(pid_t pid, cap_t cap_d);
+extern int capsetp(pid_t pid, cap_t cap_d);
+
+/* prctl based API for altering character of current process */
+#define PR_GET_KEEPCAPS 7
+#define PR_SET_KEEPCAPS 8
+#define PR_CAPBSET_READ 23
+#define PR_CAPBSET_DROP 24
+#define PR_GET_SECUREBITS 27
+#define PR_SET_SECUREBITS 28
+
+/*
+ * The library compares sizeof() with integer return values. To avoid
+ * signed/unsigned comparisons, leading to unfortunate
+ * misinterpretations of -1, we provide a convenient cast-to-signed-integer
+ * version of sizeof().
+ */
+#define ssizeof(x) ((ssize_t) sizeof(x))
+
+/*
+ * Put this here as a macro so we can unit test it.
+ */
+#define _binary_search(val, fn, low, high, fallback) do { \
+ cap_value_t min = low, max = high; \
+ while (min <= max) { \
+ cap_value_t mid = (min+max) / 2; \
+ if (fn(mid) < 0) { \
+ max = mid - 1; \
+ } else { \
+ min = mid + 1; \
+ } \
+ } \
+ val = min ? (min <= high ? min : fallback) : fallback; \
+ } while(0)
+
+/*
+ * cap_iab_s holds a collection of inheritable capability bits. The i
+ * bits are inheritable (these are the same as those in cap_t), the a
+ * bits are ambient bits (which cannot be a superset of i&p), and nb
+ * are the bits that will be dropped from the bounding set when
+ * applied.
+ */
+struct cap_iab_s {
+ __u8 mutex;
+ __u32 i[_LIBCAP_CAPABILITY_U32S];
+ __u32 a[_LIBCAP_CAPABILITY_U32S];
+ __u32 nb[_LIBCAP_CAPABILITY_U32S];
+};
+
+#define LIBCAP_IAB_I_FLAG (1U << CAP_IAB_INH)
+#define LIBCAP_IAB_A_FLAG (1U << CAP_IAB_AMB)
+#define LIBCAP_IAB_IA_FLAG (LIBCAP_IAB_I_FLAG | LIBCAP_IAB_A_FLAG)
+#define LIBCAP_IAB_NB_FLAG (1U << CAP_IAB_BOUND)
+
+/*
+ * The following support launching another process without destroying
+ * the state of the current process. This is especially useful for
+ * multithreaded applications.
+ */
+struct cap_launch_s {
+ __u8 mutex;
+ /*
+ * Once forked but before active privilege is changed, this
+ * function (if non-NULL) is called.
+ */
+ int (*custom_setup_fn)(void *detail);
+
+ /*
+ * user and groups to be used by the forked child.
+ */
+ int change_uids;
+ uid_t uid;
+
+ int change_gids;
+ gid_t gid;
+ int ngroups;
+ const gid_t *groups;
+
+ /*
+ * mode holds the preferred capability mode. Any non-uncertain
+ * setting here will require an empty ambient set.
+ */
+ int change_mode;
+ cap_mode_t mode;
+
+ /*
+ * i,a,[n]b caps. These bitmaps hold all of the capability sets that
+ * cap_launch will affect. nb holds values to be lowered in the bounding
+ * set.
+ */
+ struct cap_iab_s *iab;
+
+ /* chroot holds a preferred chroot for the launched child. */
+ char *chroot;
+
+ /*
+ * execve style arguments
+ */
+ const char *arg0;
+ const char *const *argv;
+ const char *const *envp;
+};
+
+#endif /* LIBCAP_H */
diff --git a/depends/libcap/libcap/libcap.pc.in b/depends/libcap/libcap/libcap.pc.in
new file mode 100644
index 0000000..69cd231
--- /dev/null
+++ b/depends/libcap/libcap/libcap.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcap
+Description: libcap - linux capabilities library
+Version: @VERSION@
+Libs: -L${libdir} -lcap
+Libs.private: @deps@
+Cflags: -I${includedir}
diff --git a/depends/libcap/libcap/libpsx.pc.in b/depends/libcap/libcap/libpsx.pc.in
new file mode 100644
index 0000000..d032b9f
--- /dev/null
+++ b/depends/libcap/libcap/libpsx.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpsx
+Description: libpsx - linux posix syscall API for pthreads
+Version: @VERSION@
+Libs: -L${libdir} -lpsx -lpthread -Wl,-wrap,pthread_create
+Libs.private: @deps@
+Cflags: -I${includedir}
diff --git a/depends/libcap/libcap/psx_exec.c b/depends/libcap/libcap/psx_exec.c
new file mode 100644
index 0000000..5e7a88f
--- /dev/null
+++ b/depends/libcap/libcap/psx_exec.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include "execable.h"
+
+SO_MAIN(int argc, char **argv)
+{
+ const char *cmd = "This library";
+ if (argv != NULL && argv[0] != NULL) {
+ cmd = argv[0];
+ }
+ printf("%s is the shared library version: " LIBRARY_VERSION ".\n"
+ "See the License file for distribution information.\n"
+ "More information on this library is available from:\n"
+ "\n"
+ " https://sites.google.com/site/fullycapable/\n", cmd);
+}