parse-util: Add parse_capability_set()

Let's extract common capability parsing code into a generic function
parse_capability_set() with a comprehensive set of unit tests.

We also replace usages of UINT64_MAX with CAP_MASK_UNSET where
applicable and replace the default value of CapabilityBoundingSet
with CAP_MASK_ALL which more clearly identifies that it is initialized
to all capabilities.

AI (copilot) was used to extract the generic function and write the
unit tests, with manual review and fixing afterwards to make sure
everything was correct.
This commit is contained in:
Daan De Meyer
2025-10-29 22:39:48 +01:00
committed by Yu Watanabe
parent 1a3b3c57c6
commit 10e82fde7b
12 changed files with 197 additions and 67 deletions

View File

@@ -7,6 +7,8 @@
#include <sys/socket.h>
#include "alloc-util.h"
#include "capability-list.h"
#include "capability-util.h"
#include "errno-list.h"
#include "extract-word.h"
#include "locale-util.h"
@@ -809,3 +811,39 @@ bool nft_identifier_valid(const char *id) {
return in_charset(id + 1, ALPHANUMERICAL "/\\_.");
}
int parse_capability_set(const char *s, uint64_t initial, uint64_t *current) {
int r;
assert(s);
assert(current);
if (isempty(s)) {
*current = CAP_MASK_UNSET;
return 1;
}
bool invert = false;
if (s[0] == '~') {
invert = true;
s++;
}
uint64_t parsed;
r = capability_set_from_string(s, &parsed);
if (r < 0)
return r;
if (parsed == 0 || *current == initial)
/* "~" or uninitialized data -> replace */
*current = invert ? all_capabilities() & ~parsed : parsed;
else {
/* previous data -> merge */
if (invert)
*current &= ~parsed;
else
*current |= parsed;
}
return r;
}

View File

@@ -22,6 +22,8 @@ int parse_errno(const char *t);
int parse_fd(const char *t);
int parse_user_shell(const char *s, char **ret_sh, bool *ret_copy);
int parse_capability_set(const char *s, uint64_t initial, uint64_t *capability_set);
#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)
#define SAFE_ATO_REFUSE_LEADING_WHITESPACE (1U << 28)