kdbus: CMD_UPDATE_METADATA, use it in seclabel test
authorKonrad Lipinski <konrad.l@samsung.com>
Thu, 8 Dec 2016 14:11:27 +0000 (15:11 +0100)
committerKonrad Lipinski <konrad.l@samsung.com>
Thu, 8 Dec 2016 14:11:27 +0000 (15:11 +0100)
23 files changed:
include/uapi/linux/kdbus.h
ipc/kdbus/bus.c
ipc/kdbus/connection.c
ipc/kdbus/connection.h
ipc/kdbus/domain.c
ipc/kdbus/endpoint.c
ipc/kdbus/fs.c
ipc/kdbus/handle.c
ipc/kdbus/main.c
ipc/kdbus/match.c
ipc/kdbus/message.c
ipc/kdbus/metadata.c
ipc/kdbus/metadata.h
ipc/kdbus/names.c
ipc/kdbus/node.c
ipc/kdbus/policy.c
ipc/kdbus/pool.c
ipc/kdbus/reply.c
tools/testing/selftests/kdbus/kdbus-api.h
tools/testing/selftests/kdbus/kdbus-test.c
tools/testing/selftests/kdbus/kdbus-util.c
tools/testing/selftests/kdbus/kdbus-util.h
tools/testing/selftests/kdbus/test-match.c

index 4fc44cb1d4a8cdd053f9b4d9f8f6a96e683f5199..c160849ab99fbf47174832ca94feb7f4b9a40906 100644 (file)
@@ -964,6 +964,7 @@ enum kdbus_ioctl_type {
                                             struct kdbus_cmd_info),
        KDBUS_CMD_LIST =                _IOR(KDBUS_IOCTL_MAGIC, 0x86,
                                             struct kdbus_cmd_list),
+       KDBUS_CMD_UPDATE_METADATA = _IO(KDBUS_IOCTL_MAGIC, 0x89),
 
        KDBUS_CMD_SEND =                _IOW(KDBUS_IOCTL_MAGIC, 0x90,
                                             struct kdbus_cmd_send),
index 2939f0089c333fe775c728fcbc60a138c5e1050a..dc720dd8fdf83741c1db2b437ac8a06f7990cc3f 100644 (file)
@@ -455,8 +455,7 @@ int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp)
        cnt += kdbus_meta_emit_stack_kvec(&bus->meta, conn, &kvec[cnt], &meta_stack, attach_flags, &size);
        if (attach_flags & KDBUS_ATTACH_AUXGROUPS) {
                unsigned pay_size;
-               pay = kdbus_meta_payload_new(bus->meta.auxgroups_alloc_order);
-               if (!pay) {
+               if (!(pay = kdbus_meta_payload_new(bus->meta.auxgroups_alloc_order))) {
                        ret = -ENOMEM;
                        goto exit;
                }
index a12262095b2c1854ce5b450b67f8111da0fa2b16..a0141de7326b78417a830e312352fc6ef1db0367 100644 (file)
@@ -57,6 +57,8 @@
  */
 #define DISABLE_KDBUS_POLICY
 
+static wur int kdbus_conn_meta_update(struct kdbus_conn *__restrict__ conn, bool first_time);
+
 static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
                                         struct file *file,
                                         struct kdbus_cmd_hello *hello,
@@ -122,49 +124,39 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
        have_meta_fake = creds || pids || seclabel;
 
        {
-               struct kdbus_meta_payload *meta_payload = kdbus_meta_payload_new(0);
-               unsigned meta_size;
-               unsigned meta_items_offset;
-               unsigned conn_desc_item_size = 0;
-               unsigned conn_desc_len;
-               if (!meta_payload)
-                       return ERR_PTR(-ENOMEM);
-
-               /* privileged processes can impersonate somebody else */
-               if (have_meta_fake) {
-                       meta_items_offset = offsetof(typeof(*conn), meta_fake.meta_items);
-                       ret = kdbus_meta_fake_collect(&meta_payload, seclabel);
-               } else {
-                       meta_items_offset = offsetof(typeof(*conn), meta.meta_items);
-                       ret = kdbus_meta_proc_collect(&meta_payload, KDBUS_ATTACH_MASK_ALL & ~KDBUS_ATTACH_SECLABEL);
+               unsigned seclabel_len;
+               unsigned seclabel_item_size = 0;
+               unsigned conn_description_len;
+               unsigned conn_description_item_size = 0;
+               unsigned meta_items_offset = have_meta_fake
+                       ? offsetof(typeof(*conn), meta_fake.meta_items)
+                       : offsetof(typeof(*conn), meta.conn_description);
+               BUILD_BUG_ON(offsetof(typeof(*conn), meta_fake.meta_items) % 8);
+               BUILD_BUG_ON(offsetof(typeof(*conn), meta.conn_description) % 8);
+               if (seclabel) {
+                       seclabel_len = strlen(seclabel);
+                       seclabel_item_size = KDBUS_ITEM_SIZE(1+seclabel_len);
                }
-               if (ret >= 0) {
-                       if (conn_description) {
-                               ret |= KDBUS_ATTACH_CONN_DESCRIPTION;
-                               conn_desc_item_size = KDBUS_ITEM_SIZE(1+(conn_desc_len = strlen(conn_description)));
-                       }
-                       meta_size = kdbus_meta_payload_size(meta_payload);
-                       if ((conn = kmalloc(meta_items_offset + meta_size + conn_desc_item_size, GFP_KERNEL)))
-                               memcpy((void*)((uintptr_t)conn + meta_items_offset), kdbus_meta_payload_ptr(meta_payload), meta_size);
-                       else
-                               ret = -ENOMEM;
+               if (conn_description) {
+                       conn_description_len = strlen(conn_description);
+                       conn_description_item_size = KDBUS_ITEM_SIZE(1+conn_description_len);
                }
-               kdbus_meta_payload_free(meta_payload);
-               if (ret < 0)
-                       return ERR_PTR(ret);
+
+               if (!(conn = kmalloc(meta_items_offset + seclabel_item_size + conn_description_item_size, GFP_KERNEL)))
+                       return ERR_PTR(-ENOMEM);
 
                BUILD_BUG_ON(offsetof(typeof(*conn), meta) != offsetof(typeof(*conn), meta_fake));
                memset(conn, 0, offsetof(typeof(*conn), meta)); /* meta needs no init */
 
+               if (seclabel) {
+                       kdbus_write_string_item((struct kdbus_item *)((uintptr_t)conn + meta_items_offset), KDBUS_ITEM_SECLABEL, seclabel, seclabel_len);
+                       meta_items_offset += conn_description_item_size;
+                       conn->meta_valid = KDBUS_ATTACH_SECLABEL;
+               }
                if (conn_description) {
-                       struct kdbus_item *item = conn->description = (struct kdbus_item *)((uintptr_t)conn + meta_items_offset + meta_size);
-                       item->size = conn_desc_item_size;
-                       item->type = KDBUS_ITEM_CONN_DESCRIPTION;
-                       kdbus_copy_string(item->str, conn_description, conn_desc_len);
-                       ret |= KDBUS_ATTACH_CONN_DESCRIPTION;
+                       kdbus_write_string_item(conn->description = (struct kdbus_item *)((uintptr_t)conn + meta_items_offset), KDBUS_ITEM_CONN_DESCRIPTION, conn_description, conn_description_len);
+                       conn->meta_valid |= KDBUS_ATTACH_CONN_DESCRIPTION;
                }
-
-               conn->meta_valid = ret | KDBUS_ATTACH_NAMES;
        }
 
        conn->kref.refcount.counter = 1; /* no need for atomicity yet */
@@ -176,9 +168,8 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
        INIT_LIST_HEAD(&conn->names_list);
        INIT_LIST_HEAD(&conn->dequeued_reply_list);
        INIT_LIST_HEAD(&conn->enqueued_reply_list);
-       conn->request_quota.counter = 1+KDBUS_CONN_MAX_REQUESTS_PENDING; /* atomicity not required due to locks */ /*atomic_set(&conn->request_count, 0);*/ /* already zeroed */
+       conn->request_quota.counter = 1+KDBUS_CONN_MAX_REQUESTS_PENDING; /* atomicity not required due to locks */
        /*atomic_set(&conn->lost_count, 0);*/ /* already zeroed */
-       INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
        conn->cred = get_cred(file->f_cred);
        conn->pid = get_pid(task_pid(current));
        get_fs_root(current->fs, &conn->root_path);
@@ -198,10 +189,10 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
 
        ret = have_meta_fake
                ? kdbus_dst_sensitive_meta_fake_collect(&conn->meta_fake.meta, creds, pids)
-               : kdbus_dst_sensitive_meta_collect(&conn->meta.meta, KDBUS_ATTACH_MASK_ALL);
+               : kdbus_conn_meta_update(conn, 1);
        if (ret < 0)
                goto exit_unref;
-       conn->meta_valid |= ret;
+       conn->meta_valid |= have_meta_fake ? ret : KDBUS_ATTACH_NAMES;
 
        if ((ret = kdbus_pool_init(&conn->pool, conn_description, hello->pool_size)))
                goto exit_unref;
@@ -263,6 +254,8 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
        kdbus_pool_slice_publish(&conn->pool, slice, &hello->offset, &hello->items_size);
        kdbus_pool_slice_release(&conn->pool, slice);
 
+       INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
+
        return conn;
 
 exit_slice:
@@ -290,12 +283,11 @@ static void __kdbus_conn_free(struct kref *kref)
                kdbus_user_unref(conn->user);
        }
 
-       BUILD_BUG_ON(offsetof(typeof(conn->meta.meta), common));
-       BUILD_BUG_ON(offsetof(typeof(conn->meta_fake.meta), common));
-       BUILD_BUG_ON(offsetof(typeof(*conn), meta_fake.meta) != offsetof(typeof(*conn), meta.meta));
-       kdbus_dst_sensitive_meta_common_destroy(&conn->meta.meta.common, conn->meta_valid);
-       if (!conn->have_meta_fake)
-               kdbus_dst_sensitive_meta_real_destroy(&conn->meta.meta, conn->meta_valid);
+
+       if (conn->have_meta_fake)
+               kdbus_dst_sensitive_meta_common_destroy(&conn->meta_fake.meta.common, conn->meta_valid);
+       else
+               kdbus_conn_meta_free(conn->meta.meta);
 
        kdbus_match_db_destroy(&conn->match_db);
        kdbus_pool_destroy(&conn->pool);
@@ -703,8 +695,7 @@ int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
                unsigned users;
 
                users = max(KDBUS_ALIGN8(id) + 8, id);
-               quota = krealloc(c->quota, users * sizeof(*quota), GFP_KERNEL);
-               if (!quota)
+               if (!(quota = krealloc(c->quota, users * sizeof(*quota), GFP_KERNEL)))
                        return -ENOMEM;
 
                do kdbus_quota_init(&quota[n_quota]); while (++n_quota < users);
@@ -1722,20 +1713,17 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
        struct kdbus_name_entry *entry = NULL;
        struct kdbus_name_owner *owner = NULL;
        struct kdbus_conn *owner_conn = NULL;
-       struct kdbus_item *meta_items;
        struct kdbus_info info;
        struct kdbus_cmd_info *cmd;
        struct kdbus_bus *bus = conn->ep->bus;
        struct kdbus_meta_payload *meta_payload = NULL;
+       struct kdbus_conn_meta *meta = NULL;
        struct kvec kvec[1/*info*/ + MAX_META_EMIT_VECS_CONN];
        unsigned cnt = 0;
-       const char *name;
        unsigned size;
        int ret;
-       attach_flags_t attach_flags, valid_flags;
-       #ifdef CONFIG_SECURITY
-               attach_flags_t missing_flags;
-       #endif
+       attach_flags_t attach_flags, valid;
+       bool fake;
 
        struct kdbus_arg argv[] = {
                { .type = KDBUS_ITEM_NAME },
@@ -1755,9 +1743,8 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
        if ((ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags)))
                goto exit;
 
-       name = argv[0].item ? argv[0].item->str : NULL;
-
-       if (name) {
+       if (argv[0].item) {
+               char const *name = argv[0].item->str;
                entry = kdbus_name_lookup_unlocked(&bus->name_registry, name);
                if (entry)
                        owner = kdbus_name_get_owner(entry);
@@ -1768,8 +1755,8 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
                        ret = -ESRCH;
                        goto exit;
                }
-
                owner_conn = owner->conn;
+               kdbus_assert(owner_conn);
        } else if (cmd->id > 0) {
                owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id);
                if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(),
@@ -1783,11 +1770,17 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
                goto exit;
        }
 
-       valid_flags = atomic_attach_flags_read(&owner_conn->attach_flags_send) & owner_conn->meta_valid;
-       #ifdef CONFIG_SECURITY
-               missing_flags = attach_flags & KDBUS_ATTACH_SECLABEL;
-       #endif
-       attach_flags &= valid_flags;
+       valid = owner_conn->meta_valid;
+       if (!(fake = owner_conn->have_meta_fake)) {
+               rcu_read_lock();
+               meta = rcu_dereference(owner_conn->meta.meta);
+               kdbus_assert(meta);
+               kdbus_conn_meta_ref(meta);
+               rcu_read_unlock();
+               valid |= meta->valid;
+       }
+
+       attach_flags &= atomic_attach_flags_read(&owner_conn->attach_flags_send) & valid;
        attach_flags = kdbus_sanitize_exe_flag(attach_flags, conn);
 
        info.id = owner_conn->id;
@@ -1795,56 +1788,34 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
        kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info));
        size = sizeof(info);
 
-       kdbus_assert(1 <= cnt);
-       kdbus_assert(cnt <= 2);
-       if (2 == cnt) {
-               kdbus_assert((uintptr_t)&meta_stack <= (uintptr_t)kvec[1].iov_base);
-               kdbus_assert((uintptr_t)kvec[1].iov_base < (uintptr_t)&meta_stack + sizeof(meta_stack));
-               kdbus_assert(kvec[1].iov_len <= (uintptr_t)&meta_stack + sizeof(meta_stack) - (uintptr_t)kvec[1].iov_base);
-       }
-
-       #define DO_META(INFIX) do {\
-               cnt += kdbus_meta_emit_stack##INFIX##_kvec(&owner_conn->meta##INFIX.meta, conn, &kvec[cnt], &meta_stack, attach_flags, &size);\
-               meta_items = owner_conn->meta##INFIX.meta_items;\
-       } while (0)
-
-       if (owner_conn->have_meta_fake)
-               DO_META(_fake);
-       else {
-               DO_META();
-       #undef DO_META
-               if (attach_flags & (KDBUS_ATTACH_AUXGROUPS|KDBUS_ATTACH_NAMES)
-                       #ifdef CONFIG_SECURITY
-                               || missing_flags
-                       #endif
-               ) {
+       if (fake) {
+               cnt += kdbus_meta_emit_stack_fake_kvec(&owner_conn->meta_fake.meta, conn, &kvec[cnt], &meta_stack, attach_flags, &size);
+               cnt += kdbus_meta_emit_kvecs(&kvec[cnt], owner_conn->meta_fake.meta_items, attach_flags & (KDBUS_ATTACH_SECLABEL|KDBUS_ATTACH_CONN_DESCRIPTION), &size);
+       } else {
+               cnt += kdbus_meta_emit_stack_kvec(&meta->meta, conn, &kvec[cnt], &meta_stack, attach_flags, &size);
+               if (attach_flags & (KDBUS_ATTACH_AUXGROUPS|KDBUS_ATTACH_NAMES)) {
                        unsigned pay_size;
-                       meta_payload = kdbus_meta_payload_new(attach_flags & KDBUS_ATTACH_AUXGROUPS ? owner_conn->meta.meta.auxgroups_alloc_order : 0);
-                       if (!meta_payload) {
+                       if (!(meta_payload = kdbus_meta_payload_new(attach_flags & KDBUS_ATTACH_AUXGROUPS ? meta->meta.auxgroups_alloc_order : 0))) {
                                ret = -ENOMEM;
                                goto exit;
                        }
-                       if (attach_flags & KDBUS_ATTACH_AUXGROUPS) /* not fake */
-                               kdbus_meta_payload_collect_auxgroups_preallocated(meta_payload, &owner_conn->meta.meta, conn);
+                       if (attach_flags & KDBUS_ATTACH_AUXGROUPS)
+                               kdbus_meta_payload_collect_auxgroups_preallocated(meta_payload, &meta->meta, conn);
                        if (attach_flags & KDBUS_ATTACH_NAMES) {
                                if (0 > (ret = kdbus_meta_payload_collect_names(&meta_payload, owner_conn)))
                                        goto exit;
                                ret = 0;
                        }
-                       #ifdef CONFIG_SECURITY
-                               if (missing_flags && 0 > (ret = kdbus_meta_payload_collect_seclabel(&meta_payload)))
-                                       goto exit;
-                               ret = 0;
-                       #endif
                        if ((pay_size = kdbus_meta_payload_size(meta_payload))) {
                                kdbus_assert(!(pay_size % 8));
                                kdbus_kvec_set(&kvec[cnt++], kdbus_meta_payload_ptr(meta_payload), pay_size);
                                size = KDBUS_ALIGN8(size) + pay_size;
                        }
                }
+               cnt += kdbus_meta_emit_kvecs(&kvec[cnt], meta->meta_items, attach_flags & KDBUS_ATTACH_MASK_PROC_DST_AGNOSTIC, &size);
+               cnt += kdbus_meta_emit_kvecs(&kvec[cnt], owner_conn->meta.conn_description, attach_flags & KDBUS_ATTACH_CONN_DESCRIPTION, &size);
        }
 
-       cnt += kdbus_meta_emit_kvecs(&kvec[cnt], meta_items, attach_flags & (KDBUS_ATTACH_MASK_PROC_DST_AGNOSTIC|KDBUS_ATTACH_CONN_DESCRIPTION), &size);
        kdbus_assert(cnt <= sizeof(kvec)/sizeof(kvec[0]));
        info.size = size;
        size = KDBUS_ALIGN8(size);
@@ -1869,8 +1840,11 @@ exit:
        up_read(&bus->name_registry.rwlock);
        if (slice)
                kdbus_pool_slice_release(&conn->pool, slice);
-       if (meta_payload)
-               kdbus_meta_payload_free(meta_payload);
+       if (meta) {
+               kdbus_conn_meta_unref(meta);
+               if (meta_payload)
+                       kdbus_meta_payload_free(meta_payload);
+       }
        return kdbus_args_clear(&args, ret);
 }
 
@@ -1954,6 +1928,59 @@ exit:
        return kdbus_args_clear(&args, ret);
 }
 
+static wur int kdbus_conn_meta_update(struct kdbus_conn *__restrict__ conn, bool first_time)
+{
+       struct kdbus_meta_payload *meta_payload;
+       struct kdbus_conn_meta *meta;
+       int ret;
+
+       kdbus_assert(conn);
+       kdbus_assert(!conn->have_meta_fake);
+
+       if (!(meta_payload = kdbus_meta_payload_new(0)))
+               return -ENOMEM;
+       if (0 <= (ret = kdbus_meta_proc_collect(&meta_payload, KDBUS_ATTACH_MASK_ALL))) {
+               unsigned pay_size = kdbus_meta_payload_size(meta_payload);
+               if (!(meta = kmalloc(sizeof(*meta) + pay_size, GFP_KERNEL)))
+                       ret = -ENOMEM;
+               else {
+                       meta->kref.refcount.counter = 1; /* no need for atomicity yet */
+                       meta->valid = ret | kdbus_dst_sensitive_meta_collect(&meta->meta, KDBUS_ATTACH_MASK_ALL);
+                       memcpy(meta->meta_items, kdbus_meta_payload_ptr(meta_payload), pay_size);
+               }
+       }
+       kdbus_meta_payload_free(meta_payload);
+       if (ret < 0)
+               return ret;
+
+       if (first_time)
+               conn->meta.meta = meta;
+       else {
+               struct kdbus_conn_meta *old_meta;
+               mutex_lock(&conn->lock);
+               old_meta = conn->meta.meta;
+               rcu_assign_pointer(conn->meta.meta, meta);
+               synchronize_rcu();
+               mutex_unlock(&conn->lock);
+               kdbus_conn_meta_unref(old_meta);
+       }
+
+       return 0;
+}
+
+/**
+ * kdbus_cmd_update_metadata() - handle KDBUS_CMD_UPDATE_METADATA
+ * @conn:              connection to operate on
+ *
+ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_update_metadata(struct kdbus_conn *conn)
+{
+       if (conn->have_meta_fake)
+               return -EOPNOTSUPP;
+       return kdbus_conn_meta_update(conn, 0);
+}
+
 /**
  * kdbus_cmd_send() - handle KDBUS_CMD_SEND
  * @conn:              connection to operate on
index 9077095f2be424c241a5e4bcc3abc708bc9acfe1..755174bebc5579d2e872d24fb603f4fedaba6c99 100644 (file)
 struct kdbus_name_entry;
 struct kdbus_quota;
 
+struct kdbus_conn_meta {
+       struct kref kref;
+       attach_flags_t valid;
+       struct kdbus_dst_sensitive_meta meta;
+       struct kdbus_item meta_items[0];
+};
+
+void kdbus_conn_meta_free(struct kdbus_conn_meta *meta);
+void kdbus_conn_meta_ref(struct kdbus_conn_meta *meta);
+void kdbus_conn_meta_unref(struct kdbus_conn_meta *meta);
+
 /**
  * struct kdbus_conn - connection to a bus
  * @kref:              Reference count
@@ -115,12 +126,12 @@ struct kdbus_conn {
 
        union {
                struct {
-                       struct kdbus_dst_sensitive_meta meta;
-                       struct kdbus_item meta_items[0];
+                       struct kdbus_conn_meta *meta; /* rcu-protected and refcounted, contains its own meta_valid and both dst-sensitive and insensitive metadata */
+                       struct kdbus_item conn_description[0]; /* conn_description or nothing */
                } meta;
                struct {
                        struct kdbus_dst_sensitive_meta_fake meta;
-                       struct kdbus_item meta_items[0];
+                       struct kdbus_item meta_items[0]; /* seclabel, conn_description */
                } meta_fake;
        };
 };
@@ -167,6 +178,7 @@ wur struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
 wur int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
 wur int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
 wur int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp);
+wur int kdbus_cmd_update_metadata(struct kdbus_conn *conn);
 wur int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp);
 wur int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp);
 wur int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp);
index ea669e8f5c48324d1629cd5aed74567540e7b08c..c873b050733a145521a5b669b8ca84ad90003f57 100644 (file)
@@ -39,8 +39,7 @@ static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain,
        struct kdbus_node *node;
        int ret;
 
-       node = kzalloc(sizeof(*node), GFP_KERNEL);
-       if (!node)
+       if (!(node = kzalloc(sizeof(*node), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        kdbus_node_init(node, KDBUS_NODE_CONTROL);
@@ -86,8 +85,7 @@ struct kdbus_domain *kdbus_domain_new(unsigned int access)
        struct kdbus_domain *d;
        int ret;
 
-       d = kzalloc(sizeof(*d), GFP_KERNEL);
-       if (!d)
+       if (!(d = kzalloc(sizeof(*d), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN);
@@ -199,8 +197,7 @@ struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid)
                }
        }
 
-       u = kzalloc(sizeof(*u), GFP_KERNEL);
-       if (!u) {
+       if (!(u = kzalloc(sizeof(*u), GFP_KERNEL))) {
                ret = -ENOMEM;
                goto exit;
        }
index f12843b472468a1848b8410da4109d8931c320c7..fb9d2b77bf43c54a6a275daafc6a943597573136 100644 (file)
@@ -97,8 +97,7 @@ struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name,
        if (is_custom && (ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, uid)))
                return ERR_PTR(ret);
 
-       e = kzalloc(sizeof(*e), GFP_KERNEL);
-       if (!e)
+       if (!(e = kzalloc(sizeof(*e), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT);
index c67246a7cb1d808e3d8653f59ff049bace32e16a..0b4c74acb6254036d4a01027043a97676d47dcf9 100644 (file)
@@ -194,8 +194,7 @@ static struct inode *fs_inode_get(struct super_block *sb,
 {
        struct inode *inode;
 
-       inode = iget_locked(sb, node->id);
-       if (!inode)
+       if (!(inode = iget_locked(sb, node->id)))
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
@@ -292,10 +291,8 @@ static int fs_super_fill(struct super_block *sb)
                return PTR_ERR(inode);
 
        sb->s_root = d_make_root(inode);
-       if (!sb->s_root) {
-               /* d_make_root iput()s the inode on failure */
+       if (!sb->s_root) /* d_make_root iput()s the inode on failure */
                return -ENOMEM;
-       }
 
        /* sb holds domain reference */
        sb->s_root->d_fsdata = &domain->node;
index d217cf8686a2380bdc2a043aeabf5227948e3a4c..6441e69b51b40eeb700dd2f1dd34aedf86556b8f 100644 (file)
@@ -299,8 +299,8 @@ int __kdbus_args_parse(struct kdbus_args *args, void __user *argp,
                args->cmd = (void*)args->cmd_buf;
        else if (!(args->cmd = kmalloc(aligned_user_size, GFP_TEMPORARY)))
                return -ENOMEM;
-               if (IS_ERR(args->cmd))
-                       return PTR_ERR(args->cmd);
+       if (IS_ERR(args->cmd))
+               return PTR_ERR(args->cmd);
 
        /* pad with trailing zeroes to alignment of 8 */
        *(u64*)((uintptr_t)args->cmd + aligned_user_size - 8) = 0;
@@ -761,8 +761,7 @@ static int kdbus_handle_open(struct inode *inode, struct file *file)
        if (!kdbus_node_acquire(node))
                return -ESHUTDOWN;
 
-       handle = kzalloc(sizeof(*handle), GFP_KERNEL);
-       if (!handle) {
+       if (!(handle = kzalloc(sizeof(*handle), GFP_KERNEL))) {
                ret = -ENOMEM;
                goto exit;
        }
@@ -970,6 +969,9 @@ static long kdbus_handle_ioctl_connected(struct file *file,
        case KDBUS_CMD_UPDATE:
                ret = kdbus_cmd_update(conn, buf);
                break;
+       case KDBUS_CMD_UPDATE_METADATA:
+               ret = kdbus_cmd_update_metadata(conn);
+               break;
        case KDBUS_CMD_MATCH_ADD:
                ret = kdbus_cmd_match_add(conn, buf);
                break;
@@ -1047,6 +1049,7 @@ static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
        case KDBUS_CMD_NAME_ACQUIRE:
        case KDBUS_CMD_NAME_RELEASE:
        case KDBUS_CMD_LIST:
+       case KDBUS_CMD_UPDATE_METADATA:
        case KDBUS_CMD_CONN_INFO:
        case KDBUS_CMD_BUS_CREATOR_INFO:
        case KDBUS_CMD_UPDATE:
index 58e7274ccba61cfee24ba63d446eda03fd44f247..259adf4a48726edd3560d6cc169297e9574bec16 100644 (file)
@@ -103,8 +103,7 @@ static int __init kdbus_init(void)
                                               sizeof (struct kdbus_reply),
                                               0, 0, NULL);
 
-       kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj);
-       if (!kdbus_dir)
+       if (!(kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj)))
                return -ENOMEM;
 
        if ((ret = kdbus_fs_init())) {
index 155d9dc6adc711ee85252734e621d305de2a84e8..8af216bf6a07d3eebd470fe7e493900cee417663 100644 (file)
@@ -559,8 +559,8 @@ int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
                        kernel_size = 0;
        }
 
-       entry = kmalloc(sizeof(*entry) + kernel_size + (user_size<0 ? 0 : user_size), GFP_KERNEL);
-       if (!entry) {
+       ;
+       if (!(entry = kmalloc(sizeof(*entry) + kernel_size + (user_size<0 ? 0 : user_size), GFP_KERNEL))) {
                ret = -ENOMEM;
                goto exit;
        }
index 5e5ac20dad33ddc453ef02aecbdba168c7414a5c..f4e43de43a58a3ce27e16b7cae7e591d69089ed2 100644 (file)
@@ -140,8 +140,7 @@ int kdbus_gaps_install(
                fds = &fds_stack_buffer[0];
        else {
                order = kdbus_page_alloc_order(n_total_fds * sizeof(*fds));
-               fds = (typeof(fds))__get_free_pages(GFP_TEMPORARY, order);
-               if (!fds)
+               if (!(fds = (typeof(fds))__get_free_pages(GFP_TEMPORARY, order)))
                        return -ENOMEM;
        }
 
index eaebd34c77ae70faeeed85dea2396f119f65ec20..d079a5240791a06c8b3b2098d2d089bcf8b9b969 100644 (file)
@@ -61,6 +61,32 @@ void kdbus_dst_sensitive_meta_destroy(struct kdbus_dst_sensitive_meta *meta, att
        kdbus_dst_sensitive_meta_real_destroy(meta, valid);
 }
 
+static void __kdbus_conn_meta_free(struct kref *kref)
+{
+       struct kdbus_conn_meta *meta = container_of(kref, struct kdbus_conn_meta, kref);
+       kdbus_dst_sensitive_meta_destroy(&meta->meta, meta->valid);
+       kfree(meta);
+}
+
+void kdbus_conn_meta_free(struct kdbus_conn_meta *meta)
+{
+       kdbus_assert(meta);
+       kdbus_assert(1 == meta->kref.refcount.counter);
+       __kdbus_conn_meta_free(&meta->kref);
+}
+
+void kdbus_conn_meta_ref(struct kdbus_conn_meta *meta)
+{
+       kdbus_assert(meta);
+       kref_get(&meta->kref);
+}
+
+void kdbus_conn_meta_unref(struct kdbus_conn_meta *meta)
+{
+       kdbus_assert(meta);
+       kref_put(&meta->kref, __kdbus_conn_meta_free);
+}
+
 static void kdbus_meta_export_caps(struct kdbus_meta_caps *__restrict__ out,
                                   const struct cred *__restrict__ cred,
                                   struct user_namespace *__restrict__ user_ns)
@@ -341,14 +367,19 @@ static wur int kdbus_meta_payload_write_head(struct kdbus_meta_payload * __restr
        return 0;
 }
 
-static void kdbus_meta_payload_write_string_item_preallocated(struct kdbus_meta_payload *__restrict__ pay, kdbus_item_type_t type, char const *__restrict__ str, unsigned len)
+void kdbus_write_string_item(struct kdbus_item *__restrict__ item, kdbus_item_type_t type, char const *__restrict__ str, unsigned len)
 {
-       struct kdbus_item * __restrict__ item = kdbus_meta_payload_item(pay);
        unsigned item_size = KDBUS_ITEM_HEADER_SIZE + len+1;
        item->size = item_size;
        item->type = type;
        kdbus_copy_string(item->str, str, len);
-       kdbus_meta_payload_advance(pay, KDBUS_ALIGN8(item_size));
+}
+
+static void kdbus_meta_payload_write_string_item_preallocated(struct kdbus_meta_payload *__restrict__ pay, kdbus_item_type_t type, char const *__restrict__ str, unsigned len)
+{
+       struct kdbus_item * __restrict__ item = kdbus_meta_payload_item(pay);
+       kdbus_write_string_item(item, type, str, len);
+       kdbus_meta_payload_advance(pay, KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + len+1));
 }
 
 static wur int kdbus_meta_payload_write_string_item(struct kdbus_meta_payload *__restrict__ *__restrict__ pptr, kdbus_item_type_t type, char const *__restrict__ str)
@@ -372,7 +403,7 @@ static wur int kdbus_meta_payload_write_comm(kdbus_item_type_t type, struct kdbu
 }
 
 #ifdef CONFIG_SECURITY
-wur int kdbus_meta_payload_collect_seclabel(struct kdbus_meta_payload * __restrict__ * __restrict__ pptr)
+static wur int kdbus_meta_payload_collect_seclabel(struct kdbus_meta_payload * __restrict__ * __restrict__ pptr)
 {
        for (;;) {
                typeof(*pptr) pay;
@@ -460,8 +491,7 @@ wur int kdbus_meta_proc_collect(struct kdbus_meta_payload * __restrict__ * __res
        #ifdef CONFIG_CGROUPS
                if (what & KDBUS_ATTACH_CGROUP) {
                        char *s;
-                       tmp_page = (typeof(tmp_page))__get_free_page(GFP_TEMPORARY);
-                       if (!tmp_page)
+                       if (!(tmp_page = (typeof(tmp_page))__get_free_page(GFP_TEMPORARY)))
                                return -ENOMEM;
                        if ((s = task_cgroup_path(current, tmp_page, PAGE_SIZE))) {
                                if ((ret = kdbus_meta_payload_write_string_item(pptr, KDBUS_ITEM_CGROUP, s))) {
@@ -501,24 +531,6 @@ end_page:
        return valid;
 }
 
-/**
- * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials
- * @mf:                Fake metadata object
- * @seclabel:  Seclabel to set, may be %NULL
- *
- * Return: valid flags on success, negative error code on failure.
- */
-int kdbus_meta_fake_collect(struct kdbus_meta_payload * __restrict__ * __restrict__ pptr,
-                           const char * __restrict__ seclabel)
-{
-       int ret;
-       if (!seclabel)
-               return 0;
-       if ((ret = kdbus_meta_payload_write_string_item(pptr, KDBUS_ITEM_SECLABEL, seclabel)))
-               return ret;
-       return KDBUS_ATTACH_SECLABEL;
-}
-
 void kdbus_collect_timestamp(struct kdbus_timestamp *ts)
 {
        ts->monotonic_ns = ktime_get_ns();
index f6e102be5225225af92bf577bb1099258013721b..acf19e81244ec2dfdd31d459c16ce4bfa5d5f053 100644 (file)
@@ -78,7 +78,7 @@ static inline wur int kdbus_sanitize_attach_flags(u64 flags, attach_flags_t *att
 /* bus info */
 #define MAX_META_EMIT_VECS_BUS (1/* DST_SENSITIVE generated on stack*/+1/*AUXGROUPS in dynamically allocated buffer*/+_CONTIGUOUS_IOVEC_COUNT_(_MAX_META_EMIT_CONT_ITEM_COUNT_BUS_))
 /* conn info */
-#define MAX_META_EMIT_VECS_CONN (1/*CAPS CREDS PID generated on stack*/+1/*AUXGROUPS+NAMES in dynamically allocated buffer*/+_CONTIGUOUS_IOVEC_COUNT_(_MAX_META_EMIT_CONT_ITEM_COUNT_BUS_+1/*CONN_DESCRIPTION*/))
+#define MAX_META_EMIT_VECS_CONN (1/*CAPS CREDS PID generated on stack*/+1/*CONN_DESCRIPTION*/+1/*AUXGROUPS+NAMES in dynamically allocated buffer*/+_CONTIGUOUS_IOVEC_COUNT_(_MAX_META_EMIT_CONT_ITEM_COUNT_BUS_))
 
 #define N_RESERVED_STAGING_USER_PARTS_BEFORE_PAYLOAD\
        (1 /* iovec to copy kdbus_msg.size */\
@@ -143,7 +143,8 @@ static inline void kdbus_meta_payload_set_meta_offset(struct kdbus_meta_payload
 }
 static inline wur struct kdbus_meta_payload *kdbus_meta_payload_new_offset_later(unsigned order) {
        var(p, (struct kdbus_meta_payload *)__get_free_pages(GFP_TEMPORARY, order));
-       p->alloc_order = order;
+       if (p)
+               p->alloc_order = order;
        return p;
 }
 static inline wur struct kdbus_meta_payload *kdbus_meta_payload_new(unsigned order) {
@@ -250,10 +251,9 @@ static inline wur struct kdbus_item *kdbus_meta_payload_ptr(struct kdbus_meta_pa
        return (struct kdbus_item *)((uintptr_t)load + load->meta_offset);
 }
 
+void kdbus_write_string_item(struct kdbus_item *__restrict__ item, kdbus_item_type_t type, char const *__restrict__ str, unsigned len);
+
 wur int kdbus_meta_proc_collect(struct kdbus_meta_payload *__restrict__ *__restrict__ pptr, attach_flags_t what);
-wur int kdbus_meta_fake_collect(struct kdbus_meta_payload *__restrict__ *__restrict__ pptr, const char *__restrict__ seclabel);
-/* KDBUS_ATTACH_SECLABEL if collected, 0 if not supported, <0 if error */
-wur int kdbus_meta_payload_collect_seclabel(struct kdbus_meta_payload * __restrict__ * __restrict__ pptr);
 
 wur unsigned _kdbus_meta_emit_(struct k_or_io_vec vec, struct kdbus_item *meta_item, attach_flags_t what, unsigned *size, unsigned total_meta_name_size);
 
index 5ecc0be6045270aa8ba85fcf327829fd698dfad4..d752291551e2dc5517a213bfbd5e521c0b9955e8 100644 (file)
@@ -54,8 +54,7 @@ kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name,
        if (conn->name_count >= KDBUS_CONN_MAX_NAMES)
                return ERR_PTR(-E2BIG);
 
-       owner = kmalloc(sizeof(*owner), GFP_KERNEL);
-       if (!owner)
+       if (!(owner = kmalloc(sizeof(*owner), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        owner->flags = flags & KDBUS_NAME_SAVED_MASK;
@@ -117,8 +116,7 @@ kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash,
 
        namelen = strlen(name_str);
 
-       name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL);
-       if (!name)
+       if (!(name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        name->name_id = ++r->name_seq_last;
index 0bc18974209782d0a673cf7302cc6db4b10407a3..9460720084b96a195da932ec49b620c21d9b6d87 100644 (file)
@@ -329,10 +329,8 @@ int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
                return -EINVAL;
 
        if (name) {
-               node->name = kstrdup(name, GFP_KERNEL);
-               if (!node->name)
+               if (!(node->name = kstrdup(name, GFP_KERNEL)))
                        return -ENOMEM;
-
                node->hash = kdbus_node_name_hash(name);
        }
 
index d18e42d8cac58856026c8c2893c38d1499c819cb..9122ae8f192c4c3f59fedf60a5efb5ccc43821a5 100644 (file)
@@ -280,8 +280,7 @@ kdbus_policy_make_access(const struct kdbus_policy_access *uaccess)
        int ret;
        struct kdbus_policy_db_entry_access *a;
 
-       a = kzalloc(sizeof(*a), GFP_KERNEL);
-       if (!a)
+       if (!(a = kzalloc(sizeof(*a), GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
        ret = -EINVAL;
@@ -384,8 +383,7 @@ int kdbus_policy_set(struct kdbus_policy_db *db,
                                goto exit;
                        }
 
-                       e = kzalloc(sizeof(*e), GFP_KERNEL);
-                       if (!e) {
+                       if (!(e = kzalloc(sizeof(*e), GFP_KERNEL))) {
                                ret = -ENOMEM;
                                goto exit;
                        }
@@ -394,8 +392,7 @@ int kdbus_policy_set(struct kdbus_policy_db *db,
                        e->owner = owner;
                        hlist_add_head(&e->hentry, &entries);
 
-                       e->name = kstrdup(item->str, GFP_KERNEL);
-                       if (!e->name) {
+                       if (!(e->name = kstrdup(item->str, GFP_KERNEL))) {
                                ret = -ENOMEM;
                                goto exit;
                        }
index bb51dc836d332422d1d6d20fa3b584ec1bcc099a..c7c1eb7b297a092f6cac86baf7e2c34f6dddf67a 100644 (file)
@@ -168,9 +168,7 @@ struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
                s = rb_entry(found, struct kdbus_pool_slice, rb_node);
 
                /* split-off the remainder of the size to its own slice */
-               s_new = kdbus_pool_slice_new(pool, s->off + slice_size,
-                                            s->size - slice_size);
-               if (!s_new) {
+               if (!(s_new = kdbus_pool_slice_new(pool, s->off + slice_size, s->size - slice_size))) {
                        ret = -ENOMEM;
                        goto exit_unlock;
                }
@@ -385,8 +383,7 @@ int kdbus_pool_init(struct kdbus_pool *p, const char *name, unsigned size)
        int ret;
 
        if (name) {
-               n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name);
-               if (!n) {
+               if (!(n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name))) {
                        ret = -ENOMEM;
                        goto exit_fail;
                }
@@ -405,8 +402,7 @@ int kdbus_pool_init(struct kdbus_pool *p, const char *name, unsigned size)
                goto exit_put_shmem;
 
        /* allocate first slice spanning the entire pool */
-       s = kdbus_pool_slice_new(p, 0, size);
-       if (!s) {
+       if (!(s = kdbus_pool_slice_new(p, 0, size))) {
                ret = -ENOMEM;
                goto exit_put_write;
        }
index e0ae70835024eb2dfc4b855870d824c14cb0e0d9..006bc9821d88b6da5ed51e7db545465b77b58666 100644 (file)
@@ -43,8 +43,7 @@ struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
                goto exit_inc_request_quota;
        }
 
-       r = kmem_cache_alloc(kdbus_reply_cachep, GFP_KERNEL);
-       if (!r) {
+       if (!(r = kmem_cache_alloc(kdbus_reply_cachep, GFP_KERNEL))) {
                ret = -ENOMEM;
                goto exit_inc_request_quota;
        }
index 4189a6a1b1db509e6110abef6d9b6bde61c4fc66..26b111fd82e93055db8fd0dd314a74602f78f9fd 100644 (file)
@@ -75,6 +75,12 @@ static inline wur int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd)
        return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
 }
 
+static inline wur int kdbus_cmd_update_metadata(int fd)
+{
+       int ret = ioctl(fd, KDBUS_CMD_UPDATE_METADATA);
+       return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
+}
+
 static inline wur int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd)
 {
        int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd);
index 2a2e14e6f071d8c0beeefbfaae1d2d242058a5be..cf12eb5b25c6a6e6724d44650dff0a73acd43b7b 100644 (file)
@@ -52,8 +52,6 @@ struct kdbus_test_args {
        char *busname;
 };
 
-pthread_mutex_t global_print_lock = PTHREAD_MUTEX_INITIALIZER;
-
 static const struct kdbus_test tests[] = {
        {
                .name   = "bus-make",
index 7addb4409e79e87724aa61d38296675f304adeda..dd79147849d74934c7f049c0b1b4094157b8ecff 100644 (file)
@@ -413,6 +413,7 @@ wur int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
                free(cmd);
                return -EIO;
        }
+       ASSERT_ZERO(kdbus_info_dump(cmd, info));
 
        if (offset) {
                *offset = cmd->offset;
@@ -722,90 +723,8 @@ static wur char *msg_id(uint64_t id, char *buf)
        return buf;
 }
 
-wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
-       const struct kdbus_item *item = msg->items;
-       char buf_src[32];
-       char buf_dst[32];
-       uint64_t timeout = 0;
-       uint64_t cookie_reply = 0;
-       int ret = 0;
-
-       if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
-               timeout = msg->timeout_ns;
-       else
-               cookie_reply = msg->cookie_reply;
-
-       kdbus_printf("MESSAGE(%p): %s (%llu bytes) flags=0x%08llx, %s → %s, "
-                    "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
-               msg,
-               enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size,
-               (unsigned long long)msg->flags,
-               msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst),
-               (unsigned long long)msg->cookie, (unsigned long long)timeout,
-               (unsigned long long)cookie_reply, (long long)msg->priority);
-
-       KDBUS_ITEM_FOREACH(item, msg, items) {
-               if (item->size < KDBUS_ITEM_HEADER_SIZE) {
-                       kdbus_printf("  +%s (%llu bytes) invalid data record\n",
-                                    enum_MSG(item->type), item->size);
-                       return -EINVAL;
-               }
-
-               switch (item->type) {
-               case KDBUS_ITEM_PAYLOAD_OFF: {
-                       char *s;
-
-                       if (item->vec.offset == ~0ULL)
-                               s = "[\\0-bytes]";
-                       else
-                               s = (char *)msg + item->vec.offset;
-
-                       kdbus_printf("  +%s (%llu bytes) off=%llu size=%llu '%s'\n",
-                              enum_MSG(item->type), item->size,
-                              (unsigned long long)item->vec.offset,
-                              (unsigned long long)item->vec.size, s);
-                       break;
-               }
-
-               case KDBUS_ITEM_FDS: {
-                       int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
-                                       sizeof(int);
-
-                       kdbus_printf("  +%s (%llu bytes, %d fds)\n",
-                              enum_MSG(item->type), item->size, n);
-
-                       for (i = 0; i < n; i++)
-                               kdbus_printf("    fd[%d] = %d\n",
-                                            i, item->fds[i]);
-
-                       break;
-               }
-
-               case KDBUS_ITEM_PAYLOAD_MEMFD: {
-                       char *buf;
-                       off_t size;
-
-                       buf = mmap(NULL, item->memfd.size, PROT_READ,
-                                  MAP_PRIVATE, item->memfd.fd, 0);
-                       if (buf == MAP_FAILED) {
-                               kdbus_printf("mmap() fd=%i size=%llu failed: %m\n",
-                                            item->memfd.fd, item->memfd.size);
-                               break;
-                       }
-
-                       if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
-                               kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
-                               break;
-                       }
-
-                       kdbus_printf("  +%s (%llu bytes) fd=%i size=%llu filesize=%llu '0x%llx'\n",
-                              enum_MSG(item->type), item->size, item->memfd.fd,
-                              (unsigned long long)item->memfd.size,
-                              (unsigned long long)size, (unsigned long long)(size >= 8 ? *(unsigned long long *)buf : size >= 4 ? *(unsigned *)buf : *buf));
-                       munmap(buf, item->memfd.size);
-                       break;
-               }
-
+static wur bool kdbus_dump_meta_item(struct kdbus_item const *item) {
+       switch (item->type) {
                case KDBUS_ITEM_CREDS:
                        kdbus_printf("  +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, "
                                                        "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n",
@@ -837,7 +756,6 @@ wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
                        break;
                }
 
-               case KDBUS_ITEM_NAME:
                case KDBUS_ITEM_PID_COMM:
                case KDBUS_ITEM_TID_COMM:
                case KDBUS_ITEM_EXE:
@@ -915,6 +833,128 @@ wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
                        kdbus_printf("\n");
                        break;
                }
+               defaul: return 0;
+       }
+       return 1;
+}
+
+wur int kdbus_info_dump(struct kdbus_cmd_info const *cmd, struct kdbus_info const *info) {
+       struct kdbus_item const *item;
+       kdbus_printf("CONN_INFO cmd(%p): (%llu bytes) flags=0x%08llx return_flags=0x%08llx attach_flags=0x%08llx id=%llu, "
+                    "offset=%llu, size=%llu\n",
+               cmd, (unsigned long long)cmd->size,
+               (unsigned long long)cmd->flags,
+               (unsigned long long)cmd->return_flags,
+               (unsigned long long)cmd->attach_flags,
+               (unsigned long long)cmd->id,
+               (unsigned long long)cmd->offset, (unsigned long long)cmd->info_size);
+       kdbus_printf("CONN_INFO info(%p): (%llu bytes) id=%llu flags=0x%08llx\n",
+               info, (unsigned long long)cmd->size, (unsigned long long)cmd->id, (unsigned long long)cmd->flags);
+
+       KDBUS_ITEM_FOREACH(item, info, items) {
+               if (item->size < KDBUS_ITEM_HEADER_SIZE) {
+                       kdbus_printf("  +%s (%llu bytes) invalid data record\n",
+                                    enum_MSG(item->type), item->size);
+                       return -EINVAL;
+               }
+               if (!kdbus_dump_meta_item(item))
+                       return TEST_ERR;
+       }
+       return 0;
+}
+
+wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
+       const struct kdbus_item *item = msg->items;
+       char buf_src[32];
+       char buf_dst[32];
+       uint64_t timeout = 0;
+       uint64_t cookie_reply = 0;
+       int ret = 0;
+
+       if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
+               timeout = msg->timeout_ns;
+       else
+               cookie_reply = msg->cookie_reply;
+
+       kdbus_printf("MESSAGE(%p): %s (%llu bytes) flags=0x%08llx, %s → %s, "
+                    "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
+               msg,
+               enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size,
+               (unsigned long long)msg->flags,
+               msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst),
+               (unsigned long long)msg->cookie, (unsigned long long)timeout,
+               (unsigned long long)cookie_reply, (long long)msg->priority);
+
+       KDBUS_ITEM_FOREACH(item, msg, items) {
+               if (item->size < KDBUS_ITEM_HEADER_SIZE) {
+                       kdbus_printf("  +%s (%llu bytes) invalid data record\n",
+                                    enum_MSG(item->type), item->size);
+                       return -EINVAL;
+               }
+
+               if (kdbus_dump_meta_item(item))
+                       continue;
+
+               switch (item->type) {
+               case KDBUS_ITEM_PAYLOAD_OFF: {
+                       char *s;
+
+                       if (item->vec.offset == ~0ULL)
+                               s = "[\\0-bytes]";
+                       else
+                               s = (char *)msg + item->vec.offset;
+
+                       kdbus_printf("  +%s (%llu bytes) off=%llu size=%llu '%s'\n",
+                              enum_MSG(item->type), item->size,
+                              (unsigned long long)item->vec.offset,
+                              (unsigned long long)item->vec.size, s);
+                       break;
+               }
+
+               case KDBUS_ITEM_FDS: {
+                       int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
+                                       sizeof(int);
+
+                       kdbus_printf("  +%s (%llu bytes, %d fds)\n",
+                              enum_MSG(item->type), item->size, n);
+
+                       for (i = 0; i < n; i++)
+                               kdbus_printf("    fd[%d] = %d\n",
+                                            i, item->fds[i]);
+
+                       break;
+               }
+
+               case KDBUS_ITEM_PAYLOAD_MEMFD: {
+                       char *buf;
+                       off_t size;
+
+                       buf = mmap(NULL, item->memfd.size, PROT_READ,
+                                  MAP_PRIVATE, item->memfd.fd, 0);
+                       if (buf == MAP_FAILED) {
+                               kdbus_printf("mmap() fd=%i size=%llu failed: %m\n",
+                                            item->memfd.fd, item->memfd.size);
+                               break;
+                       }
+
+                       if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
+                               kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
+                               break;
+                       }
+
+                       kdbus_printf("  +%s (%llu bytes) fd=%i size=%llu filesize=%llu '0x%llx'\n",
+                              enum_MSG(item->type), item->size, item->memfd.fd,
+                              (unsigned long long)item->memfd.size,
+                              (unsigned long long)size, (unsigned long long)(size >= 8 ? *(unsigned long long *)buf : size >= 4 ? *(unsigned *)buf : *buf));
+                       munmap(buf, item->memfd.size);
+                       break;
+               }
+
+               case KDBUS_ITEM_NAME:
+                       kdbus_printf("  +%s (%llu bytes) '%s' (%zu)\n",
+                                    enum_MSG(item->type), item->size,
+                                    item->str, strlen(item->str));
+                       break;
 
                case KDBUS_ITEM_TIMESTAMP:
                        kdbus_printf("  +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n",
index 654adc6f607e934b2ca1fd1509b7c8c0fb64b9e5..a6188d75903f901354547d4c19b99a9b1e99ba49 100644 (file)
@@ -217,6 +217,7 @@ wur int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms,
                        struct kdbus_msg **msg_out, uint64_t *offset);
 wur int kdbus_free(const struct kdbus_conn *conn, uint64_t offset);
 wur int kdbus_free_msg(struct kdbus_conn const *conn, struct kdbus_msg *msg);
+wur int kdbus_info_dump(struct kdbus_cmd_info const *cmd, struct kdbus_info const *info);
 wur int kdbus_msg_dump(const struct kdbus_msg *msg);
 wur int kdbus_create_bus(int control_fd, const char *name,
                     uint64_t owner_meta, char **path);
@@ -267,4 +268,4 @@ wur int test_is_capable(int cap, ...);
 wur int config_user_ns_is_enabled(void);
 wur int config_auditsyscall_is_enabled(void);
 wur int config_cgroups_is_enabled(void);
-wur int config_security_is_enabled(void);
\ No newline at end of file
+wur int config_security_is_enabled(void);
index 77e4c0e424e8d5a7acf28d78d29fd6b48f6b6d97..b0caf0fe968a64bbf47a307cba9acc20f1c63d60 100644 (file)
@@ -587,9 +587,26 @@ static wur int assert_label(char const *label, struct kdbus_item const *item)
        return TEST_OK;
 }
 
+static wur int get_label(char *buf, unsigned buf_size)
+{
+       int len=0;
+       int fd = open("/proc/self/attr/current", O_RDONLY);
+       if (fd < 0)
+               return -errno;
+       do len = read(fd, buf, buf_size); while (len < 0 && (EAGAIN==errno || EINTR==errno));
+       if (len < 0)
+               return -errno;
+       if (len == buf_size)
+               return -ENAMETOOLONG;
+       buf[len] = 0;
+       if (0 > close(fd))
+               return -errno;
+       return len;
+}
+
 static wur int set_label(char const *label)
 {
-       int fd = open("/proc/self/attr/current", O_RDWR);
+       int fd = open("/proc/self/attr/current", O_WRONLY);
        ASSERT_RETURN(fd,>=,0);
        int l = strlen(label);
        ASSERT_NONZERO(l);
@@ -611,9 +628,13 @@ static wur int assert_info_label(struct kdbus_conn *conn, uint64_t id, char cons
 
 wur int kdbus_test_dynamic_seclabel(struct kdbus_test_env *env)
 {
+       char old_label[65536];
        char const *labels[] = {"System::Privileged", "UserTest"};
+       char const *prev_label = old_label;
        unsigned i;
 
+       ASSERT_RETURN(0,<=,get_label(old_label, sizeof(old_label)));
+
        for (i=TABSIZE(labels); --i;) {
                char const *label = labels[i];
                ASSERT_ZERO(set_label(label));
@@ -624,7 +645,10 @@ wur int kdbus_test_dynamic_seclabel(struct kdbus_test_env *env)
                        ASSERT_ZERO(assert_label(label, msg->items));
                        kdbus_msg_free(msg);
                }
+               ASSERT_ZERO(assert_info_label(env->conn, env->conn->id, prev_label));
+               ASSERT_ZERO(kdbus_cmd_update_metadata(env->conn->fd));
                ASSERT_ZERO(assert_info_label(env->conn, env->conn->id, label));
+               prev_label = label;
        }
 
        RUN_FORKED(({
@@ -650,8 +674,9 @@ wur int kdbus_test_dynamic_seclabel(struct kdbus_test_env *env)
                        struct kdbus_msg *msg;
                        ASSERT_ZERO(kdbus_msg_recv_poll(env->conn, 500, &msg, NULL));
                        ASSERT_RETURN(i,==,msg->cookie-1);
-                       ASSERT_ZERO(set_label(labels[i]));
                        ASSERT_ZERO(assert_label("wuj", msg->items));
+                       ASSERT_ZERO(set_label(labels[i]));
+                       ASSERT_ZERO(kdbus_cmd_update_metadata(env->conn->fd));
                        ASSERT_ZERO(kdbus_msg_send_reply(env->conn, i+1, msg->src_id));
                        ASSERT_ZERO(assert_info_label(env->conn, msg->src_id, "wuj"));
                        kdbus_msg_free(msg);