static int condition_test_capability(Condition *c) { _cleanup_fclose_ FILE *f = NULL; int value; char line[LINE_MAX]; unsigned long long capabilities = -1; assert(c); assert(c->parameter); assert(c->type == CONDITION_CAPABILITY); /* If it's an invalid capability, we don't have it */ value = capability_from_name(c->parameter); if (value < 0) return -EINVAL; /* If it's a valid capability we default to assume * that we have it */ f = fopen("/proc/self/status", "re"); if (!f) return -errno; while (fgets(line, sizeof(line), f)) { truncate_nl(line); if (startswith(line, "CapBnd:")) { (void) sscanf(line+7, "%llx", &capabilities); break; } } return !!(capabilities & (1ULL << value)); }
int config_parse_capability( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { uint64_t u = 0, *result = data; int r; assert(filename); assert(lvalue); assert(rvalue); for (;;) { _cleanup_free_ char *word = NULL; int cap; r = extract_first_word(&rvalue, &word, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); return 0; } if (r == 0) break; cap = capability_from_name(word); if (cap < 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability, ignoring: %s", word); continue; } u |= 1 << ((uint64_t) cap); } if (u == 0) return 0; *result |= u; return 0; }
/* verify the capability parser */ static void test_cap_list(void) { int i; assert_se(!capability_to_name(-1)); assert_se(!capability_to_name(capability_list_length())); for (i = 0; i < capability_list_length(); i++) { const char *n; assert_se(n = capability_to_name(i)); assert_se(capability_from_name(n) == i); printf("%s = %i\n", n, i); } assert_se(capability_from_name("asdfbsd") == -EINVAL); assert_se(capability_from_name("CAP_AUDIT_READ") == CAP_AUDIT_READ); assert_se(capability_from_name("cap_audit_read") == CAP_AUDIT_READ); 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("-1") == -EINVAL); for (i = 0; i < capability_list_length(); i++) { _cleanup_cap_free_charp_ char *a = NULL; const char *b; unsigned u; assert_se(a = cap_to_name(i)); /* quit the loop as soon as libcap starts returning * numeric ids, formatted as strings */ if (safe_atou(a, &u) >= 0) break; assert_se(b = capability_to_name(i)); printf("%s vs. %s\n", a, b); assert_se(strcasecmp(a, b) == 0); } }