Compare commits
No commits in common. "c8" and "c9s" have entirely different histories.
|
@ -1 +1 @@
|
|||
SOURCES/libcap-2.48.tar.gz
|
||||
/libcap-*.tar.gz
|
||||
|
|
|
@ -1 +1 @@
|
|||
c81102815c481257e53168e83b8849bc9f154d54 SOURCES/libcap-2.48.tar.gz
|
||||
c81102815c481257e53168e83b8849bc9f154d54 libcap-2.48.tar.gz
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
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 <ctype.h>
|
||||
#include <limits.h>
|
||||
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<maxcaps; ++i) {
|
||||
if (pointers[i]) {
|
||||
- printf(" /* %d */\t\"%s\", \\\n", i, pointers[i]);
|
||||
+ printf(" /* %d */\t\"%s\",\n", i, pointers[i]);
|
||||
} else {
|
||||
- printf(" /* %d */\tNULL,\t\t/* - presently unused */ \\\n", i);
|
||||
+ printf(" /* %d */\tNULL,\t\t/* - presently unused */\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
- printf(" }\n"
|
||||
+ printf(" };\n"
|
||||
"#endif /* LIBCAP_PLEASE_INCLUDE_ARRAY */\n"
|
||||
"\n"
|
||||
"/* END OF FILE */\n");
|
|
@ -1,54 +0,0 @@
|
|||
--- a/libcap/cap_alloc.c 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/libcap/cap_alloc.c 2022-05-17 20:06:53.570560396 +0200
|
||||
@@ -123,6 +123,10 @@
|
||||
|
||||
cap_iab_t cap_iab_init(void) {
|
||||
__u32 *base = calloc(1, sizeof(__u32) + sizeof(struct cap_iab_s));
|
||||
+ if (base == NULL) {
|
||||
+ _cap_debug("out of memory");
|
||||
+ return NULL;
|
||||
+ }
|
||||
*(base++) = CAP_IAB_MAGIC;
|
||||
return (cap_iab_t) base;
|
||||
}
|
||||
@@ -138,6 +142,10 @@
|
||||
const char * const *envp)
|
||||
{
|
||||
__u32 *data = calloc(1, sizeof(__u32) + sizeof(struct cap_launch_s));
|
||||
+ if (data == NULL) {
|
||||
+ _cap_debug("out of memory");
|
||||
+ return NULL;
|
||||
+ }
|
||||
*(data++) = CAP_LAUNCH_MAGIC;
|
||||
struct cap_launch_s *attr = (struct cap_launch_s *) data;
|
||||
attr->arg0 = arg0;
|
||||
--- a/libcap/cap_proc.c 2022-05-17 20:07:36.301803359 +0200
|
||||
+++ b/libcap/cap_proc.c 2022-05-17 20:06:59.238592623 +0200
|
||||
@@ -677,9 +677,25 @@
|
||||
*/
|
||||
cap_iab_t cap_iab_get_proc(void)
|
||||
{
|
||||
- cap_iab_t iab = cap_iab_init();
|
||||
- cap_t current = cap_get_proc();
|
||||
+ 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;
|
|
@ -1,128 +0,0 @@
|
|||
diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c
|
||||
--- a/libcap/cap_proc.c
|
||||
+++ b/libcap/cap_proc.c
|
||||
@@ -135,7 +135,13 @@ static int _libcap_wprctl3(struct syscaller_s *sc,
|
||||
long int pr_cmd, long int arg1, long int arg2)
|
||||
{
|
||||
if (_libcap_overrode_syscalls) {
|
||||
- return sc->three(SYS_prctl, pr_cmd, arg1, arg2);
|
||||
+ 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);
|
||||
}
|
||||
@@ -145,7 +151,13 @@ static int _libcap_wprctl6(struct syscaller_s *sc,
|
||||
long int arg3, long int arg4, long int arg5)
|
||||
{
|
||||
if (_libcap_overrode_syscalls) {
|
||||
- return sc->six(SYS_prctl, pr_cmd, arg1, arg2, arg3, arg4, arg5);
|
||||
+ 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);
|
||||
}
|
||||
@@ -271,26 +283,12 @@ int capsetp(pid_t pid, cap_t cap_d)
|
||||
|
||||
int cap_get_bound(cap_value_t cap)
|
||||
{
|
||||
- int result;
|
||||
-
|
||||
- result = prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0));
|
||||
- if (result < 0) {
|
||||
- errno = -result;
|
||||
- return -1;
|
||||
- }
|
||||
- return result;
|
||||
+ return prctl(PR_CAPBSET_READ, pr_arg(cap), pr_arg(0));
|
||||
}
|
||||
|
||||
static int _cap_drop_bound(struct syscaller_s *sc, cap_value_t cap)
|
||||
{
|
||||
- int result;
|
||||
-
|
||||
- result = _libcap_wprctl3(sc, PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0));
|
||||
- if (result < 0) {
|
||||
- errno = -result;
|
||||
- return -1;
|
||||
- }
|
||||
- return result;
|
||||
+ return _libcap_wprctl3(sc, PR_CAPBSET_DROP, pr_arg(cap), pr_arg(0));
|
||||
}
|
||||
|
||||
/* drop a capability from the bounding set */
|
||||
@@ -316,7 +314,7 @@ int cap_get_ambient(cap_value_t cap)
|
||||
static int _cap_set_ambient(struct syscaller_s *sc,
|
||||
cap_value_t cap, cap_flag_value_t set)
|
||||
{
|
||||
- int result, val;
|
||||
+ int val;
|
||||
switch (set) {
|
||||
case CAP_SET:
|
||||
val = PR_CAP_AMBIENT_RAISE;
|
||||
@@ -328,13 +326,8 @@ static int _cap_set_ambient(struct syscaller_s *sc,
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
- result = _libcap_wprctl6(sc, PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
|
||||
- pr_arg(0), pr_arg(0), pr_arg(0));
|
||||
- if (result < 0) {
|
||||
- errno = -result;
|
||||
- return -1;
|
||||
- }
|
||||
- return result;
|
||||
+ return _libcap_wprctl6(sc, PR_CAP_AMBIENT, pr_arg(val), pr_arg(cap),
|
||||
+ pr_arg(0), pr_arg(0), pr_arg(0));
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/libcap/cap_test.c b/libcap/cap_test.c
|
||||
--- a/libcap/cap_test.c 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/libcap/cap_test.c 2022-05-16 18:24:55.754193142 +0200
|
||||
@@ -29,11 +29,36 @@
|
||||
return failed;
|
||||
}
|
||||
|
||||
+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_prctl: being called\n");
|
||||
+ fflush(stdout);
|
||||
+ result = test_prctl() | result;
|
||||
+ printf("tested\n");
|
||||
+ fflush(stdout);
|
||||
+
|
||||
if (result) {
|
||||
- printf("test FAILED\n");
|
||||
+ printf("cap_test FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
+ printf("cap_test PASS\n");
|
||||
+ exit(0);
|
||||
}
|
|
@ -1,494 +0,0 @@
|
|||
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");
|
|
@ -0,0 +1,264 @@
|
|||
This is the Linux kernel capabilities FAQ
|
||||
|
||||
Its history, to the extent that I am able to reconstruct it is that
|
||||
v2.0 was posted to the Linux kernel list on 1999/04/02 by Boris
|
||||
Tobotras. Thanks to Denis Ducamp for forwarding me a copy.
|
||||
|
||||
Cheers
|
||||
|
||||
Andrew
|
||||
|
||||
Linux Capabilities FAQ 0.2
|
||||
==========================
|
||||
|
||||
1) What is a capability?
|
||||
|
||||
The name "capabilities" as used in the Linux kernel can be confusing.
|
||||
First there are Capabilities as defined in computer science. A
|
||||
capability is a token used by a process to prove that it is allowed to
|
||||
do an operation on an object. The capability identifies the object
|
||||
and the operations allowed on that object. A file descriptor is a
|
||||
capability. You create the file descriptor with the "open" call and
|
||||
request read or write permissions. Later, when doing a read or write
|
||||
operation, the kernel uses the file descriptor as an index into a
|
||||
data structure that indicates what operations are allowed. This is an
|
||||
efficient way to check permissions. The necessary data structures are
|
||||
created once during the "open" call. Later read and write calls only
|
||||
have to do a table lookup. Operations on capabilities include copying
|
||||
capabilities, transferring capabilities between processes, modifying a
|
||||
capability, and revoking a capability. Modifying a capability can be
|
||||
something like taking a read-write filedescriptor and making it
|
||||
read-only. A capability often has a notion of an "owner" which is
|
||||
able to invalidate all copies and derived versions of a capability.
|
||||
Entire OSes are based on this "capability" model, with varying degrees
|
||||
of purity. There are other ways of implementing capabilities than the
|
||||
file descriptor model - traditionally special hardware has been used,
|
||||
but modern systems also use the memory management unit of the CPU.
|
||||
|
||||
Then there is something quite different called "POSIX capabilities"
|
||||
which is what Linux uses. These capabilities are a partitioning of
|
||||
the all powerful root privilege into a set of distinct privileges (but
|
||||
look at securelevel emulation to find out that this isn't necessary
|
||||
the whole truth). Users familiar with VMS or "Trusted" versions of
|
||||
other UNIX variants will know this under the name "privileges". The
|
||||
name "capabilities" comes from the now defunct POSIX draft 1003.1e
|
||||
which used this name.
|
||||
|
||||
2) So what is a "POSIX capability"?
|
||||
|
||||
A process has three sets of bitmaps called the inheritable(I),
|
||||
permitted(P), and effective(E) capabilities. Each capability is
|
||||
implemented as a bit in each of these bitmaps which is either set or
|
||||
unset. When a process tries to do a privileged operation, the
|
||||
operating system will check the appropriate bit in the effective set
|
||||
of the process (instead of checking whether the effective uid of the
|
||||
process i 0 as is normally done). For example, when a process tries
|
||||
to set the clock, the Linux kernel will check that the process has the
|
||||
CAP_SYS_TIME bit (which is currently bit 25) set in its effective set.
|
||||
|
||||
The permitted set of the process indicates the capabilities the
|
||||
process can use. The process can have capabilities set in the
|
||||
permitted set that are not in the effective set. This indicates that
|
||||
the process has temporarily disabled this capability. A process is
|
||||
allowed to set a bit in its effective set only if it is available in
|
||||
the permitted set. The distinction between effective and permitted
|
||||
exists so that processes can "bracket" operations that need privilege.
|
||||
|
||||
The inheritable capabilities are the capabilities of the current
|
||||
process that should be inherited by a program executed by the current
|
||||
process. The permitted set of a process is masked against the
|
||||
inheritable set during exec(). Nothing special happens during fork()
|
||||
or clone(). Child processes and threads are given an exact copy of
|
||||
the capabilities of the parent process.
|
||||
|
||||
3) What about other entities in the system? Users, Groups, Files?
|
||||
|
||||
Files have capabilities. Conceptually they have the same three
|
||||
bitmaps that processes have, but to avoid confusion we call them by
|
||||
other names. Only executable files have capabilities, libraries don't
|
||||
have capabilities (yet). The three sets are called the allowed set,
|
||||
the forced set, and the effective set.
|
||||
|
||||
The allowed set indicates what capabilities the executable is allowed
|
||||
to receive from an execing process. This means that during exec(),
|
||||
the capabilities of the old process are first masked against a set
|
||||
which indicates what the process gives away (the inheritable set of
|
||||
the process), and then they are masked against a set which indicates
|
||||
what capabilities the new process image is allowed to receive (the
|
||||
allowed set of the executable).
|
||||
|
||||
The forced set is a set of capabilities created out of thin air and
|
||||
given to the process after execing the executable. The forced set is
|
||||
similar in nature to the setuid feature. In fact, the setuid bit from
|
||||
the filesystem is "read" as a full forced set by the kernel.
|
||||
|
||||
The effective set indicates which bits in the permitted set of the new
|
||||
process should be transferred to the effective set of the new process.
|
||||
The effective set is best thought of as a "capability aware" set. It
|
||||
should consist of only 1s if the executable is capability-dumb, or
|
||||
only 0s if the executable is capability-smart. Since the effective
|
||||
set consists of only 0s or only 1s, the filesystem can implement this
|
||||
set using a single bit.
|
||||
|
||||
NOTE: Filesystem support for capabilities is not part of Linux 2.2.
|
||||
|
||||
Users and Groups don't have associated capabilities from the kernel's
|
||||
point of view, but it is entirely reasonable to associate users or
|
||||
groups with capabilities. By letting the "login" program set some
|
||||
capabilities it is possible to make role users such as a backup user
|
||||
that will have the CAP_DAC_READ_SEARCH capability and be able to do
|
||||
backups. This could also be implemented as a PAM module, but nobody
|
||||
has implemented one yet.
|
||||
|
||||
4) What capabilities exist?
|
||||
|
||||
The capabilities available in Linux are listed and documented in the
|
||||
file /usr/src/linux/include/linux/capability.h.
|
||||
|
||||
5) Are Linux capabilities hierarchical?
|
||||
|
||||
No, you cannot make a "subcapability" out of a Linux capability as in
|
||||
capability-based OSes.
|
||||
|
||||
6) How can I use capabilities to make sure Mr. Evil Luser (eluser)
|
||||
can't exploit my "suid" programs?
|
||||
|
||||
This is the general outline of how this works given filesystem
|
||||
capability support exists. First, you have a PAM module that sets the
|
||||
inheritable capabilities of the login-shell of eluser. Then for all
|
||||
"suid" programs on the system, you decide what capabilities they need
|
||||
and set the _allowed_ set of the executable to that set of
|
||||
capabilities. The capability rules
|
||||
|
||||
new permitted = forced | (allowed & inheritable)
|
||||
|
||||
means that you should be careful about setting forced capabilities on
|
||||
executables. In a few cases, this can be useful though. For example
|
||||
the login program needs to set the inheritable set of the new user and
|
||||
therefore needs an almost full permitted set. So if you want eluser
|
||||
to be able to run login and log in as a different user, you will have
|
||||
to set some forced bits on that executable.
|
||||
|
||||
7) What about passing capabilities between processes?
|
||||
|
||||
Currently this is done by the system call "setcap" which can set the
|
||||
capabilities of another process. This requires the CAP_SETPCAP
|
||||
capability which you really only want to grant a _few_ processes.
|
||||
CAP_SETPCAP was originally intended as a workaround to be able to
|
||||
implement filesystem support for capabilities using a daemon outside
|
||||
the kernel.
|
||||
|
||||
There has been discussions about implementing socket-level capability
|
||||
passing. This means that you can pass a capability over a socket. No
|
||||
support for this exists in the official kernel yet.
|
||||
|
||||
8) I see securelevel has been removed from 2.2 and are superceeded by
|
||||
capabilities. How do I emulate securelevel using capabilities?
|
||||
|
||||
The setcap system call can remove a capability from _all_ processes on
|
||||
the system in one atomic operation. The setcap utility from the
|
||||
libcap distribution will do this for you. The utility requires the
|
||||
CAP_SETPCAP privilege to do this. The CAP_SETPCAP capability is not
|
||||
enabled by default.
|
||||
|
||||
libcap is available from
|
||||
ftp://ftp.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/
|
||||
|
||||
9) I noticed that the capability.h file lacks some capabilities that
|
||||
are needed to fully emulate 2.0 securelevel. Is there a patch for
|
||||
this?
|
||||
|
||||
Actually yes - funny you should ask :-). The problem with 2.0
|
||||
securelevel is that they for example stop root from accessing block
|
||||
devices. At the same time they restrict the use of iopl. These two
|
||||
changes are fundamentally different. Blocking access to block devices
|
||||
means restricting something that usually isn't restricted.
|
||||
Restricting access to the use of iopl on the other hand means
|
||||
restricting (blocking) access to something that is already blocked.
|
||||
Emulating the parts of 2.0 securelevel that restricts things that are
|
||||
normally not restricted means that the capabilites in the kernel has
|
||||
to have a set of capabilities that are usually _on_ for a normal
|
||||
process (note that this breaks the explanation that capabilities are a
|
||||
partitioning of the root privileges). There is an experimental patch at
|
||||
|
||||
ftp://ftp.guardian.no/pub/free/linux/capabilities/patch-cap-exp-1
|
||||
|
||||
which implements a set of capabilities with the "CAP_USER" prefix:
|
||||
|
||||
cap_user_sock - allowed to use socket()
|
||||
cap_user_dev - allowed to open char/block devices
|
||||
cap_user_fifo - allowed to use pipes
|
||||
|
||||
These should be enough to emulate 2.0 securelevel (tell me if we need
|
||||
something more).
|
||||
|
||||
10) Seems I need a CAP_SETPCAP capability that I don't have to make use
|
||||
of capabilities. How do I enable this capability?
|
||||
|
||||
Change the definition of CAP_INIT_EFF_SET and CAP_INIT_INH_SET to the
|
||||
following in include/linux/capability.h:
|
||||
|
||||
#define CAP_INIT_EFF_SET { ~0 }
|
||||
#define CAP_INIT_INH_SET { ~0 }
|
||||
|
||||
This will start init with a full capability set and not with
|
||||
CAP_SETPCAP removed.
|
||||
|
||||
11) How do I start a process with a limited set of capabilities?
|
||||
|
||||
Get the libcap library and use the execcap utility. The following
|
||||
example starts the update daemon with only the CAP_SYS_ADMIN
|
||||
capability.
|
||||
|
||||
execcap 'cap_sys_admin=eip' update
|
||||
|
||||
12) How do I start a process with a limited set of capabilities under
|
||||
another uid?
|
||||
|
||||
Use the sucap utility which changes uid from root without loosing any
|
||||
capabilities. Normally all capabilities are cleared when changing uid
|
||||
from root. The sucap utility requires the CAP_SETPCAP capability.
|
||||
The following example starts updated under uid updated and gid updated
|
||||
with CAP_SYS_ADMIN raised in the Effective set.
|
||||
|
||||
sucap updated updated execcap 'cap_sys_admin=eip' update
|
||||
|
||||
[ Sucap is currently available from
|
||||
ftp://ftp.guardian.no/pub/free/linux/capabilities/sucap.c. Put it in
|
||||
the progs directory of libcap to compile.]
|
||||
|
||||
13) What are the "capability rules"
|
||||
|
||||
The capability rules are the rules used to set the capabilities of the
|
||||
new process image after an exec. They work like this:
|
||||
|
||||
pI' = pI
|
||||
(***) pP' = fP | (fI & pI)
|
||||
pE' = pP' & fE [NB. fE is 0 or ~0]
|
||||
|
||||
I=Inheritable, P=Permitted, E=Effective // p=process, f=file
|
||||
' indicates post-exec().
|
||||
|
||||
Now to make sense of the equations think of fP as the Forced set of
|
||||
the executable, and fI as the Allowed set of the executable. Notice
|
||||
how the Inheritable set isn't touched at all during exec().
|
||||
|
||||
14) What are the laws for setting capability bits in the Inheritable,
|
||||
Permitted, and Effective sets?
|
||||
|
||||
Bits can be transferred from Permitted to either Effective or
|
||||
Inheritable set.
|
||||
|
||||
Bits can be removed from all sets.
|
||||
|
||||
15) Where is the standard on which the Linux capabilities are based?
|
||||
|
||||
There used to be a POSIX draft called POSIX.6 and later POSIX 1003.1e.
|
||||
However after the committee had spent over 10 years, POSIX decided
|
||||
that enough is enough and dropped the draft. There will therefore not
|
||||
be a POSIX standard covering security anytime soon. This may lead to
|
||||
that the POSIX draft is available for free, however.
|
||||
|
||||
--
|
||||
Best regards, -- Boris.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
--- !Policy
|
||||
product_versions:
|
||||
- rhel-9
|
||||
decision_context: osci_compose_gate
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1.functional}
|
|
@ -0,0 +1,23 @@
|
|||
.\" 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 <robbe@debian.org>,
|
||||
for the Debian GNU/Linux system (but may be used by others).
|
||||
|
|
@ -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)
|
|
@ -0,0 +1,210 @@
|
|||
diff --color -ru a/libcap/cap_proc.c b/libcap/cap_proc.c
|
||||
--- a/libcap/cap_proc.c 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/libcap/cap_proc.c 2021-08-27 10:07:37.627519433 +0200
|
||||
@@ -689,6 +689,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 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/libcap/cap_text.c 2021-08-27 10:14:45.180389737 +0200
|
||||
@@ -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 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/libcap/_makenames.c 2021-08-27 10:02:53.263979868 +0200
|
||||
@@ -49,6 +49,10 @@
|
||||
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 2021-08-26 09:23:55.560021048 +0200
|
||||
+++ b/pam_cap/pam_cap.c 2021-08-27 10:17:00.406562672 +0200
|
||||
@@ -60,6 +60,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]);
|
||||
diff --color -ru a/progs/capsh.c b/progs/capsh.c
|
||||
--- a/progs/capsh.c 2021-08-26 09:23:55.561021064 +0200
|
||||
+++ b/progs/capsh.c 2021-08-27 10:43:32.973136965 +0200
|
||||
@@ -100,7 +100,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);
|
||||
@@ -402,6 +411,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);
|
||||
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 2021-08-27 10:21:36.547999961 +0200
|
||||
@@ -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 2021-08-27 10:23:30.764835298 +0200
|
||||
@@ -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-08-26 09:23:55.562021081 +0200
|
||||
+++ b/psx/psx.c 2021-08-27 10:24:49.997107969 +0200
|
||||
@@ -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);
|
||||
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 2021-08-27 10:31:31.662559385 +0200
|
||||
@@ -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 2021-08-27 10:29:57.157041470 +0200
|
||||
@@ -16,6 +16,10 @@
|
||||
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);
|
||||
exit(0);
|
||||
@@ -27,6 +31,7 @@
|
||||
exit(1);
|
||||
}
|
||||
cap_set_proc(start);
|
||||
+ cap_free(start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -35,6 +40,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);
|
|
@ -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");
|
|
@ -0,0 +1,152 @@
|
|||
diff --color -ru a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c
|
||||
--- a/pam_cap/pam_cap.c 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/pam_cap/pam_cap.c 2021-04-23 09:48:00.091122637 +0200
|
||||
@@ -218,7 +218,7 @@
|
||||
if (!cap_set_proc(cap_s)) {
|
||||
ok = 1;
|
||||
}
|
||||
- goto cleanup_cap_s;
|
||||
+ goto cleanup_conf;
|
||||
}
|
||||
|
||||
iab = cap_iab_from_text(conf_caps);
|
||||
@@ -238,10 +238,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 2021-04-23 09:48:00.095122691 +0200
|
||||
@@ -336,8 +336,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 +352,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);
|
||||
+ }
|
||||
+
|
||||
+free_parts:
|
||||
+ free(parts);
|
||||
+ if (status) {
|
||||
+ exit(status);
|
||||
+ }
|
||||
+ return scratch;
|
||||
+}
|
||||
|
||||
- fprintf(stderr, "unable to find executable '%s' in PATH\n", arg0);
|
||||
- exit(1);
|
||||
+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[])
|
||||
@@ -617,7 +641,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);
|
||||
|
||||
@@ -718,14 +744,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 +767,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 +860,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;
|
||||
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 2021-04-23 09:48:00.095122691 +0200
|
||||
@@ -454,6 +454,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;
|
||||
/*
|
|
@ -1,7 +1,17 @@
|
|||
diff --color -ru a/Make.Rules b/Make.Rules
|
||||
--- a/Make.Rules 2021-02-05 06:52:17.000000000 +0100
|
||||
+++ b/Make.Rules 2021-12-13 17:09:11.225308225 +0100
|
||||
@@ -56,10 +56,10 @@
|
||||
From 7c13fa4e4c044941afd3b3766de71821cdc04397 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Sun, 14 Feb 2021 14:06:49 -0800
|
||||
Subject: [PATCH] Update Make.Rules for Fedora RPM build
|
||||
|
||||
---
|
||||
Make.Rules | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/Make.Rules b/Make.Rules
|
||||
index ded9014..537cb6c 100644
|
||||
--- a/Make.Rules
|
||||
+++ b/Make.Rules
|
||||
@@ -56,10 +56,10 @@ IPATH += -fPIC -I$(KERNEL_HEADERS) -I$(topdir)/libcap/include
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
DEFINES := -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
|
||||
|
@ -14,7 +24,7 @@ diff --color -ru a/Make.Rules b/Make.Rules
|
|||
BUILD_CFLAGS ?= $(BUILD_COPTS) $(DEFINES) $(IPATH)
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
RANLIB := $(CROSS_COMPILE)ranlib
|
||||
@@ -69,7 +69,7 @@
|
||||
@@ -69,7 +69,7 @@ WARNINGS=-Wall -Wwrite-strings \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Wnested-externs -Winline -Wshadow
|
||||
LD=$(CC) -Wl,-x -shared
|
||||
|
@ -23,12 +33,5 @@ diff --color -ru a/Make.Rules b/Make.Rules
|
|||
LIBCAPLIB := -L$(topdir)/libcap -lcap
|
||||
PSXLINKFLAGS := -lpthread -Wl,-wrap,pthread_create
|
||||
LIBPSXLIB := -L$(topdir)/libcap -lpsx $(PSXLINKFLAGS)
|
||||
@@ -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)
|
||||
--
|
||||
2.29.2
|
|
@ -1,22 +1,21 @@
|
|||
Name: libcap
|
||||
Version: 2.48
|
||||
Release: 6%{?dist}
|
||||
Release: 9%{?dist}
|
||||
Summary: Library for getting and setting POSIX.1e capabilities
|
||||
URL: https://sites.google.com/site/fullycapable/
|
||||
License: BSD or GPLv2
|
||||
Group: System Environment/Libraries
|
||||
|
||||
Source: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/snapshot/%{name}-%{version}.tar.gz
|
||||
Patch0: %{name}-2.48-buildflags.patch
|
||||
Patch1: %{name}-abi-compatibility.patch
|
||||
Patch2: %{name}-static-analysis.patch
|
||||
Patch3: %{name}-fix-ambient-caps.patch
|
||||
Patch4: %{name}-fix-prctl-usage.patch
|
||||
Patch5: %{name}-check-allocation.patch
|
||||
Patch6: %{name}-cve-2023-2603.patch
|
||||
Patch7: %{name}-cve-2023-2602.patch
|
||||
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
|
||||
Patch6: libcap-cve-2023-2603.patch
|
||||
Patch7: libcap-cve-2023-2602.patch
|
||||
|
||||
BuildRequires: libattr-devel pam-devel perl-interpreter
|
||||
BuildRequires: libattr-devel pam-devel perl-interpreter gcc
|
||||
BuildRequires: make
|
||||
|
||||
%description
|
||||
|
@ -25,7 +24,6 @@ draft 15 capabilities.
|
|||
|
||||
%package static
|
||||
Summary: Static libraries for libcap development
|
||||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description static
|
||||
|
@ -37,7 +35,6 @@ draft 15 capabilities.
|
|||
|
||||
%package devel
|
||||
Summary: Development files for libcap
|
||||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
|
@ -72,7 +69,6 @@ chmod +x %{buildroot}/%{_libdir}/*.so.*
|
|||
%ldconfig_scriptlets
|
||||
|
||||
%files
|
||||
%{!?_licensedir:%global license %%doc}
|
||||
%license License
|
||||
%doc doc/capability.notes
|
||||
%{_libdir}/*.so.*
|
||||
|
@ -92,53 +88,81 @@ chmod +x %{buildroot}/%{_libdir}/*.so.*
|
|||
%{_libdir}/pkgconfig/libcap.pc
|
||||
%{_libdir}/pkgconfig/libpsx.pc
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Dec 13 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 2.48-6
|
||||
- Bump release version to restore upgrade path
|
||||
Resolves: RHEL-19362
|
||||
|
||||
* Mon Jun 26 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 2.48-5
|
||||
* Wed Jul 12 2023 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 2.48-9
|
||||
- Fix integer overflow in _libcap_strdup() (CVE-2023-2603)
|
||||
Resolves: rhbz#2210637
|
||||
Resolves: rhbz#2210638
|
||||
- Correctly check pthread_create() return value to avoid memory leak (CVE-2023-2602)
|
||||
Resolves: rhbz#2210644
|
||||
Resolves: rhbz#2222198
|
||||
|
||||
* Tue May 17 2022 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 2.48-4
|
||||
- check for successful memory allocation
|
||||
related: rhbz#2062648
|
||||
* Fri Jan 28 2022 Zoltan Fridrich <zfridric@redhat.com> - 2.48-8
|
||||
- Fix ambient capabilities for non-root users
|
||||
Related: rhbz#2037215
|
||||
|
||||
* Mon May 16 2022 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 2.48-3
|
||||
- avoid overwriting errno set by prctl
|
||||
resolves: rhbz#2062648
|
||||
* Fri Aug 27 2021 Zoltan Fridrich <zfridric@redhat.com> - 2.48-7
|
||||
- Fix issues detected by static analyzers
|
||||
Related: rhbz#1985346
|
||||
|
||||
* Fri Jan 28 2022 Zoltan Fridrich <zfridric@redhat.com> - 2.48-2
|
||||
- rebase to 2.48
|
||||
resolves: rhbz#2032813
|
||||
- fix ambient capabilities for non-root users
|
||||
resolves: rhbz#1950187
|
||||
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.48-6
|
||||
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
|
||||
Related: rhbz#1991688
|
||||
|
||||
* Thu Jun 10 2021 Zoltan Fridrich <zfridric@redhat.com> - 2.26-5
|
||||
- added CAP_PERFMON, CAP_BPF and CAP_CHECKPOINT_RESTORE capabilities
|
||||
resolves: rhbz#1946982 rhbz#1921576
|
||||
* Fri Jun 18 2021 Zoltan Fridrich <zfridric@redhat.com> - 2.48-5
|
||||
- Remove deprecated tests
|
||||
Resolves: rhbz#1938758
|
||||
|
||||
* Fri May 22 2020 Jiri Vymazal <jvymazal@redhat.com> - 2.26-4
|
||||
- added patch implementing support for ambient capabilities
|
||||
resolves: rhbz#1487388
|
||||
* Tue Jun 15 2021 Zoltan Fridrich <zfridric@redhat.com> - 2.48-4
|
||||
- Fix issues detected by static analyzers (rhbz#1938758)
|
||||
|
||||
* Tue Oct 15 2019 Marek Tamaskovic <mtamasko@redhat.com> - 2.26-3
|
||||
- changed url
|
||||
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.48-3
|
||||
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
||||
|
||||
* Wed May 22 2019 Karsten Hopp <karsten@redhat.com> - 2.26-2
|
||||
* Sun Feb 14 2021 Peter Robinson <pbrobinson@fedoraproject.org> - 2.48-2
|
||||
- Rebase distro flags patch
|
||||
|
||||
* Wed Feb 10 2021 Giuseppe Scrivano <gscrivan@redhat.com> - 2.48-1
|
||||
- Update to 0.2.48
|
||||
|
||||
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.46-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||
|
||||
* Sun Jan 17 2021 Peter Robinson <pbrobinson@fedoraproject.org> - 2.46-1
|
||||
- Update to 0.2.46
|
||||
|
||||
* Wed Oct 21 2020 Karsten Hopp <karsten@fedoraproject.org> - 2.44-1
|
||||
- update to 2.44
|
||||
- remove additional getpcaps manpage as it now included in the sources
|
||||
|
||||
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.26-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||
|
||||
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.26-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||
|
||||
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.26-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Mon Feb 04 2019 Karsten Hopp <karsten@redhat.com> - 2.26-5
|
||||
- enable gating
|
||||
|
||||
* Mon Feb 04 2019 Karsten Hopp <karsten@redhat.com> - 2.26-4
|
||||
- bump release
|
||||
|
||||
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.26-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Mon Jan 28 2019 Karsten Hopp <karsten@redhat.com> - 2.26-2
|
||||
- add CI tests using the standard test interface (astepano)
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.25-12
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Mon Jul 02 2018 Karsten Hopp <karsten@redhat.com> - 2.25-11
|
||||
- rebuild
|
||||
|
||||
* Fri Apr 12 2019 Karsten Hopp <karsten@redhat.com> - 2.26-1
|
||||
- update to 2.26
|
||||
|
||||
* Thu Apr 11 2019 Karsten Hopp <karsten@redhat.com> - 2.25-11
|
||||
- rebuild
|
||||
|
||||
* Thu Apr 11 2019 Karsten Hopp <karsten@redhat.com> - 2.25-10
|
||||
- rebuild
|
||||
* Wed Feb 21 2018 Karsten Hopp <karsten@redhat.com> - 2.25-10
|
||||
- buildrequire gcc
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.25-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
Loading…
Reference in New Issue