#include <unistd.h>
#include "alloc-util.h"
-#include "capability-util.h"
#include "cap-list.h"
+#include "capability-util.h"
+#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "logarithm.h"
#include "missing_prctl.h"
#include "missing_threads.h"
#include "parse-util.h"
+#include "pidref.h"
+#include "stat-util.h"
#include "user-util.h"
int have_effective_cap(int value) {
*ret = a;
return 1;
}
+
+int pidref_get_capability(const PidRef *pidref, CapabilityQuintet *ret) {
+ int r;
+
+ if (!pidref_is_set(pidref))
+ return -ESRCH;
+ if (pidref_is_remote(pidref))
+ return -EREMOTE;
+
+ const char *path = procfs_file_alloca(pidref->pid, "status");
+ _cleanup_fclose_ FILE *f = fopen(path, "re");
+ if (!f) {
+ if (errno == ENOENT && proc_mounted() == 0)
+ return -ENOSYS;
+
+ return -errno;
+ }
+
+ CapabilityQuintet q = CAPABILITY_QUINTET_NULL;
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ static const struct {
+ const char *field;
+ size_t offset;
+ } fields[] = {
+ { "CapBnd:", offsetof(CapabilityQuintet, bounding) },
+ { "CapInh:", offsetof(CapabilityQuintet, inheritable) },
+ { "CapPrm:", offsetof(CapabilityQuintet, permitted) },
+ { "CapEff:", offsetof(CapabilityQuintet, effective) },
+ { "CapAmb:", offsetof(CapabilityQuintet, ambient) },
+ };
+
+ FOREACH_ELEMENT(i, fields) {
+
+ const char *p = first_word(line, i->field);
+ if (!p)
+ continue;
+
+ uint64_t *v = (uint64_t*) ((uint8_t*) &q + i->offset);
+
+ if (*v != CAP_MASK_UNSET)
+ return -EBADMSG;
+
+ r = safe_atoux64(p, v);
+ if (r < 0)
+ return r;
+
+ if (*v == CAP_MASK_UNSET)
+ return -EBADMSG;
+ }
+ }
+
+ if (q.effective == CAP_MASK_UNSET ||
+ q.inheritable == CAP_MASK_UNSET ||
+ q.permitted == CAP_MASK_UNSET ||
+ q.effective == CAP_MASK_UNSET ||
+ q.ambient == CAP_MASK_UNSET)
+ return -EBADMSG;
+
+ r = pidref_verify(pidref);
+ if (r < 0)
+ return r;
+
+ if (ret)
+ *ret = q;
+
+ return 0;
+}
#include "macro.h"
#include "missing_capability.h"
+#include "pidref.h"
/* Special marker used when storing a capabilities mask as "unset" */
#define CAP_MASK_UNSET UINT64_MAX
int capability_quintet_enforce(const CapabilityQuintet *q);
int capability_get_ambient(uint64_t *ret);
+
+int pidref_get_capability(const PidRef *pidref, CapabilityQuintet *ret);
#include "battery-util.h"
#include "blockdev-util.h"
#include "cap-list.h"
+#include "capability-util.h"
#include "cgroup-util.h"
#include "compare-operator.h"
#include "condition.h"
}
static int condition_test_capability(Condition *c, char **env) {
- unsigned long long capabilities = (unsigned long long) -1;
- _cleanup_fclose_ FILE *f = NULL;
- int value, r;
+ int r;
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);
+ int 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;
-
- for (;;) {
- _cleanup_free_ char *line = NULL;
-
- r = read_line(f, LONG_LINE_MAX, &line);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- const char *p = startswith(line, "CapBnd:");
- if (p) {
- if (sscanf(p, "%llx", &capabilities) != 1)
- return -EIO;
-
- break;
- }
- }
+ CapabilityQuintet q;
+ r = pidref_get_capability(&PIDREF_MAKE_FROM_PID(getpid_cached()), &q);
+ if (r < 0)
+ return r;
- return !!(capabilities & (1ULL << value));
+ return !!(q.bounding & ((UINT64_C(1) << value)));
}
static int condition_test_needs_update(Condition *c, char **env) {
}
}
+static void test_pidref_get_capability(void) {
+ CapabilityQuintet q = CAPABILITY_QUINTET_NULL;
+
+ assert_se(pidref_get_capability(&PIDREF_MAKE_FROM_PID(getpid_cached()), &q) >= 0);
+
+ assert_se(q.effective != CAP_MASK_UNSET);
+ assert_se(q.inheritable != CAP_MASK_UNSET);
+ assert_se(q.permitted != CAP_MASK_UNSET);
+ assert_se(q.effective != CAP_MASK_UNSET);
+ assert_se(q.ambient != CAP_MASK_UNSET);
+}
+
int main(int argc, char *argv[]) {
bool run_ambient;
test_capability_get_ambient();
+ test_pidref_get_capability();
+
return 0;
}