The number of available caps can be read from
/proc/sys/kernel/cap_last_cap during runtime. Our helper cap_last_cap()
does that, so there's no reason to remember the size of any capability
cache. We can just pre-allocate arrays with a suitable size for all
available caps and reject any higher caps.
The kernel capability API uses u32 as base so make sure we do the same.
Note that this is specified by POSIX, so it's unlikely to change.
#include "bus-control.h"
#include "bus-bloom.h"
#include "bus-util.h"
#include "bus-control.h"
#include "bus-bloom.h"
#include "bus-util.h"
#include "cgroup-util.h"
_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
#include "cgroup-util.h"
_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
if (m) {
SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
if (m) {
- c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
- c->capability = memdup(item->caps.caps, c->capability_size);
+ if (item->caps.last_cap != cap_last_cap() ||
+ item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
+ return -EBADMSG;
+
+ c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
if (!c->capability)
return -ENOMEM;
if (!c->capability)
return -ENOMEM;
#include <stdlib.h>
#include "util.h"
#include <stdlib.h>
#include "util.h"
#include "cgroup-util.h"
#include "fileio.h"
#include "audit.h"
#include "cgroup-util.h"
#include "fileio.h"
#include "audit.h"
+ assert(capability >= 0);
- sz = c->capability_size / 4;
- if ((size_t) capability >= sz*8)
+ sz = DIV_ROUND_UP(cap_last_cap(), 32U) * 4;
+ if ((unsigned)capability > cap_last_cap())
return 0;
return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8)));
return 0;
return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8)));
}
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
}
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
unsigned i;
assert(c);
assert(p);
unsigned i;
assert(c);
assert(p);
+ max = DIV_ROUND_UP(cap_last_cap(), 32U) * 4;
p += strspn(p, WHITESPACE);
sz = strlen(p);
p += strspn(p, WHITESPACE);
sz = strlen(p);
+ if (sz > max)
+ return -EINVAL;
+
- c->capability = new0(uint8_t, sz * 4);
+ c->capability = new0(uint8_t, max * 4);
if (!c->capability)
return -ENOMEM;
if (!c->capability)
return -ENOMEM;
-
- c->capability_size = sz * 4;
}
for (i = 0; i < sz; i ++) {
}
for (i = 0; i < sz; i ++) {
if (x < 0 || y < 0)
return -EINVAL;
if (x < 0 || y < 0)
return -EINVAL;
- c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
+ c->capability[offset * max + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
}
if (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_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;
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);
}
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);
}
char *slice;
uint8_t *capability;
char *slice;
uint8_t *capability;
- size_t capability_size;
uint32_t audit_session_id;
uid_t audit_login_uid;
uint32_t audit_session_id;
uid_t audit_login_uid;
#include "util.h"
#include "strv.h"
#include "memfd-util.h"
#include "util.h"
#include "strv.h"
#include "memfd-util.h"
#include "cgroup-util.h"
#include "fileio.h"
#include "cgroup-util.h"
#include "fileio.h"
break;
case KDBUS_ITEM_CAPS:
break;
case KDBUS_ITEM_CAPS:
+ if (d->caps.last_cap != cap_last_cap() ||
+ d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
+ r = -EBADMSG;
+ goto fail;
+ }
+
m->creds.capability = (uint8_t *) d->caps.caps;
m->creds.capability = (uint8_t *) d->caps.caps;
- m->creds.capability_size = d->size - offsetof(struct kdbus_item, caps.caps);
m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
break;
m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
break;