summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2021-09-24 10:46:24 -0700
committerAndrew G. Morgan <morgan@kernel.org>2021-09-24 10:46:24 -0700
commit6643c636e8ab44add497f97e479ad8a931d43adf (patch)
tree19233d725b9e5fcde9833198a175c6f21a08af02
parentf8b754967348052ca92c6d2c95551cbbb1e1d387 (diff)
downloadlibcap2-6643c636e8ab44add497f97e479ad8a931d43adf.tar.gz
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>
-rw-r--r--doc/cap_clear.320
-rw-r--r--libcap/cap_proc.c5
-rw-r--r--libcap/cap_test.c8
-rw-r--r--libcap/libcap.h7
-rw-r--r--tests/libcap_launch_test.c6
5 files changed, 33 insertions, 13 deletions
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 @@ fills the to flag values by copying all of the from flag values.
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 @@ pid_t cap_launch(cap_launch_t attr, void *detail) {
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 @@ static int test_cap_flags(void)
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 @@ struct _cap_struct {
/* 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 main(int argc, char **argv) {
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) {