diff options
-rw-r--r-- | bus.c | 10 | ||||
-rw-r--r-- | connection.c | 7 | ||||
-rw-r--r-- | handle.c | 2 | ||||
-rw-r--r-- | metadata.c | 145 | ||||
-rw-r--r-- | metadata.h | 8 |
5 files changed, 97 insertions, 75 deletions
@@ -177,7 +177,7 @@ struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain, goto exit_unref; } - ret = kdbus_meta_collect(b->meta, 0, + ret = kdbus_meta_collect(b->meta, NULL, 0, KDBUS_ATTACH_CREDS | KDBUS_ATTACH_PIDS | KDBUS_ATTACH_AUXGROUPS | @@ -386,7 +386,8 @@ void kdbus_bus_broadcast(struct kdbus_bus *bus, * requested metadata. It's up to the receiver to drop * messages that lack expected metadata. */ - kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, conn_dst); + kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, + NULL, conn_dst); } else { /* * Check if there is a policy db that prevents the @@ -437,7 +438,8 @@ void kdbus_bus_eavesdrop(struct kdbus_bus *bus, * that lack data, than to skip it entirely. */ if (conn_src) - kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, conn_dst); + kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, + conn_src, conn_dst); kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL); } @@ -469,7 +471,7 @@ int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, name_len = strlen(bus->node.name); name_size = KDBUS_ITEM_SIZE(name_len + 1); - ret = kdbus_meta_export(bus->meta, NULL, conn, flags, &buf, &meta_size); + ret = kdbus_meta_export(bus->meta, conn, flags, &buf, &meta_size); if (ret < 0) return ret; diff --git a/connection.c b/connection.c index e341ce3914d..0106d30a6d6 100644 --- a/connection.c +++ b/connection.c @@ -550,7 +550,7 @@ static int kdbus_conn_export_meta(struct kdbus_conn *conn_src, /* any message with source must have metadata allocated */ BUG_ON(!kmsg->meta); - return kdbus_meta_export(kmsg->meta, conn_src, conn_dst, attach_flags, + return kdbus_meta_export(kmsg->meta, conn_dst, attach_flags, out_buf, out_size); } @@ -911,7 +911,8 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, goto wait_sync; } - ret = kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, conn_dst); + ret = kdbus_meta_collect_dst(kmsg->meta, kmsg->seq, + conn_src, conn_dst); if (ret < 0) goto exit_unref; @@ -1401,7 +1402,7 @@ int kdbus_cmd_info(struct kdbus_conn *conn, attach_flags = cmd_info->flags & atomic64_read(&owner_conn->attach_flags_send); - ret = kdbus_meta_export(owner_conn->meta, owner_conn, conn, + ret = kdbus_meta_export(owner_conn->meta, conn, attach_flags, &meta_buf, &meta_size); if (ret < 0) goto exit; @@ -120,7 +120,7 @@ static int handle_ep_open(struct inode *inode, struct file *file) goto exit_free; } - ret = kdbus_meta_collect(handle->meta, 0, + ret = kdbus_meta_collect(handle->meta, NULL, 0, KDBUS_ATTACH_CREDS | KDBUS_ATTACH_PIDS | KDBUS_ATTACH_AUXGROUPS | diff --git a/metadata.c b/metadata.c index 364196eeb5b..f66a090e411 100644 --- a/metadata.c +++ b/metadata.c @@ -46,6 +46,9 @@ * @egid: Task egid * @sgid: Task sgid * @fsgid: Task fsgid + * @conn_description: Source connection's description + * @owned_names_items: Array of items with names owned by the source + * @owned_names_size: Number of bytes in @owned_names_items * @audit_loginuid: Audit loginuid * @audit_sessionid: Audio session ID * @seclabel: LSM security label @@ -90,6 +93,10 @@ struct kdbus_meta { kgid_t sgid; kgid_t fsgid; + char *conn_description; + struct kdbus_item *owned_names_items; + size_t owned_names_size; + kuid_t audit_loginuid; unsigned int audit_sessionid; @@ -144,7 +151,7 @@ struct kdbus_meta *kdbus_meta_new(void) static void __kdbus_meta_free(struct kref *kref) { - struct kdbus_meta *meta = container_of(kref, struct kdbus_meta, kref); + struct kdbus_meta *meta = container_of(kref, struct kdbus_meta, kref); if (meta->exe) fput(meta->exe); @@ -153,6 +160,8 @@ static void __kdbus_meta_free(struct kref *kref) put_pid(meta->tgid); put_pid(meta->pid); + kfree(meta->owned_names_items); + kfree(meta->conn_description); kfree(meta->seclabel); kfree(meta->auxgrps); kfree(meta->cmdline); @@ -248,9 +257,21 @@ int kdbus_meta_fake(struct kdbus_meta *meta, return 0; } +static inline void kdbus_meta_write_item(struct kdbus_item *item, u64 type, + const void *data, size_t len) +{ + item->type = type; + item->size = KDBUS_ITEM_HEADER_SIZE + len; + + if (data) + memcpy(item->data, data, len); +} + /** * kdbus_meta_collect() - collect metadata from current process * @meta: Metadata object + * @conn_src: Connection to get owned names and description from, + * may be %NULL * @seq: Message sequence number * @which: KDBUS_ATTACH_* mask * @@ -261,6 +282,7 @@ int kdbus_meta_fake(struct kdbus_meta *meta, * Return: 0 on success, negative errno on failure. */ int kdbus_meta_collect(struct kdbus_meta *meta, + struct kdbus_conn *conn_src, u64 seq, u64 which) { u64 mask; @@ -349,6 +371,43 @@ int kdbus_meta_collect(struct kdbus_meta *meta, meta->collected |= KDBUS_ATTACH_TID_COMM; } + if (mask & KDBUS_ATTACH_NAMES && conn_src) { + const struct kdbus_name_entry *e; + struct kdbus_item *item; + + meta->owned_names_size = 0; + + list_for_each_entry(e, &conn_src->names_list, conn_entry) + meta->owned_names_size += + KDBUS_ITEM_SIZE(strlen(e->name) + 1); + + meta->owned_names_items = + kmalloc(meta->owned_names_size, GFP_KERNEL); + if (!meta->owned_names_items) + return -ENOMEM; + + item = meta->owned_names_items; + + list_for_each_entry(e, &conn_src->names_list, conn_entry) { + kdbus_meta_write_item(item, KDBUS_ITEM_OWNED_NAME, + e->name, strlen(e->name) + 1); + item = KDBUS_ITEM_NEXT(item); + } + + meta->collected |= KDBUS_ATTACH_NAMES; + } + +#if 0 + if (mask & KDBUS_ATTACH_CONN_DESCRIPTION && + conn_src && conn_src->name) { + meta->conn_description = kstrdup(conn_src->name, GFP_KERNEL); + if (!meta->conn_description) + return -ENOMEM; + + meta->collected |= KDBUS_ATTACH_CONN_DESCRIPTION; + } +#endif + if (mask & KDBUS_ATTACH_EXE) { struct mm_struct *mm = get_task_mm(current); @@ -471,20 +530,11 @@ int kdbus_meta_collect(struct kdbus_meta *meta, * Return: 0 on success, negative error code on failure. */ int kdbus_meta_collect_dst(struct kdbus_meta *meta, u64 seq, - const struct kdbus_conn *conn) + struct kdbus_conn *conn_src, + const struct kdbus_conn *conn_dst) { - return kdbus_meta_collect(meta, seq, - atomic64_read(&conn->attach_flags_recv)); -} - -static inline void kdbus_meta_write_item(struct kdbus_item *item, u64 type, - const void *data, size_t len) -{ - item->type = type; - item->size = KDBUS_ITEM_HEADER_SIZE + len; - - if (data) - memcpy(item->data, data, len); + return kdbus_meta_collect(meta, conn_src, seq, + atomic64_read(&conn_dst->attach_flags_recv)); } static void kdbus_meta_export_creds(const struct kdbus_meta *meta, @@ -521,7 +571,6 @@ static void kdbus_meta_export_creds(const struct kdbus_meta *meta, /** * kdbus_meta_export() - export information from metadata into buffer * @meta: The metadata object - * @conn_src: Connection to get description and owned names from, may be %NULL * @conn_dst: Connection to translate items for * @mask: Mask of KDBUS_ATTACH_* flags to export * @buf: Pointer to return the allocated buffer @@ -531,9 +580,6 @@ static void kdbus_meta_export_creds(const struct kdbus_meta *meta, * Only information that is requested in @mask and that has been collected * before is exported. * - * If @conn_src is %NULL, the attach flags KDBUS_ATTACH_NAMES and - * KDBUS_ATTACH_CONN_DESCRIPTION will be ignored. - * * All information will be translated using the namespaces pinned by @conn_dst. * * Upon success, @buf will point to the newly allocated buffer, and @sz will @@ -543,34 +589,22 @@ static void kdbus_meta_export_creds(const struct kdbus_meta *meta, * Return: 0 on success, nagative error number otherwise. */ int kdbus_meta_export(const struct kdbus_meta *meta, - struct kdbus_conn *conn_src, struct kdbus_conn *conn_dst, u64 mask, u8 **buf, size_t *sz) { struct user_namespace *user_ns; struct pid_namespace *pid_ns; - struct kdbus_name_entry *e; struct kdbus_item *item; char *exe_pathname = NULL; size_t size = 0; - bool src_lock; int ret = 0; - u64 conn_items = 0; u8 *p, *tmp; tmp = (char *)__get_free_page(GFP_TEMPORARY | __GFP_ZERO); if (!tmp) return -ENOMEM; - if (conn_src) { - if (conn_src->name) - conn_items |= KDBUS_ATTACH_CONN_DESCRIPTION; - - conn_items |= KDBUS_ATTACH_NAMES; - } - - mask &= (meta->collected | conn_items) & kdbus_meta_attach_mask; - src_lock = !!(mask & conn_items); + mask &= meta->collected & kdbus_meta_attach_mask; user_ns = conn_dst->user_namespace; pid_ns = conn_dst->pid_namespace; @@ -643,16 +677,11 @@ int kdbus_meta_export(const struct kdbus_meta *meta, if (mask & KDBUS_ATTACH_AUDIT) size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit)); - if (src_lock) - mutex_lock(&conn_src->lock); + if (mask & KDBUS_ATTACH_CONN_DESCRIPTION) + size += KDBUS_ITEM_SIZE(strlen(meta->conn_description) + 1); if (mask & KDBUS_ATTACH_NAMES) - list_for_each_entry(e, &conn_src->names_list, conn_entry) - size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_name) + - strlen(e->name) + 1); - - if (mask & KDBUS_ATTACH_CONN_DESCRIPTION) - size += KDBUS_ITEM_SIZE(strlen(conn_src->name) + 1); + size += meta->owned_names_size; /* * Now we know how big our final blog of metadata will be. @@ -661,9 +690,6 @@ int kdbus_meta_export(const struct kdbus_meta *meta, p = kzalloc(size, GFP_KERNEL); if (!p) { - if (src_lock) - mutex_unlock(&conn_src->lock); - ret = -ENOMEM; goto exit_free; } @@ -715,28 +741,6 @@ int kdbus_meta_export(const struct kdbus_meta *meta, item = KDBUS_ITEM_NEXT(item); } - if (mask & KDBUS_ATTACH_CONN_DESCRIPTION) { - kdbus_meta_write_item(item, KDBUS_ITEM_CONN_DESCRIPTION, - conn_src->name, - strlen(conn_src->name) + 1); - item = KDBUS_ITEM_NEXT(item); - } - - if (mask & KDBUS_ATTACH_NAMES) - list_for_each_entry(e, &conn_src->names_list, conn_entry) { - size_t len = strlen(e->name) + 1; - - kdbus_meta_write_item(item, KDBUS_ITEM_OWNED_NAME, - NULL, - sizeof(struct kdbus_name) + len); - item->name.flags = e->flags; - memcpy(item->name.name, e->name, len); - item = KDBUS_ITEM_NEXT(item); - } - - if (src_lock) - mutex_unlock(&conn_src->lock); - if (mask & KDBUS_ATTACH_PID_COMM) { kdbus_meta_write_item(item, KDBUS_ITEM_PID_COMM, meta->pid_comm, @@ -792,6 +796,19 @@ int kdbus_meta_export(const struct kdbus_meta *meta, item = KDBUS_ITEM_NEXT(item); } + if (mask & KDBUS_ATTACH_CONN_DESCRIPTION) { + kdbus_meta_write_item(item, KDBUS_ITEM_CONN_DESCRIPTION, + meta->conn_description, + strlen(meta->conn_description) + 1); + item = KDBUS_ITEM_NEXT(item); + } + + if (mask & KDBUS_ATTACH_NAMES) { + memcpy(item, meta->owned_names_items, meta->owned_names_size); + item = (struct kdbus_item *) + ((u8 *) item + meta->owned_names_size); + } + /* sanity check: the buffer should be completely written now */ WARN_ON((char *) item != (char *) (p + size)); diff --git a/metadata.h b/metadata.h index 9f8a268858f..1ea12ddee17 100644 --- a/metadata.h +++ b/metadata.h @@ -25,15 +25,17 @@ struct kdbus_meta *kdbus_meta_new(void); struct kdbus_meta *kdbus_meta_ref(struct kdbus_meta *meta); struct kdbus_meta *kdbus_meta_unref(struct kdbus_meta *meta); -int kdbus_meta_collect(struct kdbus_meta *meta, u64 seq, u64 which); +int kdbus_meta_collect(struct kdbus_meta *meta, + struct kdbus_conn *conn_src, + u64 seq, u64 which); int kdbus_meta_collect_dst(struct kdbus_meta *meta, u64 seq, - const struct kdbus_conn *conn); + struct kdbus_conn *conn_src, + const struct kdbus_conn *conn_dst); int kdbus_meta_fake(struct kdbus_meta *meta, const struct kdbus_creds *creds, const struct kdbus_pids *pids, const char *seclabel); int kdbus_meta_export(const struct kdbus_meta *meta, - struct kdbus_conn *conn_src, struct kdbus_conn *conn_dst, u64 mask, u8 **buf, size_t *size); |