capability-util: add CAP_MASK_ALL + CAP_MASK_UNSET macros

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).
This commit is contained in:
Lennart Poettering 2023-02-20 12:53:26 +01:00
parent 6c5fff017e
commit 3fd5190b5e
5 changed files with 29 additions and 23 deletions

View 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;

View 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:

View 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);

View 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 {

View 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;