aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2022-03-29 18:06:18 -0700
committerAndrew G. Morgan <morgan@kernel.org>2022-03-29 18:10:10 -0700
commit15cacf20709c6917c798e298a1e087c0663e5c13 (patch)
tree04d1f95bcce8319b684c369d9067d55b9749f77b
parentaae937481ae28c0cfe502309e9acb5c34ba0b2cd (diff)
downloadlibcap-15cacf20709c6917c798e298a1e087c0663e5c13.tar.gz
Fix prctl return code/errno handling in libcap.
Bug reported by Anderson Toshiyuki Sasaki: https://bugzilla.kernel.org/show_bug.cgi?id=215772 Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r--libcap/cap_proc.c45
-rw-r--r--libcap/cap_test.c18
2 files changed, 37 insertions, 26 deletions
diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c
index 65204bf..0ce5db7 100644
--- 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
index 39df261..68b6a13 100644
--- a/libcap/cap_test.c
+++ b/libcap/cap_test.c
@@ -254,6 +254,21 @@ drop_c:
return retval;
}
+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;
@@ -269,6 +284,9 @@ int main(int argc, char **argv) {
printf("test_alloc: being called\n");
fflush(stdout);
result = test_alloc() | result;
+ printf("test_prctl: being called\n");
+ fflush(stdout);
+ result = test_prctl() | result;
printf("tested\n");
fflush(stdout);