]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cap-list: refuse parsing numeric capability 63
authorLennart Poettering <lennart@poettering.net>
Mon, 20 Feb 2023 11:26:46 +0000 (12:26 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 20 Feb 2023 15:13:49 +0000 (16:13 +0100)
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.

src/basic/cap-list.c
src/basic/capability-util.c
src/test/test-cap-list.c

index 0af37b94ee98e8ddba7d1949d46d1d0ab274eaf6..bcf7e597c2def35b50dc32395a81274d6e7942d2 100644 (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 */
index 5ab110d341786131560a3be5e4e029fdaea1445a..13aa6fee4382f6a148b11ffeb3bf8b651159ba86 100644 (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;
         }
index cc5f3a0c35d41db2c9290b8d0b186388780afe8b..517641a019a2f0e19564153b1a090d1df5e06ff9 100644 (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);
 }