From 5825377672df0d8fe1d4e8403c7a73e4197f35d7 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 1 Mar 2022 08:15:24 -0500 Subject: [PATCH] import libcap-2.48-8.el9 --- SOURCES/libcap-disable-golang.patch | 12 ++ SOURCES/libcap-fix-ambient-caps.patch | 147 ++++++++++++++++++ SOURCES/libcap-static-analysis-fix-3.patch | 169 +++++++++++++++++++++ SPECS/libcap.spec | 9 +- 4 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 SOURCES/libcap-disable-golang.patch create mode 100644 SOURCES/libcap-fix-ambient-caps.patch create mode 100644 SOURCES/libcap-static-analysis-fix-3.patch diff --git a/SOURCES/libcap-disable-golang.patch b/SOURCES/libcap-disable-golang.patch new file mode 100644 index 0000000..99693d9 --- /dev/null +++ b/SOURCES/libcap-disable-golang.patch @@ -0,0 +1,12 @@ +diff --color -ru a/Make.Rules b/Make.Rules +--- a/Make.Rules 2022-01-04 16:57:52.071890314 +0100 ++++ b/Make.Rules 2022-01-04 16:59:33.171786150 +0100 +@@ -104,7 +104,7 @@ + + ifeq ($(PTHREADS),yes) + GO ?= go +-GOLANG ?= $(shell if [ -n "$(shell $(GO) version 2>/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/SOURCES/libcap-fix-ambient-caps.patch b/SOURCES/libcap-fix-ambient-caps.patch new file mode 100644 index 0000000..de08d03 --- /dev/null +++ b/SOURCES/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/SOURCES/libcap-static-analysis-fix-3.patch b/SOURCES/libcap-static-analysis-fix-3.patch new file mode 100644 index 0000000..237c256 --- /dev/null +++ b/SOURCES/libcap-static-analysis-fix-3.patch @@ -0,0 +1,169 @@ +diff --color -ru a/libcap/_makenames.c b/libcap/_makenames.c +--- a/libcap/_makenames.c 2022-01-28 14:41:38.357147972 +0100 ++++ b/libcap/_makenames.c 2022-01-28 14:42:45.681379827 +0100 +@@ -45,7 +45,7 @@ + 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 *)); +diff --color -ru a/progs/capsh.c b/progs/capsh.c +--- a/progs/capsh.c 2022-01-28 14:41:38.359148009 +0100 ++++ b/progs/capsh.c 2022-01-28 14:42:45.682379846 +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]; +@@ -362,7 +391,7 @@ + + parts = strdup(path); + if (parts == NULL) { +- fprintf(stderr, "insufficient memory for parts of path\n"); ++ fprintf(stderr, "insufficient memory for parts of path\n"); + exit(1); + } + +@@ -610,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", +@@ -667,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", +@@ -680,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; + } +@@ -696,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); +@@ -722,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", +@@ -733,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", +@@ -744,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", +@@ -924,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); +@@ -933,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/tests/libcap_psx_test.c b/tests/libcap_psx_test.c +--- a/tests/libcap_psx_test.c 2022-01-28 14:41:38.360148027 +0100 ++++ b/tests/libcap_psx_test.c 2022-01-28 14:42:45.683379864 +0100 +@@ -21,7 +21,10 @@ + 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; +@@ -51,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/SPECS/libcap.spec b/SPECS/libcap.spec index 29b79d8..5018ab4 100644 --- a/SPECS/libcap.spec +++ b/SPECS/libcap.spec @@ -1,6 +1,6 @@ Name: libcap Version: 2.48 -Release: 7%{?dist} +Release: 8%{?dist} Summary: Library for getting and setting POSIX.1e capabilities URL: https://sites.google.com/site/fullycapable/ License: BSD or GPLv2 @@ -9,6 +9,9 @@ Source: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/snapshot/%{name}-% Patch0: libcap-use-compiler-flag-options.patch Patch1: libcap-static-analysis-fix.patch Patch2: libcap-static-analysis-fix-2.patch +Patch3: libcap-static-analysis-fix-3.patch +Patch4: libcap-disable-golang.patch +Patch5: libcap-fix-ambient-caps.patch BuildRequires: libattr-devel pam-devel perl-interpreter gcc BuildRequires: make @@ -85,6 +88,10 @@ chmod +x %{buildroot}/%{_libdir}/*.so.* %changelog +* Fri Jan 28 2022 Zoltan Fridrich - 2.48-8 +- Fix ambient capabilities for non-root users + Related: rhbz#2037215 + * Fri Aug 27 2021 Zoltan Fridrich - 2.48-7 - Fix issues detected by static analyzers Related: rhbz#1985346