cap-list: refuse parsing numeric capability 63

We refuse it otherwise currently, simply because we cannot store it in a
uint64_t caps mask value anymore while retaining the ability to use
UINT64_MAX as "unset" marker.

The check actually was in place already, just one off.
This commit is contained in:
Lennart Poettering 2023-02-20 12:26:46 +01:00
parent 3f444e94f5
commit d0e67c69ba
3 changed files with 11 additions and 10 deletions

View file

@ -35,10 +35,10 @@ int capability_from_name(const char *name) {
/* Try to parse numeric capability */
r = safe_atoi(name, &i);
if (r >= 0) {
if (i >= 0 && i < 64)
return i;
else
if (i < 0 || i >= 63)
return -EINVAL;
return i;
}
/* Try to parse string capability */

View file

@ -47,11 +47,11 @@ unsigned cap_last_cap(void) {
r = safe_atolu(content, &p);
if (r >= 0) {
if (p > 63) /* Safety for the future: if one day the kernel learns more than 64 caps,
if (p > 62) /* Safety for the future: if one day the kernel learns more than 64 caps,
* then we are in trouble (since we, as much userspace and kernel space
* store capability masks in uint64_t types). Let's hence protect
* ourselves against that and always cap at 63 for now. */
p = 63;
p = 62;
saved = p;
valid = true;
@ -60,7 +60,7 @@ unsigned cap_last_cap(void) {
}
/* fall back to syscall-probing for pre linux-3.2 */
p = MIN((unsigned long) CAP_LAST_CAP, 63U);
p = MIN((unsigned long) CAP_LAST_CAP, 62U);
if (prctl(PR_CAPBSET_READ, p) < 0) {
@ -72,7 +72,7 @@ unsigned cap_last_cap(void) {
} else {
/* Hmm, look upwards, until we find one that doesn't work */
for (; p < 63; p++)
for (; p < 62; p++)
if (prctl(PR_CAPBSET_READ, p+1) < 0)
break;
}

View file

@ -29,7 +29,8 @@ TEST(cap_list) {
assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ);
assert_se(capability_from_name("0") == 0);
assert_se(capability_from_name("15") == 15);
assert_se(capability_from_name("63") == 63);
assert_se(capability_from_name("62") == 62);
assert_se(capability_from_name("63") == -EINVAL);
assert_se(capability_from_name("64") == -EINVAL);
assert_se(capability_from_name("-1") == -EINVAL);
@ -117,9 +118,9 @@ static void test_capability_set_to_string_invalid(uint64_t invalid_cap_set) {
TEST(capability_set_to_string) {
test_capability_set_to_string_invalid(0);
/* once the kernel supports 63 caps, there are no 'invalid' numbers
/* once the kernel supports 62 caps, there are no 'invalid' numbers
* for us to test with */
if (cap_last_cap() < 63)
if (cap_last_cap() < 62)
test_capability_set_to_string_invalid(all_capabilities() + 1);
}