mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
bus: fix capabilities on big-endian
The kernel provides capabilities as a u32 array, sd-bus uses an u8 array. This works fine on little-endian as both are encoded the same way. However, this fails on big-endian if we do not perform sufficient byte-swapping on each u32 entry. This patch makes sd-bus use u32, too. We avoid changing any kernel provided data so we can keep pointing into kdbus pool buffers which contain u32 arrays.
This commit is contained in:
parent
34a5d5e526
commit
7d9fcc2bf6
@ -20,6 +20,7 @@
|
||||
***/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <linux/capability.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "capability.h"
|
||||
@ -592,11 +593,11 @@ static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
|
||||
assert(capability >= 0);
|
||||
assert(c->capability);
|
||||
|
||||
sz = DIV_ROUND_UP(cap_last_cap(), 32U) * 4;
|
||||
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) {
|
||||
@ -641,38 +642,42 @@ _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
|
||||
|
||||
static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
|
||||
size_t sz, max;
|
||||
unsigned i;
|
||||
unsigned i, j;
|
||||
|
||||
assert(c);
|
||||
assert(p);
|
||||
|
||||
max = DIV_ROUND_UP(cap_last_cap(), 32U) * 4;
|
||||
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 /= 2;
|
||||
sz /= 8;
|
||||
if (sz > max)
|
||||
return -EINVAL;
|
||||
|
||||
if (!c->capability) {
|
||||
c->capability = new0(uint8_t, max * 4);
|
||||
c->capability = new0(uint32_t, max * 4);
|
||||
if (!c->capability)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
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 * max + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
|
||||
v = (v << 4) | t;
|
||||
}
|
||||
|
||||
c->capability[offset * max + (sz - i - 1)] = v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -60,7 +60,7 @@ struct sd_bus_creds {
|
||||
char *user_unit;
|
||||
char *slice;
|
||||
|
||||
uint8_t *capability;
|
||||
uint32_t *capability;
|
||||
|
||||
uint32_t audit_session_id;
|
||||
uid_t audit_login_uid;
|
||||
|
@ -680,7 +680,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m->creds.capability = (uint8_t *) d->caps.caps;
|
||||
m->creds.capability = d->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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user