#include "domain.h"
#include "endpoint.h"
#include "item.h"
+#include "metadata.h"
#include "names.h"
#include "policy.h"
kdbus_name_registry_free(bus->name_registry);
kdbus_domain_unref(bus->domain);
kdbus_policy_db_clear(&bus->policy_db);
+ kdbus_meta_free(bus->meta);
kfree(bus->name);
kfree(bus);
}
return bus;
}
+/**
+ * kdbus_cmd_bus_creator_info() - get information on a bus creator
+ * @conn: The querying connection
+ * @cmd_info: The command buffer, as passed in from the ioctl
+ *
+ * Gather information on the creator of the bus @conn is connected to.
+ *
+ * Return: 0 on success, error otherwise.
+ */
+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn,
+ struct kdbus_cmd_conn_info *cmd_info)
+{
+ struct kdbus_bus *bus = conn->bus;
+ struct kdbus_pool_slice *slice;
+ struct kdbus_conn_info info = {};
+ int ret;
+
+ info.size = sizeof(info) + bus->meta->size;
+ info.id = bus->id;
+ info.flags = bus->bus_flags;
+
+ if (!kdbus_meta_ns_eq(conn->meta, bus->meta))
+ return -EPERM;
+
+ ret = kdbus_pool_slice_alloc(conn->pool, &slice, info.size);
+ if (ret < 0)
+ return ret;
+
+ ret = kdbus_pool_slice_copy(slice, 0, &info, sizeof(info));
+ if (ret < 0)
+ goto exit_free_slice;
+
+ ret = kdbus_pool_slice_copy(slice, sizeof(info), bus->meta->data,
+ bus->meta->size);
+ if (ret < 0)
+ goto exit_free_slice;
+
+ /* write back the offset */
+ cmd_info->offset = kdbus_pool_slice_offset(slice);
+ kdbus_pool_slice_flush(slice);
+ kdbus_pool_slice_make_public(slice);
+
+ return 0;
+
+exit_free_slice:
+ kdbus_pool_slice_free(slice);
+ return ret;
+}
+
/**
* kdbus_bus_new() - create a new bus
* @domain: The domain to work on
/* generate unique bus id */
generate_random_uuid(b->id128);
+ /* cache the metadata/credentials of the creator */
+ ret = kdbus_meta_new(&b->meta);
+ if (ret < 0)
+ return ret;
+
+ ret = kdbus_meta_append(b->meta, NULL, 0,
+ KDBUS_ATTACH_CREDS |
+ KDBUS_ATTACH_TID_COMM |
+ KDBUS_ATTACH_PID_COMM |
+ KDBUS_ATTACH_EXE |
+ KDBUS_ATTACH_CMDLINE |
+ KDBUS_ATTACH_CGROUP |
+ KDBUS_ATTACH_CAPS |
+ KDBUS_ATTACH_SECLABEL |
+ KDBUS_ATTACH_AUDIT);
+ if (ret < 0)
+ goto exit_free;
+
b->name = kstrdup(name, GFP_KERNEL);
if (!b->name) {
ret = -ENOMEM;
exit_free_name:
kfree(b->name);
exit_free:
+ kdbus_meta_free(b->meta);
kdbus_policy_db_clear(&b->policy_db);
kdbus_domain_unref(b->domain);
kfree(b);
* @conn_rwlock: Read/Write lock for all lists of child connections
* @conn_hash: Map of connection IDs
* @monitors_list: Connections that monitor this bus
+ * @meta: Meta information about the bus creator
*
* A bus provides a "bus" endpoint / device node.
*
struct rw_semaphore conn_rwlock;
DECLARE_HASHTABLE(conn_hash, 8);
struct list_head monitors_list;
+
+ struct kdbus_meta *meta;
};
int kdbus_bus_make_user(const struct kdbus_cmd_make *make,
const struct kdbus_bloom_parameter *bloom,
umode_t mode, kuid_t uid, kgid_t gid,
struct kdbus_bus **bus);
+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn,
+ struct kdbus_cmd_conn_info *cmd_info);
struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus);
struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus);
void kdbus_bus_disconnect(struct kdbus_bus *bus);
break;
}
- case KDBUS_CMD_CONN_INFO: {
+ case KDBUS_CMD_CONN_INFO:
+ case KDBUS_CMD_BUS_CREATOR_INFO: {
struct kdbus_cmd_conn_info *cmd_info;
/* return the properties of a connection */
if (ret < 0)
break;
- ret = kdbus_cmd_conn_info(conn, cmd_info);
+ if (cmd == KDBUS_CMD_CONN_INFO)
+ ret = kdbus_cmd_conn_info(conn, cmd_info);
+ else
+ ret = kdbus_cmd_bus_creator_info(conn, cmd_info);
+
if (ret < 0)
break;
* @KDBUS_CMD_CONN_UPDATE: Update the properties of a connection. Used to
* update the metadata subscription mask and
* policy.
+ * @KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus
+ * a connection is attached to.
* @KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used
* to update the policy.
* @KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
struct kdbus_cmd_conn_info),
KDBUS_CMD_CONN_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x61,
struct kdbus_cmd_update),
+ KDBUS_CMD_BUS_CREATOR_INFO = _IOWR(KDBUS_IOCTL_MAGIC, 0x62,
+ struct kdbus_cmd_conn_info),
KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x71,
struct kdbus_cmd_update),
KDBUS_CMD_FREE for the offset.
-6.5 Updating connection details
+6.5 Getting information about a connection's bus creator
+--------------------------------------------------------
+
+The KDBUS_CMD_BUS_CREATOR_INFO ioctl takes the same struct as
+KDBUS_CMD_CONN_INFO but is used to retrieve information about the creator of
+the bus the connection is attached to. The metadata returned by this call is
+collected during the creation of the bus and is never altered afterwards, so
+it provides pristine information on the task that created the bus, at the
+moment when it did so.
+
+In response to this call, a slice in the connection's pool is allocated and
+filled with an object of type struct kdbus_conn_info, pointed to by the ioctl's
+'offset' field.
+
+struct kdbus_conn_info {
+ __u64 size;
+ The overall size of the struct, including all its items.
+
+ __u64 id;
+ The bus' ID
+
+ __u64 flags;
+ The bus' flags as specified when it was created.
+
+ __u64 kernel_flags;
+ Valid flags for this command, returned by the kernel upon each call.
+
+ struct kdbus_item items[0];
+ Metadata information is stored in items here.
+};
+
+Once the caller is finished with parsing the return buffer, it needs to call
+KDBUS_CMD_FREE for the offset.
+
+
+6.6 Updating connection details
-------------------------------
Some of a connection's details can be updated with the KDBUS_CMD_CONN_UPDATE
kdbus-test.o \
test-activator.o \
test-benchmark.o \
+ test-bus.o \
test-chat.o \
test-connection.o \
test-daemon.o \
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+
+#include "kdbus-util.h"
+#include "kdbus-enum.h"
+#include "kdbus-test.h"
+
+static int test_bus_creator_info(const char *bus_path)
+{
+ int ret;
+ struct kdbus_conn *conn;
+ struct kdbus_cmd_conn_info cmd = {};
+
+ cmd.size = sizeof(cmd);
+
+ conn = kdbus_hello(bus_path, 0, NULL, 0);
+ ASSERT_RETURN(conn);
+
+ ret = ioctl(conn->fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
+ ASSERT_RETURN_VAL(ret == 0, ret);
+
+ ret = kdbus_free(conn, cmd.offset);
+ ASSERT_RETURN_VAL(ret == 0, ret);
+
+ return 0;
+}
+
+int kdbus_test_bus_make(struct kdbus_test_env *env)
+{
+ struct {
+ struct kdbus_cmd_make head;
+
+ /* bloom size item */
+ struct {
+ uint64_t size;
+ uint64_t type;
+ struct kdbus_bloom_parameter bloom;
+ } bs;
+
+ /* name item */
+ uint64_t n_size;
+ uint64_t n_type;
+ char name[64];
+ } bus_make;
+ char s[PATH_MAX];
+ int ret;
+ uid_t uid;
+
+ env->control_fd = open("/dev/" KBUILD_MODNAME "/control",
+ O_RDWR|O_CLOEXEC);
+ ASSERT_RETURN(env->control_fd >= 0);
+
+ memset(&bus_make, 0, sizeof(bus_make));
+
+ bus_make.bs.size = sizeof(bus_make.bs);
+ bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER;
+ bus_make.bs.bloom.size = 64;
+ bus_make.bs.bloom.n_hash = 1;
+
+ bus_make.n_type = KDBUS_ITEM_MAKE_NAME;
+
+ uid = getuid();
+
+ /* missing uid prefix */
+ snprintf(bus_make.name, sizeof(bus_make.name), "foo");
+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.head.size = sizeof(struct kdbus_cmd_make) +
+ sizeof(bus_make.bs) + bus_make.n_size;
+ ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
+ ASSERT_RETURN(ret == -1 && errno == EINVAL);
+
+ /* non alphanumeric character */
+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid);
+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.head.size = sizeof(struct kdbus_cmd_make) +
+ sizeof(bus_make.bs) + bus_make.n_size;
+ ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
+ ASSERT_RETURN(ret == -1 && errno == EINVAL);
+
+ /* '-' at the end */
+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid);
+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.head.size = sizeof(struct kdbus_cmd_make) +
+ sizeof(bus_make.bs) + bus_make.n_size;
+ ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
+ ASSERT_RETURN(ret == -1 && errno == EINVAL);
+
+ /* create a new bus */
+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-1", uid);
+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.head.size = sizeof(struct kdbus_cmd_make) +
+ sizeof(bus_make.bs) + bus_make.n_size;
+ ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
+ ASSERT_RETURN(ret == 0);
+ snprintf(s, sizeof(s), "/dev/" KBUILD_MODNAME "/%u-blah-1/bus", uid);
+ ASSERT_RETURN(access(s, F_OK) == 0);
+
+ ret = test_bus_creator_info(s);
+ ASSERT_RETURN(ret == 0);
+
+ /* can't use the same fd for bus make twice */
+ ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
+ ASSERT_RETURN(ret == -1 && errno == EBADFD);
+
+ return TEST_OK;
+}
#include "kdbus-enum.h"
#include "kdbus-test.h"
-int kdbus_test_bus_make(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_make head;
-
- /* bloom size item */
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_bloom_parameter bloom;
- } bs;
-
- /* name item */
- uint64_t n_size;
- uint64_t n_type;
- char name[64];
- } bus_make;
- char s[PATH_MAX];
- int ret;
- uid_t uid;
-
- env->control_fd = open("/dev/" KBUILD_MODNAME "/control",
- O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(env->control_fd >= 0);
-
- memset(&bus_make, 0, sizeof(bus_make));
-
- bus_make.bs.size = sizeof(bus_make.bs);
- bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER;
- bus_make.bs.bloom.size = 64;
- bus_make.bs.bloom.n_hash = 1;
-
- bus_make.n_type = KDBUS_ITEM_MAKE_NAME;
-
- uid = getuid();
-
- /* missing uid prefix */
- snprintf(bus_make.name, sizeof(bus_make.name), "foo");
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.head.size = sizeof(struct kdbus_cmd_make) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
- ASSERT_RETURN(ret == -1 && errno == EINVAL);
-
- /* non alphanumeric character */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.head.size = sizeof(struct kdbus_cmd_make) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
- ASSERT_RETURN(ret == -1 && errno == EINVAL);
-
- /* '-' at the end */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.head.size = sizeof(struct kdbus_cmd_make) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
- ASSERT_RETURN(ret == -1 && errno == EINVAL);
-
- /* create a new bus */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-1", uid);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.head.size = sizeof(struct kdbus_cmd_make) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
- ASSERT_RETURN(ret == 0);
- snprintf(s, sizeof(s), "/dev/" KBUILD_MODNAME "/%u-blah-1/bus", uid);
- ASSERT_RETURN(access(s, F_OK) == 0);
-
- /* can't use the same fd for bus make twice */
- ret = ioctl(env->control_fd, KDBUS_CMD_BUS_MAKE, &bus_make);
- ASSERT_RETURN(ret == -1 && errno == EBADFD);
-
- return TEST_OK;
-}
-
int kdbus_test_hello(struct kdbus_test_env *env)
{
struct kdbus_cmd_hello hello;