From 8a70482ab7f5a5f0ca9c75ccfe7a9726196c0eeb Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Wed, 13 Apr 2022 15:19:02 +0800 Subject: [PATCH] update to libcap-2.48-2.el8.src.rpm Signed-off-by: Liwei Ge --- download | 1 + getpcaps.8 | 23 - libcap-2.25-buildflags.patch | 22 - libcap-2.26-ambient-caps.patch | 952 ----------------------------- libcap-2.26.tar.gz | Bin 77163 -> 0 bytes libcap-2.48-buildflags.patch | 34 ++ libcap-PAM_REINITIALIZE_CRED.patch | 12 - libcap-abi-compatibility.patch | 37 ++ libcap-add-new-caps.patch | 96 --- libcap-fix-ambient-caps.patch | 147 +++++ libcap-static-analysis.patch | 494 +++++++++++++++ libcap.spec | 32 +- 12 files changed, 730 insertions(+), 1120 deletions(-) create mode 100644 download delete mode 100644 getpcaps.8 delete mode 100644 libcap-2.25-buildflags.patch delete mode 100644 libcap-2.26-ambient-caps.patch delete mode 100644 libcap-2.26.tar.gz create mode 100644 libcap-2.48-buildflags.patch delete mode 100644 libcap-PAM_REINITIALIZE_CRED.patch create mode 100644 libcap-abi-compatibility.patch delete mode 100644 libcap-add-new-caps.patch create mode 100644 libcap-fix-ambient-caps.patch create mode 100644 libcap-static-analysis.patch diff --git a/download b/download new file mode 100644 index 0000000..543e00e --- /dev/null +++ b/download @@ -0,0 +1 @@ +5b48cfc381c69c82d197674a7f5c4b59 libcap-2.48.tar.gz diff --git a/getpcaps.8 b/getpcaps.8 deleted file mode 100644 index 6bbf46a..0000000 --- a/getpcaps.8 +++ /dev/null @@ -1,23 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH GETPCAPS 8 "2001-05-29" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -getpcaps \- display process capabilities -.SH SYNOPSIS -.B getpcaps -.IR pid ... -.SH DESCRIPTION -.B getpcaps -displays the capabilities on the processes indicated by the -.I pid -value(s) given on the commandline. The capabilities -are displayed in the -.BR cap_from_text (3) -format. -.SH SEE ALSO -.BR execcap (8). -.br -.SH AUTHOR -This manual page was written by Robert Bihlmeyer , -for the Debian GNU/Linux system (but may be used by others). - diff --git a/libcap-2.25-buildflags.patch b/libcap-2.25-buildflags.patch deleted file mode 100644 index 48745fd..0000000 --- a/libcap-2.25-buildflags.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -up libcap-2.25/Make.Rules.rh libcap-2.25/Make.Rules ---- libcap-2.25/Make.Rules.rh 2016-04-11 18:52:01.418065682 +0200 -+++ libcap-2.25/Make.Rules 2016-04-11 18:52:10.790113866 +0200 -@@ -49,7 +49,8 @@ KERNEL_HEADERS := $(topdir)/libcap/inclu - IPATH += -fPIC -I$(KERNEL_HEADERS) -I$(topdir)/libcap/include - - CC := gcc --CFLAGS := -O2 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -+CFLAGS := $(RPM_OPT_FLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -+ - BUILD_CC := $(CC) - BUILD_CFLAGS := $(CFLAGS) $(IPATH) - AR := ar -@@ -60,7 +61,7 @@ WARNINGS=-Wall -Wwrite-strings \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Wnested-externs -Winline -Wshadow - LD=$(CC) -Wl,-x -shared --LDFLAGS := #-g -+LDFLAGS := $(RPM_LD_FLAGS) #-g - BUILD_GPERF := $(shell which gperf >/dev/null 2>/dev/null && echo yes) - - SYSTEM_HEADERS = /usr/include diff --git a/libcap-2.26-ambient-caps.patch b/libcap-2.26-ambient-caps.patch deleted file mode 100644 index b8eeedd..0000000 --- a/libcap-2.26-ambient-caps.patch +++ /dev/null @@ -1,952 +0,0 @@ -From 99c995b84ef2974426b0acfa584d75e9a7d82028 Mon Sep 17 00:00:00 2001 -From: "Andrew G. Morgan" -Date: Sun, 22 Dec 2019 08:08:48 -0800 -Subject: Add group, ambient and bound setting support to pam_cap. - -Rewrote the pam_cap config file parsing to support: - - - @group syntax for identifying groups of users - - ^cap_foo support for raising both inheritable and ambient caps - - !cap_bar support for dropping bounding capabilities - -Updated documentation for pre-existing libcap's ambient support. - -This pam_cap feature upgrade was done in collaboration with -Knut Omang and Christoph Lameter. - -Signed-off-by: Andrew G. Morgan ---- - doc/cap_get_ambient.3 | 1 + - doc/cap_get_proc.3 | 46 ++++++- - doc/cap_reset_ambient.3 | 1 + - doc/cap_set_ambient.3 | 1 + - pam_cap/.gitignore | 3 +- - pam_cap/Makefile | 21 ++- - pam_cap/pam_cap.c | 355 +++++++++++++++++++++++++++++++++++------------- - pam_cap/sudotest.conf | 23 ++++ - pam_cap/test_pam_cap.c | 200 +++++++++++++++++++++++++++ - 10 files changed, 556 insertions(+), 113 deletions(-) - create mode 100644 doc/cap_get_ambient.3 - create mode 100644 doc/cap_reset_ambient.3 - create mode 100644 doc/cap_set_ambient.3 - create mode 100644 pam_cap/sudotest.conf - create mode 100644 pam_cap/test_pam_cap.c - -diff --git a/doc/cap_get_ambient.3 b/doc/cap_get_ambient.3 -new file mode 100644 -index 0000000..65ea3e4 ---- /dev/null -+++ b/doc/cap_get_ambient.3 -@@ -0,0 +1 @@ -+.so man3/cap_get_proc.3 -diff --git a/doc/cap_get_proc.3 b/doc/cap_get_proc.3 -index ed87fb7..712b3ff 100644 ---- a/doc/cap_get_proc.3 -+++ b/doc/cap_get_proc.3 -@@ -3,7 +3,8 @@ - .\" - .TH CAP_GET_PROC 3 "2008-05-11" "" "Linux Programmer's Manual" - .SH NAME --cap_get_proc, cap_set_proc, capgetp, cap_get_bound, cap_drop_bound \- -+cap_get_proc, cap_set_proc, capgetp, cap_get_bound, cap_drop_bound \ -+cap_get_ambient, cap_set_ambient, cap_reset_ambient, \- - capability manipulation on processes - .SH SYNOPSIS - .B #include -@@ -18,6 +19,14 @@ - .sp - .BI "int cap_drop_bound(cap_value_t " cap ); - .sp -+.BI "int cap_get_ambient(cap_value_t " cap ); -+.sp -+.BI "int cap_set_ambient(cap_value_t " cap ", cap_flag_value_t " value); -+.sp -+.B int cap_reset_ambient(void); -+.sp -+.BI CAP_AMBIENT_SUPPORTED(); -+.sp - .B #include - .sp - .BI "cap_t cap_get_pid(pid_t " pid ); -@@ -75,11 +84,38 @@ - .PP - .BR cap_drop_bound () - can be used to lower the specified bounding set capability, --.BR cap , -+.BR cap . - To complete successfully, the prevailing - .I effective - capability set must have a raised - .BR CAP_SETPCAP . -+.BR cap_get_ambient () -+returns the prevailing value of the specified ambient capability, or -+-1 if the capability is not supported by the running kernel. A macro -+.BR CAP_AMBIENT_SUPPORTED () -+uses this function to determine if ambient capabilities are supported -+by the kernel. -+.PP -+.BR cap_set_ambient () -+sets the specified ambient capability to a specific value. To complete -+successfully, the prevailing -+.I effective -+capability set must have a raised -+.BR CAP_SETPCAP . -+.PP -+.BR cap_reset_ambient () -+resets all of the ambient capabilities for the current process to -+their lowered value. To complete successfully, the prevailing -+.I effective -+capability set must have a raised -+.BR CAP_SETPCAP . -+Note, the ambient set is intended to operate in a legacy environment -+where the application has limited awareness of capabilities in -+general. Executing a file with associated filesystem capabilities, the -+kernel will implicitly reset the ambient set of the process. Also, -+changes to the inheritable set by the program code without explicitly -+fixing up the ambient set can also drop ambient bits. -+.PP - .SH "RETURN VALUE" - The functions - .BR cap_get_proc () -diff --git a/doc/cap_reset_ambient.3 b/doc/cap_reset_ambient.3 -new file mode 100644 -index 0000000..65ea3e4 ---- /dev/null -+++ b/doc/cap_reset_ambient.3 -@@ -0,0 +1 @@ -+.so man3/cap_get_proc.3 -diff --git a/doc/cap_set_ambient.3 b/doc/cap_set_ambient.3 -new file mode 100644 -index 0000000..65ea3e4 ---- /dev/null -+++ b/doc/cap_set_ambient.3 -@@ -0,0 +1 @@ -+.so man3/cap_get_proc.3 -diff --git a/pam_cap/.gitignore b/pam_cap/.gitignore -index 11806f5..05e9bbf 100644 ---- a/pam_cap/.gitignore -+++ b/pam_cap/.gitignore -@@ -1,2 +1,3 @@ - pam_cap.so --testcompile -+testlink -+test_pam_cap -diff --git a/pam_cap/Makefile b/pam_cap/Makefile -index 22f0f81..56604fd 100644 ---- a/pam_cap/Makefile -+++ b/pam_cap/Makefile -@@ -10,7 +10,7 @@ - LDLIBS += -L../libcap -lcap - - all: pam_cap.so -- $(MAKE) testcompile -+ $(MAKE) testlink - - install: all - mkdir -p -m 0755 $(FAKEROOT)$(LIBDIR)/security -@@ -22,8 +22,23 @@ - pam_cap.o: pam_cap.c - $(CC) $(CFLAGS) $(IPATH) -c $< -o $@ - --testcompile: test.c pam_cap.o -+test_pam_cap: test_pam_cap.c pam_cap.c -+ $(CC) $(CFLAGS) $(IPATH) -o $@ test_pam_cap.c $(LIBCAPLIB) $(LDFLAGS) --static -+ -+testlink: test.c pam_cap.o - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ -lpam -ldl $(LDLIBS) - -+test: pam_cap.so -+ make testlink -+ -+sudotest: test test_pam_cap -+ sudo ./test_pam_cap root 0x0 0x0 0x0 config=./capability.conf -+ sudo ./test_pam_cap root 0x0 0x0 0x0 config=./sudotest.conf -+ sudo ./test_pam_cap alpha 0x0 0x0 0x0 config=./capability.conf -+ sudo ./test_pam_cap alpha 0x0 0x1 0x80 config=./sudotest.conf -+ sudo ./test_pam_cap beta 0x0 0x1 0x0 config=./sudotest.conf -+ sudo ./test_pam_cap gamma 0x0 0x0 0x81 config=./sudotest.conf -+ sudo ./test_pam_cap delta 0x41 0x80 0x41 config=./sudotest.conf -+ - clean: -- rm -f *.o *.so testcompile *~ -+ rm -f *.o *.so testlink test_pam_cap *~ -diff --git a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c -index b1cc5cb..58ffe4a 100644 ---- a/pam_cap/pam_cap.c -+++ b/pam_cap/pam_cap.c -@@ -1,20 +1,23 @@ - /* -- * Copyright (c) 1999,2007 Andrew G. Morgan -+ * Copyright (c) 1999,2007,2019 Andrew G. Morgan - * -- * The purpose of this module is to enforce inheritable capability sets -- * for a specified user. -+ * The purpose of this module is to enforce inheritable, bounding and -+ * ambient capability sets for a specified user. - */ - - /* #define DEBUG */ - --#include --#include - #include -+#include -+#include -+#include - #include - #include -+#include -+#include - #include -- - #include -+#include - - #include - #include -@@ -22,8 +25,6 @@ - #define USER_CAP_FILE "/etc/security/capability.conf" - #define CAP_FILE_BUFFER_SIZE 4096 - #define CAP_FILE_DELIMITERS " \t\n" --#define CAP_COMBINED_FORMAT "%s all-i %s+i" --#define CAP_DROP_ALL "%s all-i" - - struct pam_cap_s { - int debug; -@@ -31,25 +32,71 @@ struct pam_cap_s { - const char *conf_filename; - }; - -+/* -+ * load_groups obtains the list all of the groups associated with the -+ * requested user: gid & supplemental groups. -+ */ -+static int load_groups(const char *user, char ***groups, int *groups_n) { -+ struct passwd *pwd; -+ gid_t grps[NGROUPS_MAX]; -+ int ngrps = NGROUPS_MAX; -+ -+ *groups = NULL; -+ *groups_n = 0; -+ -+ pwd = getpwnam(user); -+ if (pwd == NULL) { -+ return -1; -+ } -+ -+ /* must include at least pwd->pw_gid, hence < 1 test. */ -+ if (getgrouplist(user, pwd->pw_gid, grps, &ngrps) < 1) { -+ return -1; -+ } -+ -+ *groups = calloc(ngrps, sizeof(char *)); -+ int g_n = 0; -+ for (int i = 0; i < ngrps; i++) { -+ const struct group *g = getgrgid(grps[i]); -+ if (g == NULL) { -+ continue; -+ } -+ D(("noting [%s] is a member of [%s]", user, g->gr_name)); -+ (*groups)[g_n++] = strdup(g->gr_name); -+ } -+ -+ *groups_n = g_n; -+ return 0; -+} -+ - /* obtain the inheritable capabilities for the current user */ - - static char *read_capabilities_for_user(const char *user, const char *source) - { - char *cap_string = NULL; - char buffer[CAP_FILE_BUFFER_SIZE], *line; -+ char **groups; -+ int groups_n; - FILE *cap_file; - -+ if (load_groups(user, &groups, &groups_n)) { -+ D(("unknown user [%s]", user)); -+ return NULL; -+ } -+ - cap_file = fopen(source, "r"); - if (cap_file == NULL) { - D(("failed to open capability file")); -- return NULL; -+ goto defer; - } - -- while ((line = fgets(buffer, CAP_FILE_BUFFER_SIZE, cap_file))) { -- int found_one = 0; -+ int found_one = 0; -+ while (!found_one && -+ (line = fgets(buffer, CAP_FILE_BUFFER_SIZE, cap_file))) { - const char *cap_text; - -- cap_text = strtok(line, CAP_FILE_DELIMITERS); -+ char *next = NULL; -+ cap_text = strtok_r(line, CAP_FILE_DELIMITERS, &next); - - if (cap_text == NULL) { - D(("empty line")); -@@ -60,38 +107,63 @@ static char *read_capabilities_for_user(const char *user, const char *source) - continue; - } - -- while ((line = strtok(NULL, CAP_FILE_DELIMITERS))) { -- -+ /* -+ * Explore whether any of the ids are a match for the current -+ * user. -+ */ -+ while ((line = strtok_r(next, CAP_FILE_DELIMITERS, &next))) { - if (strcmp("*", line) == 0) { - D(("wildcard matched")); - found_one = 1; -- cap_string = strdup(cap_text); - break; - } - - if (strcmp(user, line) == 0) { - D(("exact match for user")); - found_one = 1; -- cap_string = strdup(cap_text); - break; - } - -- D(("user is not [%s] - skipping", line)); -- } -+ if (line[0] != '@') { -+ D(("user [%s] is not [%s] - skipping", user, line)); -+ } - -- cap_text = NULL; -- line = NULL; -+ for (int i=0; i < groups_n; i++) { -+ if (!strcmp(groups[i], line+1)) { -+ D(("user group matched [%s]", line)); -+ found_one = 1; -+ break; -+ } -+ } -+ if (found_one) { -+ break; -+ } -+ } - - if (found_one) { -+ cap_string = strdup(cap_text); - D(("user [%s] matched - caps are [%s]", user, cap_string)); -- break; - } -+ -+ cap_text = NULL; -+ line = NULL; - } - - fclose(cap_file); - -+defer: - memset(buffer, 0, CAP_FILE_BUFFER_SIZE); - -+ for (int i = 0; i < groups_n; i++) { -+ char *g = groups[i]; -+ _pam_overwrite(g); -+ _pam_drop(g); -+ } -+ if (groups != NULL) { -+ memset(groups, 0, groups_n * sizeof(char *)); -+ _pam_drop(groups); -+ } -+ - return cap_string; - } - -@@ -100,15 +172,16 @@ static char *read_capabilities_for_user(const char *user, const char *source) - * permitted+executable sets combined with the configured inheritable - * set. - */ -- - static int set_capabilities(struct pam_cap_s *cs) - { - cap_t cap_s; -- ssize_t length = 0; -- char *conf_icaps; -- char *proc_epcaps; -- char *combined_caps; -+ char *conf_caps; - int ok = 0; -+ int has_ambient = 0, has_bound = 0; -+ int *bound = NULL, *ambient = NULL; -+ cap_flag_value_t had_setpcap = 0; -+ cap_value_t max_caps = 0; -+ const cap_value_t wanted_caps[] = { CAP_SETPCAP }; - - cap_s = cap_get_proc(); - if (cap_s == NULL) { -@@ -116,82 +189,170 @@ static int set_capabilities(struct pam_cap_s *cs) - strerror(errno))); - return 0; - } -+ if (cap_get_flag(cap_s, CAP_SETPCAP, CAP_EFFECTIVE, &had_setpcap)) { -+ D(("failed to read a e capability: %s", strerror(errno))); -+ goto cleanup_cap_s; -+ } -+ if (cap_set_flag(cap_s, CAP_EFFECTIVE, 1, wanted_caps, CAP_SET) != 0) { -+ D(("unable to raise CAP_SETPCAP: %s", strerrno(errno))); -+ goto cleanup_cap_s; -+ } - -- conf_icaps = -- read_capabilities_for_user(cs->user, -- cs->conf_filename -- ? cs->conf_filename:USER_CAP_FILE ); -- if (conf_icaps == NULL) { -+ conf_caps = read_capabilities_for_user(cs->user, -+ cs->conf_filename -+ ? cs->conf_filename:USER_CAP_FILE ); -+ if (conf_caps == NULL) { - D(("no capabilities found for user [%s]", cs->user)); - goto cleanup_cap_s; - } - -- proc_epcaps = cap_to_text(cap_s, &length); -- if (proc_epcaps == NULL) { -- D(("unable to convert process capabilities to text")); -- goto cleanup_icaps; -+ ssize_t conf_caps_length = strlen(conf_caps); -+ if (!strcmp(conf_caps, "all")) { -+ /* -+ * all here is interpreted as no change/pass through, which is -+ * likely to be the same as none for sensible system defaults. -+ */ -+ ok = 1; -+ goto cleanup_caps; - } - -- /* -- * This is a pretty inefficient way to combine -- * capabilities. However, it seems to be the most straightforward -- * one, given the limitations of the POSIX.1e draft spec. The spec -- * is optimized for applications that know the capabilities they -- * want to manipulate at compile time. -- */ -- -- combined_caps = malloc(1+strlen(CAP_COMBINED_FORMAT) -- +strlen(proc_epcaps)+strlen(conf_icaps)); -- if (combined_caps == NULL) { -- D(("unable to combine capabilities into one string - no memory")); -- goto cleanup_epcaps; -+ if (cap_set_proc(cap_s) != 0) { -+ D(("unable to use CAP_SETPCAP: %s", strerrno(errno))); -+ goto cleanup_caps; -+ } -+ if (cap_reset_ambient() == 0) { -+ // Ambient set fully declared by this config. -+ has_ambient = 1; - } - -- if (!strcmp(conf_icaps, "none")) { -- sprintf(combined_caps, CAP_DROP_ALL, proc_epcaps); -- } else if (!strcmp(conf_icaps, "all")) { -- /* no change */ -- sprintf(combined_caps, "%s", proc_epcaps); -+ if (!strcmp(conf_caps, "none")) { -+ /* clearing CAP_INHERITABLE will also clear the ambient caps. */ -+ cap_clear_flag(cap_s, CAP_INHERITABLE); - } else { -- sprintf(combined_caps, CAP_COMBINED_FORMAT, proc_epcaps, conf_icaps); -- } -- D(("combined_caps=[%s]", combined_caps)); -+ /* -+ * we know we have to perform some capability operations and -+ * we need to know how many capabilities there are to do it -+ * successfully. -+ */ -+ while (cap_get_bound(max_caps) >= 0) { -+ max_caps++; -+ } -+ has_bound = (max_caps != 0); -+ if (has_bound) { -+ bound = calloc(max_caps, sizeof(int)); -+ if (has_ambient) { -+ // In kernel lineage, bound came first. -+ ambient = calloc(max_caps, sizeof(int)); -+ } -+ } -+ -+ /* -+ * Scan the configured capability string for: -+ * -+ * cap_name: add to cap_s' inheritable vector -+ * ^cap_name: add to cap_s' inheritable vector and ambient set -+ * !cap_name: drop from bounding set -+ * -+ * Setting ambient capabilities requires that we first enable -+ * the corresponding inheritable capability to set them. So, -+ * there is an order we use: parse the config line, building -+ * the inheritable, ambient and bounding sets in three separate -+ * arrays. Then, set I set A set B. Finally, at the end, we -+ * restore the E value for CAP_SETPCAP. -+ */ -+ char *token = NULL; -+ char *next = conf_caps; -+ while ((token = strtok_r(next, ",", &next))) { -+ if (strlen(token) < 4) { -+ D(("bogus cap: [%s] - ignored\n", token)); -+ goto cleanup_caps; -+ } -+ int is_a = 0, is_b = 0; -+ if (*token == '^') { -+ if (!has_ambient) { -+ D(("want ambient [%s] but kernel has no support", token)); -+ goto cleanup_caps; -+ } -+ is_a = 1; -+ token++; -+ } else if (*token == '!') { -+ if (!has_bound) { -+ D(("want bound [%s] dropped - no kernel support", token)); -+ } -+ is_b = 1; -+ token++; -+ } -+ -+ cap_value_t c; -+ if (cap_from_name(token, &c) != 0) { -+ D(("unrecognized name [%s]: %s - ignored", token, -+ strerror(errno))); -+ goto cleanup_caps; -+ } - -- cap_free(cap_s); -- cap_s = cap_from_text(combined_caps); -- _pam_overwrite(combined_caps); -- _pam_drop(combined_caps); -+ if (is_b) { -+ bound[c] = 1; -+ } else { -+ if (cap_set_flag(cap_s, CAP_INHERITABLE, 1, &c, CAP_SET)) { -+ D(("failed to raise inheritable [%s]: %s", token, -+ strerror(errno))); -+ goto cleanup_caps; -+ } -+ if (is_a) { -+ ambient[c] = 1; -+ } -+ } -+ } - - #ifdef DEBUG -- { -- char *temp = cap_to_text(cap_s, NULL); -- D(("abbreviated caps for process will be [%s]", temp)); -- cap_free(temp); -- } -+ { -+ char *temp = cap_to_text(cap_s, NULL); -+ D(("abbreviated caps for process will be [%s]", temp)); -+ cap_free(temp); -+ } - #endif /* DEBUG */ -+ } - -- if (cap_s == NULL) { -- D(("no capabilies to set")); -- } else if (cap_set_proc(cap_s) == 0) { -- D(("capabilities were set correctly")); -- ok = 1; -- } else { -+ if (cap_set_proc(cap_s)) { - D(("failed to set specified capabilities: %s", strerror(errno))); -+ } else { -+ for (cap_value_t c = 0; c < max_caps; c++) { -+ if (ambient != NULL && ambient[c]) { -+ cap_set_ambient(c, CAP_SET); -+ } -+ if (bound != NULL && bound[c]) { -+ cap_drop_bound(c); -+ } -+ } -+ ok = 1; - } - --cleanup_epcaps: -- cap_free(proc_epcaps); -- --cleanup_icaps: -- _pam_overwrite(conf_icaps); -- _pam_drop(conf_icaps); -+cleanup_caps: -+ if (has_ambient) { -+ memset(ambient, 0, max_caps * sizeof(*ambient)); -+ _pam_drop(ambient); -+ ambient = NULL; -+ } -+ if (has_bound) { -+ memset(bound, 0, max_caps * sizeof(*bound)); -+ _pam_drop(bound); -+ bound = NULL; -+ } -+ memset(conf_caps, 0, conf_caps_length); -+ _pam_drop(conf_caps); - - cleanup_cap_s: -+ if (!had_setpcap) { -+ /* Only need to lower if it wasn't raised by caller */ -+ if (!cap_set_flag(cap_s, CAP_EFFECTIVE, 1, wanted_caps, -+ CAP_CLEAR)) { -+ cap_set_proc(cap_s); -+ } -+ } - if (cap_s) { - cap_free(cap_s); - cap_s = NULL; - } -- - return ok; - } - -@@ -210,11 +371,8 @@ static void _pam_log(int err, const char *format, ...) - - static void parse_args(int argc, const char **argv, struct pam_cap_s *pcs) - { -- int ctrl=0; -- - /* step through arguments */ -- for (ctrl=0; argc-- > 0; ++argv) { -- -+ for (; argc-- > 0; ++argv) { - if (!strcmp(*argv, "debug")) { - pcs->debug = 1; - } else if (!memcmp(*argv, "config=", 7)) { -@@ -222,23 +380,25 @@ static void parse_args(int argc, const char **argv, struct pam_cap_s *pcs) - } else { - _pam_log(LOG_ERR, "unknown option; %s", *argv); - } -- - } - } - -+/* -+ * pam_sm_authenticate parses the config file with respect to the user -+ * being authenticated and determines if they are covered by any -+ * capability inheritance rules. -+ */ - int pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) - { - int retval; - struct pam_cap_s pcs; -- char *conf_icaps; -+ char *conf_caps; - - memset(&pcs, 0, sizeof(pcs)); -- - parse_args(argc, argv, &pcs); - - retval = pam_get_user(pamh, &pcs.user, NULL); -- - if (retval == PAM_CONV_AGAIN) { - D(("user conversation is not available yet")); - memset(&pcs, 0, sizeof(pcs)); -@@ -251,24 +411,22 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, - return PAM_AUTH_ERR; - } - -- conf_icaps = -- read_capabilities_for_user(pcs.user, -- pcs.conf_filename -- ? pcs.conf_filename:USER_CAP_FILE ); -- -+ conf_caps = read_capabilities_for_user(pcs.user, -+ pcs.conf_filename -+ ? pcs.conf_filename:USER_CAP_FILE ); - memset(&pcs, 0, sizeof(pcs)); - -- if (conf_icaps) { -+ if (conf_caps) { - D(("it appears that there are capabilities for this user [%s]", -- conf_icaps)); -+ conf_caps)); - - /* We could also store this as a pam_[gs]et_data item for use - by the setcred call to follow. As it is, there is a small - race associated with a redundant read. Oh well, if you - care, send me a patch.. */ - -- _pam_overwrite(conf_icaps); -- _pam_drop(conf_icaps); -+ _pam_overwrite(conf_caps); -+ _pam_drop(conf_caps); - - return PAM_SUCCESS; - -@@ -280,6 +438,10 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, - } - } - -+/* -+ * pam_sm_setcred applies inheritable capabilities loaded by the -+ * pam_sm_authenticate pass for the user. -+ */ - int pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc, const char **argv) - { -@@ -292,18 +454,15 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, - } - - memset(&pcs, 0, sizeof(pcs)); -- - parse_args(argc, argv, &pcs); - - retval = pam_get_item(pamh, PAM_USER, (const void **)&pcs.user); - if ((retval != PAM_SUCCESS) || (pcs.user == NULL) || !(pcs.user[0])) { -- - D(("user's name is not set")); - return PAM_AUTH_ERR; - } - - retval = set_capabilities(&pcs); -- - memset(&pcs, 0, sizeof(pcs)); - - return (retval ? PAM_SUCCESS:PAM_IGNORE ); -diff --git a/pam_cap/sudotest.conf b/pam_cap/sudotest.conf -new file mode 100644 -index 0000000..ff528ce ---- /dev/null -+++ b/pam_cap/sudotest.conf -@@ -0,0 +1,23 @@ -+# only root -+all root -+ -+# this should fire for beta only -+!cap_chown beta -+ -+# the next one should snag gamma since beta done -+cap_setuid,cap_chown @three -+ -+# neither of these should fire -+cap_chown beta gamma -+ -+# just alpha -+!cap_chown,cap_setuid @one -+ -+# not this one -+^cap_setuid alpha -+ -+# this should fire -+^cap_chown,^cap_setgid,!cap_setuid delta -+ -+# not this one -+cap_setuid @four -diff --git a/pam_cap/test_pam_cap.c b/pam_cap/test_pam_cap.c -new file mode 100644 -index 0000000..2f519f1 ---- /dev/null -+++ b/pam_cap/test_pam_cap.c -@@ -0,0 +1,200 @@ -+/* -+ * Copyright (c) 2019 Andrew G. Morgan -+ * -+ * This test inlines the pam_cap module and runs test vectors against -+ * it. -+ */ -+ -+#include "./pam_cap.c" -+ -+const char *test_groups[] = { -+ "root", "one", "two", "three", "four", "five", "six", "seven" -+}; -+#define n_groups sizeof(test_groups)/sizeof(*test_groups) -+ -+const char *test_users[] = { -+ "root", "alpha", "beta", "gamma", "delta" -+}; -+#define n_users sizeof(test_users)/sizeof(*test_users) -+ -+// Note about memberships: -+// -+// user gid suppl groups -+// root root -+// alpha one two -+// beta two three four -+// gamma three four five six -+// delta four five six seven [eight] -+// -+ -+static char *test_user; -+ -+int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { -+ *user = test_user; -+ if (*user == NULL) { -+ return PAM_CONV_AGAIN; -+ } -+ return PAM_SUCCESS; -+} -+ -+int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item) { -+ if (item_type != PAM_USER) { -+ errno = EINVAL; -+ return -1; -+ } -+ *item = test_user; -+ return 0; -+} -+ -+int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) { -+ int i,j; -+ for (i = 0; i < n_users; i++) { -+ if (strcmp(user, test_users[i]) == 0) { -+ *ngroups = i+1; -+ break; -+ } -+ } -+ if (i == n_users) { -+ return -1; -+ } -+ groups[0] = i; -+ for (j = 1; j < *ngroups; j++) { -+ groups[j] = i+j; -+ } -+ return *ngroups; -+} -+ -+static struct group gr; -+struct group *getgrgid(gid_t gid) { -+ if (gid >= n_groups) { -+ errno = EINVAL; -+ return NULL; -+ } -+ gr.gr_name = strdup(test_groups[gid]); -+ return &gr; -+} -+ -+static struct passwd pw; -+struct passwd *getpwnam(const char *name) { -+ for (int i = 0; i < n_users; i++) { -+ if (strcmp(name, test_users[i]) == 0) { -+ pw.pw_gid = i; -+ return &pw; -+ } -+ } -+ return NULL; -+} -+ -+/* we'll use these to keep track of the three vectors - only use -+ lowest 64 bits */ -+ -+#define A 0 -+#define B 1 -+#define I 2 -+ -+/* -+ * load_vectors caches a copy of the lowest 64 bits of the inheritable -+ * cap vectors -+ */ -+static void load_vectors(unsigned long int bits[3]) { -+ memset(bits, 0, 3*sizeof(unsigned long int)); -+ cap_t prev = cap_get_proc(); -+ for (int i = 0; i < 64; i++) { -+ unsigned long int mask = (1ULL << i); -+ int v = cap_get_bound(i); -+ if (v < 0) { -+ break; -+ } -+ bits[B] |= v ? mask : 0; -+ cap_flag_value_t u; -+ if (cap_get_flag(prev, i, CAP_INHERITABLE, &u) != 0) { -+ break; -+ } -+ bits[I] |= u ? mask : 0; -+ v = cap_get_ambient(i); -+ if (v > 0) { -+ bits[A] |= mask; -+ } -+ } -+ cap_free(prev); -+} -+ -+/* -+ * args: user a b i config-args... -+ */ -+int main(int argc, char *argv[]) { -+ unsigned long int before[3], change[3], after[3]; -+ -+ /* -+ * Start out with a cleared inheritable set. -+ */ -+ cap_t orig = cap_get_proc(); -+ cap_clear_flag(orig, CAP_INHERITABLE); -+ cap_set_proc(orig); -+ -+ change[A] = strtoul(argv[2], NULL, 0); -+ change[B] = strtoul(argv[3], NULL, 0); -+ change[I] = strtoul(argv[4], NULL, 0); -+ -+ void* args_for_pam = argv+4; -+ -+ int status = pam_sm_authenticate(NULL, 0, argc-4, -+ (const char **) args_for_pam); -+ if (status != PAM_INCOMPLETE) { -+ printf("failed to recognize no username\n"); -+ exit(1); -+ } -+ -+ test_user = argv[1]; -+ -+ status = pam_sm_authenticate(NULL, 0, argc-4, (const char **) args_for_pam); -+ if (status == PAM_IGNORE) { -+ if (strcmp(test_user, "root") == 0) { -+ exit(0); -+ } -+ printf("unconfigured non-root user: %s\n", test_user); -+ exit(1); -+ } -+ if (status != PAM_SUCCESS) { -+ printf("failed to recognize username\n"); -+ exit(1); -+ } -+ -+ // Now it is time to execute the credential setting -+ load_vectors(before); -+ -+ status = pam_sm_setcred(NULL, PAM_ESTABLISH_CRED, argc-4, -+ (const char **) args_for_pam); -+ -+ load_vectors(after); -+ -+ printf("before: A=0x%016lx B=0x%016lx I=0x%016lx\n", -+ before[A], before[B], before[I]); -+ -+ long unsigned int dA = before[A] ^ after[A]; -+ long unsigned int dB = before[B] ^ after[B]; -+ long unsigned int dI = before[I] ^ after[I]; -+ -+ printf("diff : A=0x%016lx B=0x%016lx I=0x%016lx\n", dA, dB, dI); -+ printf("after : A=0x%016lx B=0x%016lx I=0x%016lx\n", -+ after[A], after[B], after[I]); -+ -+ int failure = 0; -+ if (after[A] != change[A]) { -+ printf("Ambient set error: got=0x%016lx, want=0x%016lx\n", -+ after[A], change[A]); -+ failure = 1; -+ } -+ if (dB != change[B]) { -+ printf("Bounding set error: got=0x%016lx, want=0x%016lx\n", -+ after[B], before[B] ^ change[B]); -+ failure = 1; -+ } -+ if (after[I] != change[I]) { -+ printf("Inheritable set error: got=0x%016lx, want=0x%016lx\n", -+ after[I], change[I]); -+ failure = 1; -+ } -+ -+ exit(failure); -+} --- -cgit 1.2.3-1.el7 - diff --git a/libcap-2.26.tar.gz b/libcap-2.26.tar.gz deleted file mode 100644 index 8ab0770d180b96e3b647d6ae4e0dab8b3b17f202..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77163 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/dev/null)" ]; then echo yes ; else echo no ; fi) ++GOLANG ?= no + ifeq ($(GOLANG),yes) + GOROOT ?= $(shell $(GO) env GOROOT) + GOCGO ?= $(shell if [ "$(shell $(GO) env CGO_ENABLED)" = 1 ]; then echo yes ; else echo no ; fi) diff --git a/libcap-PAM_REINITIALIZE_CRED.patch b/libcap-PAM_REINITIALIZE_CRED.patch deleted file mode 100644 index 3e99baf..0000000 --- a/libcap-PAM_REINITIALIZE_CRED.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -urN libcap-2.25/pam_cap/pam_cap.c libcap-2.25_patched/pam_cap/pam_cap.c ---- libcap-2.25/pam_cap/pam_cap.c 2013-12-16 05:46:28.000000000 +0100 -+++ libcap-2.25_patched/pam_cap/pam_cap.c 2019-03-04 16:18:23.440525062 +0100 -@@ -286,7 +286,7 @@ - int retval; - struct pam_cap_s pcs; - -- if (!(flags & PAM_ESTABLISH_CRED)) { -+ if (!(flags & (PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED))) { - D(("we don't handle much in the way of credentials")); - return PAM_IGNORE; - } diff --git a/libcap-abi-compatibility.patch b/libcap-abi-compatibility.patch new file mode 100644 index 0000000..88b4601 --- /dev/null +++ b/libcap-abi-compatibility.patch @@ -0,0 +1,37 @@ +diff --color -ru a/libcap/cap_text.c b/libcap/cap_text.c +--- a/libcap/cap_text.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/libcap/cap_text.c 2021-12-15 13:03:44.993774400 +0100 +@@ -15,7 +15,7 @@ + #define LIBCAP_PLEASE_INCLUDE_ARRAY + #include "libcap.h" + +-static char const *_cap_names[__CAP_BITS] = LIBCAP_CAP_NAMES; ++extern char const *_cap_names[__CAP_BITS]; + + #include + #include +diff --color -ru a/libcap/_makenames.c b/libcap/_makenames.c +--- a/libcap/_makenames.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/libcap/_makenames.c 2021-12-15 12:47:07.921408357 +0100 +@@ -66,17 +66,17 @@ + "#define __CAP_NAME_SIZE %d\n" + "\n" + "#ifdef LIBCAP_PLEASE_INCLUDE_ARRAY\n" +- "#define LIBCAP_CAP_NAMES { \\\n", maxcaps, maxlength+1); ++ " char const *_cap_names[__CAP_BITS] = {\n", maxcaps, maxlength+1); + + for (i=0; i= 0 && (x) <= CAP_LAST_CAP) - -diff --color -ruN a/Makefile b/Makefile ---- a/Makefile 2018-09-15 23:51:38.000000000 +0200 -+++ b/Makefile 2021-06-10 10:07:30.872573023 +0200 -@@ -33,7 +33,10 @@ - test: all - cd progs && sudo ./quicktest.sh - --morganrelease: distclean -+distcheck: -+ ./distcheck.sh -+ -+morganrelease: distclean distcheck - @echo "sign the tag twice: older DSA key; and newer RSA kernel.org key" - git tag -u D41A6DF2 -s libcap-$(VERSION).$(MINOR) -m "This is libcap-$(VERSION).$(MINOR)" - git tag -u E2CCF3F4 -s libcap-korg-$(VERSION).$(MINOR) -m "This is libcap-$(VERSION).$(MINOR)" diff --git a/libcap-fix-ambient-caps.patch b/libcap-fix-ambient-caps.patch new file mode 100644 index 0000000..de08d03 --- /dev/null +++ b/libcap-fix-ambient-caps.patch @@ -0,0 +1,147 @@ +diff --color -ru a/libcap/cap_proc.c b/libcap/cap_proc.c +--- a/libcap/cap_proc.c 2021-12-22 12:33:20.739126763 +0100 ++++ b/libcap/cap_proc.c 2021-12-22 12:33:53.195733115 +0100 +@@ -406,6 +406,29 @@ + } + + /* ++ * 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 \ +diff --color -ru a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h +--- a/libcap/include/sys/capability.h 2021-02-05 06:52:17.000000000 +0100 ++++ b/libcap/include/sys/capability.h 2021-12-22 12:33:53.196733134 +0100 +@@ -175,6 +175,11 @@ + 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[]); + +diff --color -ru a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c +--- a/pam_cap/pam_cap.c 2021-12-22 12:33:20.740126781 +0100 ++++ b/pam_cap/pam_cap.c 2021-12-22 12:33:53.196733134 +0100 +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -33,8 +34,11 @@ + + struct pam_cap_s { + int debug; ++ int keepcaps; ++ int defer; + const char *user; + const char *conf_filename; ++ pam_handle_t *pamh; + }; + + /* +@@ -178,6 +182,33 @@ + } + + /* ++ * This is the "defer" cleanup function that actually applies the IAB ++ * tuple. This happens really late in the PAM session, hopefully after ++ * the application has performed its setuid() function. ++ */ ++static void iab_apply(pam_handle_t *pamh, void *data, int error_status) ++{ ++ cap_iab_t iab = data; ++ int retval = error_status & ~(PAM_DATA_REPLACE|PAM_DATA_SILENT); ++ ++ data = NULL; ++ if (error_status & PAM_DATA_REPLACE) { ++ goto done; ++ } ++ ++ if (retval != PAM_SUCCESS || !(error_status & PAM_DATA_SILENT)) { ++ goto done; ++ } ++ ++ if (cap_iab_set_proc(iab) != 0) { ++ D(("IAB setting failed")); ++ } ++ ++done: ++ cap_free(iab); ++} ++ ++/* + * Set capabilities for current process to match the current + * permitted+executable sets combined with the configured inheritable + * set. +@@ -230,12 +261,21 @@ + goto cleanup_conf; + } + +- if (!cap_iab_set_proc(iab)) { ++ if (cs->defer) { ++ D(("configured to delay applying IAB")); ++ pam_set_data(cs->pamh, "pam_cap_iab", iab, iab_apply); ++ iab = NULL; ++ } else if (!cap_iab_set_proc(iab)) { + D(("able to set the IAB [%s] value", conf_caps)); + ok = 1; + } + cap_free(iab); + ++ if (cs->keepcaps) { ++ D(("setting keepcaps")); ++ (void) cap_prctlw(PR_SET_KEEPCAPS, 1, 0, 0, 0, 0); ++ } ++ + cleanup_conf: + memset(conf_caps, 0, conf_caps_length); + _pam_drop(conf_caps); +@@ -268,6 +308,10 @@ + pcs->debug = 1; + } else if (!strncmp(*argv, "config=", 7)) { + pcs->conf_filename = 7 + *argv; ++ } else if (!strcmp(*argv, "keepcaps")) { ++ pcs->keepcaps = 1; ++ } else if (!strcmp(*argv, "defer")) { ++ pcs->defer = 1; + } else { + _pam_log(LOG_ERR, "unknown option; %s", *argv); + } +@@ -353,6 +397,7 @@ + return PAM_AUTH_ERR; + } + ++ pcs.pamh = pamh; + retval = set_capabilities(&pcs); + memset(&pcs, 0, sizeof(pcs)); + diff --git a/libcap-static-analysis.patch b/libcap-static-analysis.patch new file mode 100644 index 0000000..c72ca73 --- /dev/null +++ b/libcap-static-analysis.patch @@ -0,0 +1,494 @@ +diff --color -ru a/libcap/cap_proc.c b/libcap/cap_proc.c +--- a/libcap/cap_proc.c 2022-01-28 12:42:39.726331628 +0100 ++++ b/libcap/cap_proc.c 2022-01-28 12:44:05.007936110 +0100 +@@ -712,6 +712,10 @@ + cap_value_t c; + int raising = 0; + ++ 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] | +diff --color -ru a/libcap/cap_text.c b/libcap/cap_text.c +--- a/libcap/cap_text.c 2022-01-28 12:42:39.725331609 +0100 ++++ b/libcap/cap_text.c 2022-01-28 12:44:05.008936129 +0100 +@@ -160,6 +160,7 @@ + cap_blks = _LINUX_CAPABILITY_U32S_3; + break; + default: ++ cap_free(res); + errno = EINVAL; + return NULL; + } +@@ -398,6 +399,9 @@ + 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; +@@ -450,6 +454,9 @@ + 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; +@@ -549,6 +556,9 @@ + 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++) { +diff --color -ru a/libcap/_makenames.c b/libcap/_makenames.c +--- a/libcap/_makenames.c 2022-01-28 12:42:39.725331609 +0100 ++++ b/libcap/_makenames.c 2022-01-28 13:07:28.700817691 +0100 +@@ -45,10 +45,14 @@ + if (maxcaps <= list[i].index) { + maxcaps = list[i].index + 1; + } +- if (list[i].index >= pointers_avail) { ++ 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); +diff --color -ru a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c +--- a/pam_cap/pam_cap.c 2022-01-28 12:42:39.726331628 +0100 ++++ b/pam_cap/pam_cap.c 2022-01-28 12:44:05.009936148 +0100 +@@ -64,6 +64,9 @@ + } + + *groups = calloc(ngrps, sizeof(char *)); ++ if (*groups == NULL) { ++ return -1; ++ } + int g_n = 0, i; + for (i = 0; i < ngrps; i++) { + const struct group *g = getgrgid(grps[i]); +@@ -249,7 +252,7 @@ + if (!cap_set_proc(cap_s)) { + ok = 1; + } +- goto cleanup_cap_s; ++ goto cleanup_conf; + } + + iab = cap_iab_from_text(conf_caps); +@@ -278,10 +281,9 @@ + _pam_drop(conf_caps); + + cleanup_cap_s: +- if (cap_s) { +- cap_free(cap_s); +- cap_s = NULL; +- } ++ cap_free(cap_s); ++ cap_s = NULL; ++ + return ok; + } + +diff --color -ru a/progs/capsh.c b/progs/capsh.c +--- a/progs/capsh.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/progs/capsh.c 2022-01-28 13:06:15.803465885 +0100 +@@ -34,6 +34,35 @@ + + #define MAX_GROUPS 100 /* max number of supplementary groups for user */ + ++/* parse a non-negative integer with some error handling */ ++static unsigned long nonneg_uint(const char *text, const char *prefix, int *ok) ++{ ++ char *remains; ++ unsigned long value; ++ ssize_t len = strlen(text); ++ ++ if (len == 0 || *text == '-') { ++ goto fail; ++ } ++ value = strtoul(text, &remains, 0); ++ if (*remains) { ++ goto fail; ++ } ++ if (ok != NULL) { ++ *ok = 1; ++ } ++ return value; ++ ++fail: ++ if (ok == NULL) { ++ fprintf(stderr, "%s: want non-negative integer, got \"%s\"\n", ++ prefix, text); ++ exit(1); ++ } ++ *ok = 0; ++ return 0; ++} ++ + static char *binary(unsigned long value) + { + static char string[8*sizeof(unsigned long) + 1]; +@@ -100,7 +129,16 @@ + display_prctl_set("Bounding", cap_get_bound); + display_prctl_set("Ambient", cap_get_ambient); + iab = cap_iab_get_proc(); ++ if (iab == NULL) { ++ perror("failed to get IAB for process"); ++ exit(1); ++ } + text = cap_iab_to_text(iab); ++ if (text == NULL) { ++ perror("failed to obtain text for IAB"); ++ cap_free(iab); ++ exit(1); ++ } + printf("Current IAB: %s\n", text); + cap_free(text); + cap_free(iab); +@@ -336,8 +374,8 @@ + */ + static char *find_self(const char *arg0) + { +- int i; +- char *parts, *dir, *scratch; ++ int i, status=1; ++ char *p = NULL, *parts, *dir, *scratch; + const char *path; + + for (i = strlen(arg0)-1; i >= 0 && arg0[i] != '/'; i--); +@@ -352,21 +390,45 @@ + } + + parts = strdup(path); ++ if (parts == NULL) { ++ fprintf(stderr, "insufficient memory for parts of path\n"); ++ exit(1); ++ } ++ + scratch = malloc(2+strlen(path)+strlen(arg0)); +- if (parts == NULL || scratch == NULL) { ++ if (scratch == NULL) { + fprintf(stderr, "insufficient memory for path building\n"); +- exit(1); ++ goto free_parts; + } + +- for (i=0; (dir = strtok(parts, ":")); parts = NULL) { ++ for (p = parts; (dir = strtok(p, ":")); p = NULL) { + sprintf(scratch, "%s/%s", dir, arg0); + if (access(scratch, X_OK) == 0) { +- return scratch; ++ status = 0; ++ break; + } + } ++ if (status) { ++ fprintf(stderr, "unable to find executable '%s' in PATH\n", arg0); ++ free(scratch); ++ } + +- fprintf(stderr, "unable to find executable '%s' in PATH\n", arg0); +- exit(1); ++free_parts: ++ free(parts); ++ if (status) { ++ exit(status); ++ } ++ return scratch; ++} ++ ++static long safe_sysconf(int name) ++{ ++ long ans = sysconf(name); ++ if (ans <= 0) { ++ fprintf(stderr, "sysconf(%d) returned a non-positive number: %ld\n", name, ans); ++ exit(1); ++ } ++ return ans; + } + + int main(int argc, char *argv[], char *envp[]) +@@ -378,6 +440,10 @@ + child = 0; + + char *temp_name = cap_to_name(cap_max_bits() - 1); ++ if (temp_name == NULL) { ++ perror("obtaining highest capability name"); ++ exit(1); ++ } + if (temp_name[0] != 'c') { + printf("WARNING: libcap needs an update (cap=%d should have a name).\n", + cap_max_bits() - 1); +@@ -573,7 +639,7 @@ + unsigned value; + int set; + +- value = strtoul(argv[i]+7, NULL, 0); ++ value = nonneg_uint(argv[i]+7, "invalid --keep value", NULL); + set = prctl(PR_SET_KEEPCAPS, value); + if (set < 0) { + fprintf(stderr, "prctl(PR_SET_KEEPCAPS, %u) failed: %s\n", +@@ -617,7 +683,9 @@ + * Given we are now in a new directory tree, its good practice + * to start off in a sane location + */ +- status = chdir("/"); ++ if (status == 0) { ++ status = chdir("/"); ++ } + + cap_free(orig); + +@@ -628,7 +696,7 @@ + } else if (!strncmp("--secbits=", argv[i], 10)) { + unsigned value; + int status; +- value = strtoul(argv[i]+10, NULL, 0); ++ value = nonneg_uint(argv[i]+10, "invalid --secbits value", NULL); + status = cap_set_secbits(value); + if (status < 0) { + fprintf(stderr, "failed to set securebits to 0%o/0x%x\n", +@@ -641,7 +709,7 @@ + fprintf(stderr, "already forked\n"); + exit(1); + } +- value = strtoul(argv[i]+10, NULL, 0); ++ value = nonneg_uint(argv[i]+10, "invalid --forkfor value", NULL); + if (value == 0) { + goto usage; + } +@@ -657,7 +725,8 @@ + pid_t result; + unsigned value; + +- value = strtoul(argv[i]+9, NULL, 0); ++ value = nonneg_uint(argv[i]+9, "invalid --killit signo value", ++ NULL); + if (!child) { + fprintf(stderr, "no forked process to kill\n"); + exit(1); +@@ -683,7 +752,7 @@ + unsigned value; + int status; + +- value = strtoul(argv[i]+6, NULL, 0); ++ value = nonneg_uint(argv[i]+6, "invalid --uid value", NULL); + status = setuid(value); + if (status < 0) { + fprintf(stderr, "Failed to set uid=%u: %s\n", +@@ -694,7 +763,7 @@ + unsigned value; + int status; + +- value = strtoul(argv[i]+10, NULL, 0); ++ value = nonneg_uint(argv[i]+10, "invalid --cap-uid value", NULL); + status = cap_setuid(value); + if (status < 0) { + fprintf(stderr, "Failed to cap_setuid(%u): %s\n", +@@ -705,7 +774,7 @@ + unsigned value; + int status; + +- value = strtoul(argv[i]+6, NULL, 0); ++ value = nonneg_uint(argv[i]+6, "invalid --gid value", NULL); + status = setgid(value); + if (status < 0) { + fprintf(stderr, "Failed to set gid=%u: %s\n", +@@ -718,14 +787,14 @@ + gid_t *group_list; + int g_count; + +- length = sysconf(_SC_GETGR_R_SIZE_MAX); ++ length = safe_sysconf(_SC_GETGR_R_SIZE_MAX); + buf = calloc(1, length); + if (NULL == buf) { + fprintf(stderr, "No memory for [%s] operation\n", argv[i]); + exit(1); + } + +- max_groups = sysconf(_SC_NGROUPS_MAX); ++ max_groups = safe_sysconf(_SC_NGROUPS_MAX); + group_list = calloc(max_groups, sizeof(gid_t)); + if (NULL == group_list) { + fprintf(stderr, "No memory for gid list\n"); +@@ -741,8 +810,7 @@ + } + if (!isdigit(*ptr)) { + struct group *g, grp; +- getgrnam_r(ptr, &grp, buf, length, &g); +- if (NULL == g) { ++ if (getgrnam_r(ptr, &grp, buf, length, &g) || NULL == g) { + fprintf(stderr, "Failed to identify gid for group [%s]\n", ptr); + exit(1); + } +@@ -835,6 +903,7 @@ + argv[argc] = NULL; + execve(argv[i], argv+i, envp); + fprintf(stderr, "execve '%s' failed!\n", argv[i]); ++ free(argv[i]); + exit(1); + } else if (!strncmp("--shell=", argv[i], 8)) { + shell = argv[i]+8; +@@ -885,7 +954,7 @@ + } else if (!strncmp("--is-uid=", argv[i], 9)) { + unsigned value; + uid_t uid; +- value = strtoul(argv[i]+9, NULL, 0); ++ value = nonneg_uint(argv[i]+9, "invalid --is-uid value", NULL); + uid = getuid(); + if (uid != value) { + fprintf(stderr, "uid: got=%d, want=%d\n", uid, value); +@@ -894,7 +963,7 @@ + } else if (!strncmp("--is-gid=", argv[i], 9)) { + unsigned value; + gid_t gid; +- value = strtoul(argv[i]+9, NULL, 0); ++ value = nonneg_uint(argv[i]+9, "invalid --is-gid value", NULL); + gid = getgid(); + if (gid != value) { + fprintf(stderr, "gid: got=%d, want=%d\n", gid, value); +diff --color -ru a/progs/getcap.c b/progs/getcap.c +--- a/progs/getcap.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/progs/getcap.c 2022-01-28 12:44:05.009936148 +0100 +@@ -110,11 +110,11 @@ + + for (i=optind; argv[i] != NULL; i++) { + struct stat stbuf; +- +- if (lstat(argv[i], &stbuf) != 0) { +- fprintf(stderr, "%s (%s)\n", argv[i], strerror(errno)); ++ char *arg = argv[i]; ++ if (lstat(arg, &stbuf) != 0) { ++ fprintf(stderr, "%s (%s)\n", arg, strerror(errno)); + } else if (recursive) { +- nftw(argv[i], do_getcap, 20, FTW_PHYS); ++ nftw(arg, do_getcap, 20, FTW_PHYS); + } else { + int tflag = S_ISREG(stbuf.st_mode) ? FTW_F : + (S_ISLNK(stbuf.st_mode) ? FTW_SL : FTW_NS); +diff --color -ru a/progs/setcap.c b/progs/setcap.c +--- a/progs/setcap.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/progs/setcap.c 2022-01-28 12:44:05.009936148 +0100 +@@ -166,9 +166,12 @@ + } + + cap_on_file = cap_get_file(*++argv); +- + if (cap_on_file == NULL) { + cap_on_file = cap_from_text("="); ++ if (cap_on_file == NULL) { ++ perror("unable to use missing capability"); ++ exit(1); ++ } + } + + cmp = cap_compare(cap_on_file, cap_d); +diff --color -ru a/psx/psx.c b/psx/psx.c +--- a/psx/psx.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/psx/psx.c 2022-01-28 12:44:05.009936148 +0100 +@@ -107,6 +107,10 @@ + */ + static void *psx_do_registration(void) { + registered_thread_t *node = calloc(1, sizeof(registered_thread_t)); ++ if (node == NULL) { ++ perror("unable to register psx handler"); ++ exit(1); ++ } + pthread_mutex_init(&node->mu, NULL); + node->thread = pthread_self(); + pthread_setspecific(psx_action_key, node); +@@ -454,6 +458,10 @@ + int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) { + psx_starter_t *starter = calloc(1, sizeof(psx_starter_t)); ++ if (starter == NULL) { ++ perror("failed at thread creation"); ++ exit(1); ++ } + starter->fn = start_routine; + starter->arg = arg; + /* +diff --color -ru a/tests/libcap_launch_test.c b/tests/libcap_launch_test.c +--- a/tests/libcap_launch_test.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/tests/libcap_launch_test.c 2022-01-28 12:44:05.010936167 +0100 +@@ -93,6 +93,10 @@ + printf("[%d] test should %s\n", i, + v->result ? "generate error" : "work"); + cap_launch_t attr = cap_new_launcher(v->args[0], v->args, v->envp); ++ if (attr == NULL) { ++ perror("failed to obtain launcher"); ++ exit(1); ++ } + if (v->chroot) { + cap_launcher_set_chroot(attr, v->chroot); + } +diff --color -ru a/tests/libcap_psx_test.c b/tests/libcap_psx_test.c +--- a/tests/libcap_psx_test.c 2021-02-05 06:52:17.000000000 +0100 ++++ b/tests/libcap_psx_test.c 2022-01-28 12:55:55.887807887 +0100 +@@ -16,8 +16,15 @@ + usleep(1234); + pid_t pid = fork(); + cap_t start = cap_get_proc(); ++ if (start == NULL) { ++ perror("FAILED: unable to start"); ++ exit(1); ++ } + if (pid == 0) { +- cap_set_proc(start); ++ if (cap_set_proc(start)) { ++ perror("setting empty caps failed"); ++ exit(1); ++ } + exit(0); + } + int res; +@@ -27,6 +34,7 @@ + exit(1); + } + cap_set_proc(start); ++ cap_free(start); + return NULL; + } + +@@ -35,6 +43,10 @@ + printf("hello libcap and libpsx "); + fflush(stdout); + cap_t start = cap_get_proc(); ++ if (start == NULL) { ++ perror("FAILED: to actually start"); ++ exit(1); ++ } + pthread_t ignored[10]; + for (i = 0; i < 10; i++) { + pthread_create(&ignored[i], NULL, thread_fork_exit, NULL); +@@ -42,7 +54,10 @@ + for (i = 0; i < 10; i++) { + printf("."); /* because of fork, this may print double */ + fflush(stdout); /* try to limit the above effect */ +- cap_set_proc(start); ++ if (cap_set_proc(start)) { ++ perror("failed to set proc"); ++ exit(1); ++ } + usleep(1000); + } + printf(" PASSED\n"); diff --git a/libcap.spec b/libcap.spec index b869d05..0b9e464 100644 --- a/libcap.spec +++ b/libcap.spec @@ -1,20 +1,19 @@ Name: libcap -Version: 2.26 -Release: 5%{?dist} +Version: 2.48 +Release: 2%{?dist} Summary: Library for getting and setting POSIX.1e capabilities URL: https://sites.google.com/site/fullycapable/ -License: GPLv2 +License: BSD or GPLv2 Group: System Environment/Libraries Source: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/snapshot/%{name}-%{version}.tar.gz -# http://manned.org/getpcaps/299a4949/src: -Source1: getpcaps.8 -Patch0: %{name}-2.25-buildflags.patch -Patch1: %{name}-PAM_REINITIALIZE_CRED.patch -Patch2: %{name}-2.26-ambient-caps.patch -Patch3: %{name}-add-new-caps.patch +Patch0: %{name}-2.48-buildflags.patch +Patch1: %{name}-abi-compatibility.patch +Patch2: %{name}-static-analysis.patch +Patch3: %{name}-fix-ambient-caps.patch BuildRequires: libattr-devel pam-devel perl-interpreter +BuildRequires: make %description libcap is a library for getting and setting POSIX.1e (formerly POSIX 6) @@ -47,11 +46,7 @@ Install libcap-devel if you want to develop or compile applications using libcap. %prep -%setup -q -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 +%autosetup -p1 %build # libcap can not be build with _smp_mflags: @@ -67,7 +62,6 @@ make install RAISE_SETFCAP=no \ mkdir -p %{buildroot}/%{_mandir}/man{2,3,8} mv -f doc/*.3 %{buildroot}/%{_mandir}/man3/ -cp -f %{SOURCE1} %{buildroot}/%{_mandir}/man8/ chmod +x %{buildroot}/%{_libdir}/*.so.* @@ -85,14 +79,22 @@ chmod +x %{buildroot}/%{_libdir}/*.so.* %files static %{_libdir}/libcap.a +%{_libdir}/libpsx.a %files devel %{_includedir}/* %{_libdir}/*.so %{_mandir}/man3/* %{_libdir}/pkgconfig/libcap.pc +%{_libdir}/pkgconfig/libpsx.pc %changelog +* Fri Jan 28 2022 Zoltan Fridrich - 2.48-2 +- rebase to 2.48 + resolves: rhbz#2032813 +- fix ambient capabilities for non-root users + resolves: rhbz#1950187 + * Thu Jun 10 2021 Zoltan Fridrich - 2.26-5 - added CAP_PERFMON, CAP_BPF and CAP_CHECKPOINT_RESTORE capabilities resolves: rhbz#1946982 rhbz#1921576 -- Gitee