chiark / gitweb /
bus: drop creds->capability_size
authorDavid Herrmann <dh.herrmann@gmail.com>
Tue, 30 Dec 2014 07:42:53 +0000 (08:42 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Tue, 30 Dec 2014 07:42:53 +0000 (08:42 +0100)
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.

src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-creds.c
src/libsystemd/sd-bus/bus-creds.h
src/libsystemd/sd-bus/bus-kernel.c

index e86546c34394711a8bdc64ff1d04534ff3dde7b7..b2394db3eb036e9ac38a3706421fa99e9d5cfafe 100644 (file)
@@ -33,6 +33,7 @@
 #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 "capability.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) {
@@ -520,8 +521,11 @@ static int bus_populate_creds_from_items(
                              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;
 
index 9978ddfa3836918417185d7361798f8549d914ad..55d6fb6b439073c11503aa48b4892923b2b33f4d 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 
 #include "util.h"
 #include <stdlib.h>
 
 #include "util.h"
+#include "capability.h"
 #include "cgroup-util.h"
 #include "fileio.h"
 #include "audit.h"
 #include "cgroup-util.h"
 #include "fileio.h"
 #include "audit.h"
@@ -588,10 +589,11 @@ static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
         size_t sz;
 
         assert(c);
         size_t sz;
 
         assert(c);
+        assert(capability >= 0);
         assert(c->capability);
 
         assert(c->capability);
 
-        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)));
@@ -638,12 +640,13 @@ _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) {
 }
 
 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
-        size_t sz;
+        size_t sz, max;
         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);
@@ -651,12 +654,13 @@ static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
                 return -EINVAL;
 
         sz /= 2;
                 return -EINVAL;
 
         sz /= 2;
+        if (sz > max)
+                return -EINVAL;
+
         if (!c->capability) {
         if (!c->capability) {
-                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 ++) {
@@ -668,7 +672,7 @@ static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
                 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;
         }
 
         return 0;
         }
 
         return 0;
@@ -1073,11 +1077,10 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
         }
 
         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);
         }
 
index 48453e2afd5010578f0e4a4fd49b81cabb8cfc33..2480a4a0b133df2439d229f9b4ff102e9b488fc9 100644 (file)
@@ -61,7 +61,6 @@ struct sd_bus_creds {
         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;
index d9252b256024f6d4ec765f83af1af0bb2429c8e2..eeb4a518d10dfd180951d038b1c1268888573fd4 100644 (file)
@@ -32,6 +32,7 @@
 #include "util.h"
 #include "strv.h"
 #include "memfd-util.h"
 #include "util.h"
 #include "strv.h"
 #include "memfd-util.h"
+#include "capability.h"
 #include "cgroup-util.h"
 #include "fileio.h"
 
 #include "cgroup-util.h"
 #include "fileio.h"
 
@@ -673,8 +674,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         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;