Recognize that NULL is an invalid cap_t and cap_iab_t.
This was a regresssion introduced in libcap-2.55. Fixed in libcap-2.59.
Added a cap_launch NULL test too. Comparing against NULL would cause a
SIGSEGV against these library revisions.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
diff --git a/doc/cap_clear.3 b/doc/cap_clear.3
index 6d06049..eb8f4ec 100644
--- a/doc/cap_clear.3
+++ b/doc/cap_clear.3
@@ -88,16 +88,18 @@
compares two full capability sets and, in the spirit of
.BR memcmp (),
returns zero if the two capability sets are identical. A positive
-return value,
-.BR status ,
-indicates there is a difference between them. The
-returned value carries further information about which of three sets,
-.I cap_flag_t
-.BR flag ,
-differ. Specifically, the macro
+return
+.I value
+indicates there is a difference between them. The returned
+.I value
+carries further information about the
+.BI "cap_flag_t " flag
+differences. Specifically, the macro
.B CAP_DIFFERS
-.RI ( status ", " flag )
-evaluates to non-zero if the returned status differs in its
+.RI ( value ", " flag )
+evaluates to non-zero if the returned
+.I value
+differs in its
.I flag
components.
.SH "RETURN VALUE"
diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c
index eac86cb..8633824 100644
--- a/libcap/cap_proc.c
+++ b/libcap/cap_proc.c
@@ -998,6 +998,11 @@
int ps[2];
pid_t child;
+ if (!good_cap_launch_t(attr)) {
+ errno = EINVAL;
+ return -1;
+ }
+
/* The launch must have a purpose */
if (attr->custom_setup_fn == NULL &&
(attr->arg0 == NULL || attr->argv == NULL)) {
diff --git a/libcap/cap_test.c b/libcap/cap_test.c
index 729efed..2c068aa 100644
--- a/libcap/cap_test.c
+++ b/libcap/cap_test.c
@@ -49,6 +49,14 @@
printf("test_flags failed to allocate a set\n");
return -1;
}
+ if (cap_compare(c, NULL) != -1) {
+ printf("compare to NULL should give invalid\n");
+ return -1;
+ }
+ if (cap_compare(NULL, c) != -1) {
+ printf("compare with NULL should give invalid\n");
+ return -1;
+ }
for (v = 0; v < __CAP_MAXBITS; v += 3) {
if (cap_set_flag(c, CAP_INHERITABLE, 1, &v, CAP_SET)) {
diff --git a/libcap/libcap.h b/libcap/libcap.h
index ffc8c8a..bd80342 100644
--- a/libcap/libcap.h
+++ b/libcap/libcap.h
@@ -133,9 +133,10 @@
/* launcher magic for cap_free */
#define CAP_LAUNCH_MAGIC 0xCA91A
-#define magic_of(x) (*(-2 + (const __u32 *) x))
-#define good_cap_t(x) (CAP_T_MAGIC == magic_of(x))
-#define good_cap_iab_t(x) (CAP_IAB_MAGIC == magic_of(x))
+#define magic_of(x) ((x) ? *(-2 + (const __u32 *) x) : 0)
+#define good_cap_t(x) (CAP_T_MAGIC == magic_of(x))
+#define good_cap_iab_t(x) (CAP_IAB_MAGIC == magic_of(x))
+#define good_cap_launch_t(x) (CAP_LAUNCH_MAGIC == magic_of(x))
/*
* kernel API cap set abstraction
diff --git a/tests/libcap_launch_test.c b/tests/libcap_launch_test.c
index 343e389..12d123c 100644
--- a/tests/libcap_launch_test.c
+++ b/tests/libcap_launch_test.c
@@ -127,8 +127,12 @@
int success = 1, i;
for (i=0; vs[i].pass_on != NO_MORE; i++) {
- cap_launch_t attr;
+ cap_launch_t attr = NULL;
const struct test_case_s *v = &vs[i];
+ if (cap_launch(attr, NULL) != -1) {
+ perror("NULL launch didn't fail");
+ exit(1);
+ }
printf("[%d] test should %s\n", i,
v->result || v->launch_abort ? "generate error" : "work");
if (v->args[0] != NULL) {