***/
#include <stdlib.h>
+#include <linux/capability.h>
#include "util.h"
+#include "capability.h"
#include "cgroup-util.h"
#include "fileio.h"
#include "audit.h"
free(c->slice);
free(c->unescaped_description);
+ free(c->well_known_names); /* note that this is an strv, but
+ * we only free the array, not the
+ * strings the array points to. The
+ * full strv we only free if
+ * c->allocated is set, see
+ * below. */
+
strv_free(c->cmdline_array);
- strv_free(c->well_known_names);
}
_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
c->n_ref--;
if (c->n_ref == 0) {
- bus_creds_done(c);
-
free(c->comm);
free(c->tid_comm);
free(c->exe);
free(c->unique_name);
free(c->cgroup_root);
free(c->description);
+ free(c->supplementary_gids);
+
+ strv_free(c->well_known_names);
+ c->well_known_names = NULL;
+
+ bus_creds_done(c);
+
free(c);
}
} else {
return 0;
}
-
_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
assert_return(c, -EINVAL);
assert_return(fsgid, -EINVAL);
return 0;
}
+_public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
+ assert_return(c, -EINVAL);
+ assert_return(gids, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
+ return -ENODATA;
+
+ *gids = c->supplementary_gids;
+ return (int) c->n_supplementary_gids;
+}
+
_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
assert_return(c, -EINVAL);
assert_return(pid, -EINVAL);
return 0;
}
-_public_ int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec) {
- assert_return(c, -EINVAL);
- assert_return(usec, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_PID_STARTTIME))
- return -ENODATA;
-
- assert(c->pid_starttime > 0);
- *usec = c->pid_starttime;
- return 0;
-}
-
_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
assert_return(c, -EINVAL);
if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
return -ENODATA;
+ /* As a special hack we return the bus driver as well-known
+ * names list when this is requested. */
+ if (c->well_known_names_driver) {
+ static const char* const wkn[] = {
+ "org.freedesktop.DBus",
+ NULL
+ };
+
+ *well_known_names = (char**) wkn;
+ return 0;
+ }
+
+ if (c->well_known_names_local) {
+ static const char* const wkn[] = {
+ "org.freedesktop.DBus.Local",
+ NULL
+ };
+
+ *well_known_names = (char**) wkn;
+ return 0;
+ }
+
*well_known_names = c->well_known_names;
return 0;
}
size_t sz;
assert(c);
+ assert(capability >= 0);
assert(c->capability);
- sz = c->capability_size / 4;
- if ((size_t) capability >= sz*8)
+ sz = DIV_ROUND_UP(cap_last_cap(), 32U);
+ if ((unsigned)capability > cap_last_cap())
return 0;
- return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8)));
+ return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
}
_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
}
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
- size_t sz;
- unsigned i;
+ size_t sz, max;
+ unsigned i, j;
assert(c);
assert(p);
+ max = DIV_ROUND_UP(cap_last_cap(), 32U);
p += strspn(p, WHITESPACE);
sz = strlen(p);
- if (sz % 2 != 0)
+ if (sz % 8 != 0)
+ return -EINVAL;
+
+ sz /= 8;
+ if (sz > max)
return -EINVAL;
- sz /= 2;
if (!c->capability) {
- c->capability = new0(uint8_t, sz * 4);
+ c->capability = new0(uint32_t, max * 4);
if (!c->capability)
return -ENOMEM;
-
- c->capability_size = sz * 4;
}
for (i = 0; i < sz; i ++) {
- int x, y;
+ uint32_t v = 0;
- x = unhexchar(p[i*2]);
- y = unhexchar(p[i*2+1]);
+ for (j = 0; j < 8; ++j) {
+ int t;
- if (x < 0 || y < 0)
- return -EINVAL;
+ t = unhexchar(*p++);
+ if (t < 0)
+ return -EINVAL;
- c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
+ v = (v << 4) | t;
+ }
+
+ c->capability[offset * max + (sz - i - 1)] = v;
}
return 0;
if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
+ SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
}
}
+ if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
+ p = startswith(line, "Groups:");
+ if (p) {
+ size_t allocated = 0;
+
+ for (;;) {
+ unsigned long g;
+ int n = 0;
+
+ p += strspn(p, WHITESPACE);
+ if (*p == 0)
+ break;
+
+ if (sscanf(p, "%lu%n", &g, &n) != 1)
+ return -EIO;
+
+ if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
+ return -ENOMEM;
+
+ c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
+ p += n;
+ }
+
+ c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
+ continue;
+ }
+ }
+
if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
p = startswith(line, "CapEff:");
if (p) {
}
}
- if (missing & (SD_BUS_CREDS_PID_STARTTIME)) {
- unsigned long long st;
-
- r = get_starttime_of_pid(pid, &st);
- if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- } else {
- c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK);
- c->mask |= SD_BUS_CREDS_PID_STARTTIME;
- }
- }
-
if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
const char *p;
n->mask |= SD_BUS_CREDS_FSGID;
}
+ if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
+ n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
+ if (!n->supplementary_gids)
+ return -ENOMEM;
+ n->n_supplementary_gids = c->n_supplementary_gids;
+ n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
+ }
+
if (c->mask & mask & SD_BUS_CREDS_PID) {
n->pid = c->pid;
n->mask |= SD_BUS_CREDS_PID;
n->mask |= SD_BUS_CREDS_TID;
}
- if (c->mask & mask & SD_BUS_CREDS_PID_STARTTIME) {
- n->pid_starttime = c->pid_starttime;
- n->mask |= SD_BUS_CREDS_PID_STARTTIME;
- }
-
if (c->mask & mask & SD_BUS_CREDS_COMM) {
n->comm = strdup(c->comm);
if (!n->comm)
}
if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
- n->capability = memdup(c->capability, c->capability_size);
+ n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
if (!n->capability)
return -ENOMEM;
- n->capability_size = c->capability_size;
n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS);
}
+ if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+ n->label = strdup(c->label);
+ if (!n->label)
+ return -ENOMEM;
+ n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+ }
+
if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
n->audit_session_id = c->audit_session_id;
n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
}
-
if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
n->audit_login_uid = c->audit_login_uid;
n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
n->unique_name = strdup(c->unique_name);
if (!n->unique_name)
return -ENOMEM;
+ n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
}
if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
n->well_known_names = strv_copy(c->well_known_names);
if (!n->well_known_names)
return -ENOMEM;
+ n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
+ }
+
+ if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
+ n->description = strdup(c->description);
+ if (!n->description)
+ return -ENOMEM;
+ n->mask |= SD_BUS_CREDS_DESCRIPTION;
}
/* Get more data */