]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
capability-util: add CAP_MASK_ALL + CAP_MASK_UNSET macros
authorLennart Poettering <lennart@poettering.net>
Mon, 20 Feb 2023 11:53:26 +0000 (12:53 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 20 Feb 2023 15:49:45 +0000 (16:49 +0100)
We should be more careful with distinguishing the cases "all bits set in
caps mask" from "cap mask invalid". We so far mostly used UINT64_MAX for
both, which is not correct though (as it would mean
AmbientCapabilities=~0 followed by AmbientCapabilities=0) would result
in capability 63 to be set (which we don't really allow, since that
means unset).

src/basic/capability-util.c
src/basic/capability-util.h
src/core/execute.c
src/core/load-fragment.c
src/core/main.c

index 13aa6fee4382f6a148b11ffeb3bf8b651159ba86..8cc75c06c8751bf49b86994011ce45e834776d5c 100644 (file)
@@ -405,7 +405,7 @@ bool capability_quintet_mangle(CapabilityQuintet *q) {
 
         combined = q->effective | q->bounding | q->inheritable | q->permitted;
 
-        ambient_supported = q->ambient != UINT64_MAX;
+        ambient_supported = q->ambient != CAP_MASK_UNSET;
         if (ambient_supported)
                 combined |= q->ambient;
 
@@ -437,7 +437,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
         _cleanup_cap_free_ cap_t c = NULL, modified = NULL;
         int r;
 
-        if (q->ambient != UINT64_MAX) {
+        if (q->ambient != CAP_MASK_UNSET) {
                 bool changed = false;
 
                 c = cap_get_proc();
@@ -479,7 +479,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                         return r;
         }
 
-        if (q->inheritable != UINT64_MAX || q->permitted != UINT64_MAX || q->effective != UINT64_MAX) {
+        if (q->inheritable != CAP_MASK_UNSET || q->permitted != CAP_MASK_UNSET || q->effective != CAP_MASK_UNSET) {
                 bool changed = false;
 
                 if (!c) {
@@ -492,7 +492,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                         uint64_t m = UINT64_C(1) << i;
                         cap_value_t cv = (cap_value_t) i;
 
-                        if (q->inheritable != UINT64_MAX) {
+                        if (q->inheritable != CAP_MASK_UNSET) {
                                 cap_flag_value_t old_value, new_value;
 
                                 if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value) < 0) {
@@ -515,7 +515,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                                 }
                         }
 
-                        if (q->permitted != UINT64_MAX) {
+                        if (q->permitted != CAP_MASK_UNSET) {
                                 cap_flag_value_t old_value, new_value;
 
                                 if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value) < 0) {
@@ -535,7 +535,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                                 }
                         }
 
-                        if (q->effective != UINT64_MAX) {
+                        if (q->effective != CAP_MASK_UNSET) {
                                 cap_flag_value_t old_value, new_value;
 
                                 if (cap_get_flag(c, cv, CAP_EFFECTIVE, &old_value) < 0) {
@@ -559,7 +559,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                 if (changed) {
                         /* In order to change the bounding caps, we need to keep CAP_SETPCAP for a bit
                          * longer. Let's add it to our list hence for now. */
-                        if (q->bounding != UINT64_MAX) {
+                        if (q->bounding != CAP_MASK_UNSET) {
                                 cap_value_t cv = CAP_SETPCAP;
 
                                 modified = cap_dup(c);
@@ -587,7 +587,7 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
                 }
         }
 
-        if (q->bounding != UINT64_MAX) {
+        if (q->bounding != CAP_MASK_UNSET) {
                 r = capability_bounding_set_drop(q->bounding, false);
                 if (r < 0)
                         return r;
index 4d1b0521f405365d97aac02801c1322bfdcc9022..48e8db35f689047cc6140e4e378af2cb0193c4ce 100644 (file)
@@ -9,7 +9,11 @@
 #include "macro.h"
 #include "missing_capability.h"
 
-#define CAP_ALL UINT64_MAX
+/* Special marker used when storing a capabilities mask as "unset" */
+#define CAP_MASK_UNSET UINT64_MAX
+
+/* All possible capabilities bits on */
+#define CAP_MASK_ALL UINT64_C(0x7fffffffffffffff)
 
 unsigned cap_last_cap(void);
 int have_effective_cap(int value);
@@ -59,14 +63,14 @@ typedef struct CapabilityQuintet {
 
 assert_cc(CAP_LAST_CAP < 64);
 
-#define CAPABILITY_QUINTET_NULL { UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX }
+#define CAPABILITY_QUINTET_NULL { CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET, CAP_MASK_UNSET }
 
 static inline bool capability_quintet_is_set(const CapabilityQuintet *q) {
-        return q->effective != UINT64_MAX ||
-                q->bounding != UINT64_MAX ||
-                q->inheritable != UINT64_MAX ||
-                q->permitted != UINT64_MAX ||
-                q->ambient != UINT64_MAX;
+        return q->effective != CAP_MASK_UNSET ||
+                q->bounding != CAP_MASK_UNSET ||
+                q->inheritable != CAP_MASK_UNSET ||
+                q->permitted != CAP_MASK_UNSET ||
+                q->ambient != CAP_MASK_UNSET;
 }
 
 /* Mangles the specified caps quintet taking the current bounding set into account:
index 5116a73617ae2f8491e52509159cb31e9f0dcc33..f38a5a41fe2c1a9c837dfa3dbcd86293d685e421 100644 (file)
@@ -5466,7 +5466,7 @@ void exec_context_init(ExecContext *c) {
         for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++)
                 c->directories[t].mode = 0755;
         c->timeout_clean_usec = USEC_INFINITY;
-        c->capability_bounding_set = CAP_ALL;
+        c->capability_bounding_set = CAP_MASK_UNSET;
         assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
         c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
         c->log_level_max = -1;
@@ -6192,7 +6192,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
                         fprintf(f, "%sSecure Bits: %s\n", prefix, str);
         }
 
-        if (c->capability_bounding_set != CAP_ALL) {
+        if (c->capability_bounding_set != CAP_MASK_UNSET) {
                 _cleanup_free_ char *str = NULL;
 
                 r = capability_set_to_string(c->capability_bounding_set, &str);
index ec782703a755ca16aaa3590b08fb7ff57a51f2c4..d4a874eafa5c3c547ed1d14fc1e02d7b703c5d8a 100644 (file)
@@ -1886,7 +1886,7 @@ int config_parse_capability_set(
                 void *userdata) {
 
         uint64_t *capability_set = ASSERT_PTR(data);
-        uint64_t sum = 0, initial = 0;
+        uint64_t sum = 0, initial, def;
         bool invert = false;
         int r;
 
@@ -1899,9 +1899,11 @@ int config_parse_capability_set(
                 rvalue++;
         }
 
-        if (streq(lvalue, "CapabilityBoundingSet"))
-                initial = CAP_ALL; /* initialized to all bits on */
-        /* else "AmbientCapabilities" initialized to all bits off */
+        if (streq(lvalue, "CapabilityBoundingSet")) {
+                initial = CAP_MASK_ALL; /* initialized to all bits on */
+                def = CAP_MASK_UNSET;   /* not set */
+        } else
+                def = initial = 0; /* All bits off */
 
         r = capability_set_from_string(rvalue, &sum);
         if (r < 0) {
@@ -1909,7 +1911,7 @@ int config_parse_capability_set(
                 return 0;
         }
 
-        if (sum == 0 || *capability_set == initial)
+        if (sum == 0 || *capability_set == def)
                 /* "", "~" or uninitialized data -> replace */
                 *capability_set = invert ? ~sum : sum;
         else {
index f28448f9e43bccf4b532d733f7018d54fbf794ec..1af9b8b50504ecb9acb11f134335499ccf49daab 100644 (file)
@@ -2458,7 +2458,7 @@ static void reset_arguments(void) {
         arg_manager_environment = strv_free(arg_manager_environment);
         rlimit_free_all(arg_default_rlimit);
 
-        arg_capability_bounding_set = CAP_ALL;
+        arg_capability_bounding_set = CAP_MASK_UNSET;
         arg_no_new_privs = false;
         arg_timer_slack_nsec = NSEC_INFINITY;
         arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;