From: Konrad Lipinski Date: Thu, 8 Dec 2016 14:11:27 +0000 (+0100) Subject: kdbus: CMD_UPDATE_METADATA, use it in seclabel test X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56ce4c373ed3110b85ff01ee4dab6f6fc17f50b0;p=platform%2Fkernel%2Flinux-exynos.git kdbus: CMD_UPDATE_METADATA, use it in seclabel test --- diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h index 4fc44cb1d4a8..c160849ab99f 100644 --- a/include/uapi/linux/kdbus.h +++ b/include/uapi/linux/kdbus.h @@ -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), diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c index 2939f0089c33..dc720dd8fdf8 100644 --- a/ipc/kdbus/bus.c +++ b/ipc/kdbus/bus.c @@ -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; } diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c index a12262095b2c..a0141de7326b 100644 --- a/ipc/kdbus/connection.c +++ b/ipc/kdbus/connection.c @@ -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("a[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 diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h index 9077095f2be4..755174bebc55 100644 --- a/ipc/kdbus/connection.h +++ b/ipc/kdbus/connection.h @@ -34,6 +34,17 @@ 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); diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c index ea669e8f5c48..c873b050733a 100644 --- a/ipc/kdbus/domain.c +++ b/ipc/kdbus/domain.c @@ -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; } diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c index f12843b47246..fb9d2b77bf43 100644 --- a/ipc/kdbus/endpoint.c +++ b/ipc/kdbus/endpoint.c @@ -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); diff --git a/ipc/kdbus/fs.c b/ipc/kdbus/fs.c index c67246a7cb1d..0b4c74acb625 100644 --- a/ipc/kdbus/fs.c +++ b/ipc/kdbus/fs.c @@ -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; diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c index d217cf8686a2..6441e69b51b4 100644 --- a/ipc/kdbus/handle.c +++ b/ipc/kdbus/handle.c @@ -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: diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c index 58e7274ccba6..259adf4a4872 100644 --- a/ipc/kdbus/main.c +++ b/ipc/kdbus/main.c @@ -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())) { diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c index 155d9dc6adc7..8af216bf6a07 100644 --- a/ipc/kdbus/match.c +++ b/ipc/kdbus/match.c @@ -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; } diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c index 5e5ac20dad33..f4e43de43a58 100644 --- a/ipc/kdbus/message.c +++ b/ipc/kdbus/message.c @@ -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; } diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c index eaebd34c77ae..d079a5240791 100644 --- a/ipc/kdbus/metadata.c +++ b/ipc/kdbus/metadata.c @@ -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(); diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h index f6e102be5225..acf19e81244e 100644 --- a/ipc/kdbus/metadata.h +++ b/ipc/kdbus/metadata.h @@ -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); diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c index 5ecc0be60452..d752291551e2 100644 --- a/ipc/kdbus/names.c +++ b/ipc/kdbus/names.c @@ -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; diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c index 0bc189742097..9460720084b9 100644 --- a/ipc/kdbus/node.c +++ b/ipc/kdbus/node.c @@ -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); } diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c index d18e42d8cac5..9122ae8f192c 100644 --- a/ipc/kdbus/policy.c +++ b/ipc/kdbus/policy.c @@ -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; } diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c index bb51dc836d33..c7c1eb7b297a 100644 --- a/ipc/kdbus/pool.c +++ b/ipc/kdbus/pool.c @@ -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; } diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c index e0ae70835024..006bc9821d88 100644 --- a/ipc/kdbus/reply.c +++ b/ipc/kdbus/reply.c @@ -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; } diff --git a/tools/testing/selftests/kdbus/kdbus-api.h b/tools/testing/selftests/kdbus/kdbus-api.h index 4189a6a1b1db..26b111fd82e9 100644 --- a/tools/testing/selftests/kdbus/kdbus-api.h +++ b/tools/testing/selftests/kdbus/kdbus-api.h @@ -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); diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c index 2a2e14e6f071..cf12eb5b25c6 100644 --- a/tools/testing/selftests/kdbus/kdbus-test.c +++ b/tools/testing/selftests/kdbus/kdbus-test.c @@ -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", diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c index 7addb4409e79..dd79147849d7 100644 --- a/tools/testing/selftests/kdbus/kdbus-util.c +++ b/tools/testing/selftests/kdbus/kdbus-util.c @@ -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", diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h index 654adc6f607e..a6188d75903f 100644 --- a/tools/testing/selftests/kdbus/kdbus-util.h +++ b/tools/testing/selftests/kdbus/kdbus-util.h @@ -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); diff --git a/tools/testing/selftests/kdbus/test-match.c b/tools/testing/selftests/kdbus/test-match.c index 77e4c0e424e8..b0caf0fe968a 100644 --- a/tools/testing/selftests/kdbus/test-match.c +++ b/tools/testing/selftests/kdbus/test-match.c @@ -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);