kdbus.h, metadata: factor out capabilities (ABI break)
authorDaniel Mack <daniel@zonque.org>
Mon, 27 Oct 2014 15:32:46 +0000 (16:32 +0100)
committerDaniel Mack <daniel@zonque.org>
Mon, 27 Oct 2014 16:05:07 +0000 (17:05 +0100)
Move capabilites to its own struct inside kdbus_item. This also gives
us the ability to inform userspace of the highest caps bit the kernel
knows about.

Hence, if the capabilites grow in either the number of sets or the
number of rows, we can now detect and handle both from userspace.

Signed-off-by: Daniel Mack <daniel@zonque.org>
kdbus.h
kdbus.txt
metadata.c
test/kdbus-util.c

diff --git a/kdbus.h b/kdbus.h
index 4c5f341cf0fbadd17cfbd80e5c30a3fe9f488259..a887d81d75227448f4a522713dfdc481d596c38c 100644 (file)
--- a/kdbus.h
+++ b/kdbus.h
@@ -89,6 +89,21 @@ struct kdbus_creds {
        __u64 starttime;
 };
 
+/**
+ * struct kdbus_caps - process capabilities
+ * @last_cap:  Highest currently known capability bit
+ * @caps:      Variable number of 32-bit capabilities flags
+ *
+ * Contains a variable number of 32-bit capabilities flags.
+ *
+ * Attached to:
+ *   KDBUS_ITEM_CAPS
+ */
+struct kdbus_caps {
+       __u32 last_cap;
+       __u32 caps[0];
+};
+
 /**
  * struct kdbus_audit - audit information
  * @sessionid:         The audit session ID
@@ -322,6 +337,7 @@ struct kdbus_item {
                struct kdbus_vec vec;
                struct kdbus_creds creds;
                struct kdbus_audit audit;
+               struct kdbus_caps caps;
                struct kdbus_timestamp timestamp;
                struct kdbus_name name;
                struct kdbus_bloom_parameter bloom_parameter;
index b491293acc2a60d07cea94ea39da7d6c4c42486d..ac1a18908976a473730eff14f7c4e90bab6ec21b 100644 (file)
--- a/kdbus.txt
+++ b/kdbus.txt
@@ -1606,9 +1606,11 @@ The following attach flags are currently supported.
     Attaches an item of type KDBUS_ITEM_CGROUP with the task's cgroup path.
 
   KDBUS_ATTACH_CAPS
-    Attaches an item of type KDBUS_ITEM_CAPS, carrying 4 sets of capabilities:
-    inheritable, permitted, effective and bset. Those should be accessed via
-    kdbus_item.data32.
+    Attaches an item of type KDBUS_ITEM_CAPS, carrying sets of capabilities
+    that should be accessed via kdbus_item.caps.caps. Also, userspace should
+    be written in a way that it takes kdbus_item.caps.last_cap into account,
+    and derive the number of sets and rows from the item size and the reported
+    number of valid capability bits.
 
   KDBUS_ATTACH_SECLABEL
     Attaches an item of type KDBUS_ITEM_SECLABEL, which contains the SELinux
index 6861899119f8369c8ba4a8bbfe044016a9476711..8323e6d7a0719dae2af9063d2e2493bf72a04162 100644 (file)
@@ -393,25 +393,30 @@ exit_free_page:
 static int kdbus_meta_append_caps(struct kdbus_meta *meta)
 {
        struct caps {
-               u32 cap[_KERNEL_CAPABILITY_U32S];
-       } cap[4];
+               u32 last_cap;
+               struct {
+                       u32 caps[_KERNEL_CAPABILITY_U32S];
+               } set[4];
+       } caps;
        unsigned int i;
        const struct cred *cred = current_cred();
 
+       caps.last_cap = CAP_LAST_CAP;
+
        for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) {
-               cap[0].cap[i] = cred->cap_inheritable.cap[i];
-               cap[1].cap[i] = cred->cap_permitted.cap[i];
-               cap[2].cap[i] = cred->cap_effective.cap[i];
-               cap[3].cap[i] = cred->cap_bset.cap[i];
+               caps.set[0].caps[i] = cred->cap_inheritable.cap[i];
+               caps.set[1].caps[i] = cred->cap_permitted.cap[i];
+               caps.set[2].caps[i] = cred->cap_effective.cap[i];
+               caps.set[3].caps[i] = cred->cap_bset.cap[i];
        }
 
        /* clear unused bits */
        for (i = 0; i < 4; i++)
-               cap[i].cap[CAP_TO_INDEX(CAP_LAST_CAP)] &=
+               caps.set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
                        CAP_TO_MASK(CAP_LAST_CAP + 1) - 1;
 
        return kdbus_meta_append_data(meta, KDBUS_ITEM_CAPS,
-                                     cap, sizeof(cap));
+                                     &caps, sizeof(caps));
 }
 
 #ifdef CONFIG_CGROUPS
index c0c01d3a34beda705535bc22523a93706e656e67..c525b43dc7ab3971f8b6e9e2708e87802a6c4eba 100644 (file)
@@ -605,17 +605,18 @@ int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg)
                        break;
 
                case KDBUS_ITEM_CAPS: {
-                       int n;
                        const uint32_t *cap;
-                       int i;
+                       int n, i;
 
-                       kdbus_printf("  +%s (%llu bytes) len=%llu bytes\n",
-                              enum_MSG(item->type), item->size,
-                              (unsigned long long)item->size -
-                                       KDBUS_ITEM_HEADER_SIZE);
+                       kdbus_printf("  +%s (%llu bytes) len=%llu bytes, last_cap %d\n",
+                                    enum_MSG(item->type), item->size,
+                                    (unsigned long long)item->size -
+                                       KDBUS_ITEM_HEADER_SIZE,
+                                    (int) item->caps.last_cap);
 
-                       cap = item->data32;
-                       n = (item->size - KDBUS_ITEM_HEADER_SIZE) / 4 / sizeof(uint32_t);
+                       cap = item->caps.caps;
+                       n = (item->size - offsetof(struct kdbus_item, caps.caps))
+                               / 4 / sizeof(uint32_t);
 
                        kdbus_printf("    CapInh=");
                        for (i = 0; i < n; i++)