in antlir/nspawn_in_subvol/clonecaps/clonecaps.c [133:219]
bool read_procfs_cap_bits(const char* status_filename, cap_bits_t* cap_bits) {
memset(cap_bits, 0, sizeof(*cap_bits));
// We'll compare these to make sure we saw all the expected procfs lines.
int expected_cap_types = CAPNG_INHERITABLE | CAPNG_PERMITTED |
CAPNG_EFFECTIVE
// NB: Antlir doesn't really like kernels older than 4.3, so
// I did not bother to conditionalize the availability of CapAmb.
| CAPNG_AMBIENT | CAPNG_BOUNDING_SET;
int actual_cap_types = 0;
FILE* status_file = fopen(status_filename, "re");
if (status_file == NULL) {
perror(status_filename);
return false;
}
// Not all lines are under 64 bytes (the max length is ~unbounded thanks
// to groups), but `Cap*:` lines will be, for the foreseeable future.
// As of capability API v3, they are at 25 bytes including newline.
char buf[64];
bool continuing_line = false; // Previous `buf` lacked `\n`.
while (fgets(buf, sizeof(buf), status_file)) {
bool skip_buf = continuing_line;
continuing_line = (buf[strlen(buf) - 1] != '\n');
if (skip_buf) {
continue; // Nothing to see here, this is not a `Cap*:` line.
}
// Both values are populated by `match`
int cap_type = 0;
int pref_len = 0;
if (!(_match(buf, "CapInh:\t", &cap_type, CAPNG_INHERITABLE, &pref_len) ||
_match(buf, "CapPrm:\t", &cap_type, CAPNG_PERMITTED, &pref_len) ||
_match(buf, "CapEff:\t", &cap_type, CAPNG_EFFECTIVE, &pref_len) ||
_match(buf, "CapBnd:\t", &cap_type, CAPNG_BOUNDING_SET, &pref_len) ||
_match(buf, "CapAmb:\t", &cap_type, CAPNG_AMBIENT, &pref_len))) {
continue;
}
// Fail on duplicate cap types in the input
if (actual_cap_types & cap_type) {
fprintf(
stderr,
"%s: Capability type %d occurred more than once\n",
status_filename,
cap_type);
return false;
}
actual_cap_types |= cap_type;
// Read out the bits for this capability, we'll apply them later
char* end_of_bits = NULL;
__u64 bits = strtoull(buf + pref_len, &end_of_bits, 16);
// We should have read 16 hex bytes, terminated by a newline.
if ((end_of_bits - (buf + pref_len)) != 16 || end_of_bits[0] != '\n') {
fprintf(
stderr,
"%s: Failed to parse value %s for capability type %d\n",
status_filename,
buf + pref_len,
cap_type);
return false;
}
if (cap_type == CAPNG_INHERITABLE) {
cap_bits->inheritable = bits;
} else if (cap_type == CAPNG_PERMITTED) {
cap_bits->permitted = bits;
} else if (cap_type == CAPNG_EFFECTIVE) {
cap_bits->effective = bits;
} else if (cap_type == CAPNG_BOUNDING_SET) {
cap_bits->bounding_set = bits;
} else if (cap_type == CAPNG_AMBIENT) {
cap_bits->ambient = bits;
}
}
fclose(status_file);
if (actual_cap_types != expected_cap_types) {
fprintf(
stderr,
"%s: Missing capability types: %d vs %d\n",
status_filename,
actual_cap_types,
expected_cap_types);
return false;
}
return true;
}