summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2013-05-22 10:53:02 +0200
committerKay Sievers <kay@vrfy.org>2013-05-24 03:07:40 +0200
commit48b24f974d131f2d85b47e128cc08f84cfa8db9c (patch)
tree6e224bd7d0885b2d947470b93eafc5f720e06fa1
parentcda746371aced17f995e494f1629cc1e8a2bc863 (diff)
downloadkdbus-bus-48b24f974d131f2d85b47e128cc08f84cfa8db9c.tar.gz
kdbus-bus-48b24f974d131f2d85b47e128cc08f84cfa8db9c.tar.bz2
kdbus-bus-48b24f974d131f2d85b47e128cc08f84cfa8db9c.zip
make part iteration generic; *really* validate parts, fix now failing test
-rw-r--r--TODO2
-rw-r--r--bus.c19
-rw-r--r--connection.c26
-rw-r--r--endpoint.c16
-rw-r--r--internal.h29
-rw-r--r--kdbus.h65
-rw-r--r--match.c9
-rw-r--r--message.c26
-rw-r--r--names.c42
-rw-r--r--namespace.c16
-rw-r--r--policy.c19
-rw-r--r--test/kdbus-util.c101
-rw-r--r--test/kdbus-util.h26
-rw-r--r--test/test-kdbus-daemon.c4
-rw-r--r--test/test-kdbus.c8
15 files changed, 211 insertions, 197 deletions
diff --git a/TODO b/TODO
index 1aac0d8b03c..399046fce41 100644
--- a/TODO
+++ b/TODO
@@ -16,6 +16,8 @@ Internal:
accounts against its budget, security_vm_enough_memory_mm())?
- how to limit memfd memory?
- memfd's file pos is shared, which can be confusing, document pread/pwrite
+ - prefix all functions with kdbus
+ - signals miss all the process metadata, we attach only creds
Kernel Core:
- remove our own task_cgroup_path_from_hierarchy() as soon as it's available:
diff --git a/bus.c b/bus.c
index 51e415e1e17..1a6b18eb6a3 100644
--- a/bus.c
+++ b/bus.c
@@ -245,9 +245,8 @@ int kdbus_bus_make_user(void __user *buf, struct kdbus_cmd_bus_kmake **kmake)
goto exit;
}
- KDBUS_ITEM_FOREACH_VALIDATE(item, &km->make) {
- /* empty items are invalid */
- if (item->size <= KDBUS_ITEM_HEADER_SIZE) {
+ KDBUS_PART_FOREACH(item, &km->make, items) {
+ if (!KDBUS_PART_VALID(item, &km->make)) {
ret = -EINVAL;
goto exit;
}
@@ -259,18 +258,18 @@ int kdbus_bus_make_user(void __user *buf, struct kdbus_cmd_bus_kmake **kmake)
goto exit;
}
- if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) {
+ if (item->size < KDBUS_PART_HEADER_SIZE + 2) {
ret = -EINVAL;
goto exit;
}
- if (item->size > KDBUS_ITEM_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
+ if (item->size > KDBUS_PART_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
ret = -ENAMETOOLONG;
goto exit;
}
if (!kdbus_validate_nul(item->str,
- item->size - KDBUS_ITEM_HEADER_SIZE)) {
+ item->size - KDBUS_PART_HEADER_SIZE)) {
ret = -EINVAL;
goto exit;
}
@@ -279,6 +278,11 @@ int kdbus_bus_make_user(void __user *buf, struct kdbus_cmd_bus_kmake **kmake)
continue;
case KDBUS_MAKE_CGROUP:
+ if (item->size != KDBUS_PART_HEADER_SIZE + sizeof(__u64)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
if (km->cgroup_id) {
ret = -EEXIST;
goto exit;
@@ -293,8 +297,7 @@ int kdbus_bus_make_user(void __user *buf, struct kdbus_cmd_bus_kmake **kmake)
}
}
- /* expect correct padding and size values */
- if ((char *)item - ((char *)&km->make + km->make.size) >= 8)
+ if (!KDBUS_PART_END(item, &km->make))
return -EINVAL;
if (!km->name) {
diff --git a/connection.c b/connection.c
index 094090aec3a..4e133d4475d 100644
--- a/connection.c
+++ b/connection.c
@@ -191,10 +191,10 @@ static int kdbus_conn_payload_add(struct kdbus_conn_queue *queue,
return -ENOMEM;
}
- KDBUS_ITEM_FOREACH(item, &kmsg->msg) {
+ KDBUS_PART_FOREACH(item, &kmsg->msg, items) {
switch (item->type) {
case KDBUS_MSG_PAYLOAD_VEC: {
- size_t size = KDBUS_ITEM_HEADER_SIZE +
+ size_t size = KDBUS_PART_HEADER_SIZE +
sizeof(struct kdbus_vec);
char tmp[size];
struct kdbus_item *it = (struct kdbus_item *)tmp;
@@ -225,7 +225,7 @@ static int kdbus_conn_payload_add(struct kdbus_conn_queue *queue,
}
case KDBUS_MSG_PAYLOAD_MEMFD: {
- size_t size = KDBUS_ITEM_HEADER_SIZE +
+ size_t size = KDBUS_PART_HEADER_SIZE +
sizeof(struct kdbus_memfd);
char tmp[size];
struct kdbus_item *it = (struct kdbus_item *)tmp;
@@ -379,7 +379,7 @@ int kdbus_conn_queue_insert(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg,
/* add a FDS item; the array content will be updated at RECV time */
if (kmsg->fds_count > 0) {
- size_t size = KDBUS_ITEM_HEADER_SIZE;
+ size_t size = KDBUS_PART_HEADER_SIZE;
char tmp[size];
struct kdbus_item *it = (struct kdbus_item *)tmp;
@@ -525,6 +525,8 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep,
kmsg))
continue;
+ //FIXME: call kdbus_kmsg_append_for_dst()?
+
kdbus_conn_queue_insert(conn_dst, kmsg, 0);
}
mutex_unlock(&ep->bus->lock);
@@ -564,11 +566,9 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep,
return ret;
}
- if (conn_src) {
- ret = kdbus_kmsg_append_for_dst(kmsg, conn_src, conn_dst);
- if (ret < 0)
- return ret;
- }
+ ret = kdbus_kmsg_append_for_dst(kmsg, conn_src, conn_dst);
+ if (ret < 0)
+ return ret;
/* monitor connections get all messages */
mutex_lock(&ep->bus->lock);
@@ -1127,9 +1127,8 @@ static long kdbus_conn_ioctl_ep(struct file *file, unsigned int cmd,
break;
}
- KDBUS_ITEM_FOREACH_VALIDATE(item, hello) {
- /* empty items are invalid */
- if (item->size <= KDBUS_ITEM_HEADER_SIZE) {
+ KDBUS_PART_FOREACH(item, hello, items) {
+ if (!KDBUS_PART_VALID(item, hello)) {
ret = -EINVAL;
break;
}
@@ -1168,6 +1167,9 @@ static long kdbus_conn_ioctl_ep(struct file *file, unsigned int cmd,
}
}
+ if (!KDBUS_PART_END(item, hello))
+ return -EINVAL;
+
mutex_init(&conn->lock);
mutex_init(&conn->names_lock);
mutex_init(&conn->accounting_lock);
diff --git a/endpoint.c b/endpoint.c
index f1610769e61..834d595c53b 100644
--- a/endpoint.c
+++ b/endpoint.c
@@ -236,9 +236,8 @@ int kdbus_ep_kmake_user(void __user *buf, struct kdbus_cmd_ep_kmake **kmake)
goto exit;
}
- KDBUS_ITEM_FOREACH_VALIDATE(item, &km->make) {
- /* empty items are invalid */
- if (item->size <= KDBUS_ITEM_HEADER_SIZE) {
+ KDBUS_PART_FOREACH(item, &km->make, items) {
+ if (!KDBUS_PART_VALID(item, &km->make)) {
ret = -EINVAL;
goto exit;
}
@@ -250,18 +249,18 @@ int kdbus_ep_kmake_user(void __user *buf, struct kdbus_cmd_ep_kmake **kmake)
goto exit;
}
- if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) {
+ if (item->size < KDBUS_PART_HEADER_SIZE + 2) {
ret = -EINVAL;
goto exit;
}
- if (item->size > KDBUS_ITEM_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
+ if (item->size > KDBUS_PART_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
ret = -ENAMETOOLONG;
goto exit;
}
if (!kdbus_validate_nul(item->str,
- item->size - KDBUS_ITEM_HEADER_SIZE)) {
+ item->size - KDBUS_PART_HEADER_SIZE)) {
ret = -EINVAL;
goto exit;
}
@@ -275,9 +274,8 @@ int kdbus_ep_kmake_user(void __user *buf, struct kdbus_cmd_ep_kmake **kmake)
}
}
- /* expect correct padding and size values */
- if ((char *)item - ((char *)&km->make + km->make.size) >= 8)
- return -EINVAL;
+ if (!KDBUS_PART_END(item, &km->make))
+ return EINVAL;
if (!km->name) {
ret = -EBADMSG;
diff --git a/internal.h b/internal.h
index c19521b87b5..32313e8e619 100644
--- a/internal.h
+++ b/internal.h
@@ -42,22 +42,23 @@
#define KDBUS_ALIGN8(s) ALIGN((s), 8)
#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8))
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (s))
-#define KDBUS_ITEM_NEXT(item) \
- (struct kdbus_item *)((u8 *)item + KDBUS_ALIGN8((item)->size))
-#define KDBUS_ITEM_FOREACH(item, head) \
- for (item = (head)->items; \
- (u8 *)(item) < (u8 *)(head) + (head)->size; \
- item = KDBUS_ITEM_NEXT(item))
-/* same iterator with more consistency checks, to be used with incoming data */
-#define KDBUS_ITEM_FOREACH_VALIDATE(item, head) \
- for (item = (head)->items; \
- (u8 *)(item) + KDBUS_ITEM_HEADER_SIZE <= (u8 *)(head) + (head)->size && \
- (u8 *)(item) + (item)->size <= (u8 *)(head) + (head)->size; \
- item = KDBUS_ITEM_NEXT(item))
+#define KDBUS_PART_HEADER_SIZE (2 * sizeof(__u64))
+#define KDBUS_PART_SIZE(s) KDBUS_ALIGN8(KDBUS_PART_HEADER_SIZE + (s))
+#define KDBUS_PART_NEXT(part) \
+ (typeof(part))(((u8 *)part) + KDBUS_ALIGN8((part)->size))
+#define KDBUS_PART_FOREACH(part, head, first) \
+ for (part = (head)->first; \
+ (u8 *)(part) < (u8 *)(head) + (head)->size; \
+ part = KDBUS_PART_NEXT(part))
+#define KDBUS_PART_VALID(part, head) \
+ ((part)->size > KDBUS_PART_HEADER_SIZE && \
+ (u8 *)(part) + (part)->size <= (u8 *)(head) + (head)->size)
+#define KDBUS_PART_END(part, head) \
+ ((u8 *)part >= ((u8 *)(head) + (head)->size) && \
+ (u8 *)part - ((u8 *)(head) + (head)->size) < 8)
#define KDBUS_MSG_HEADER_SIZE offsetof(struct kdbus_msg, items)
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8(KDBUS_PART_HEADER_SIZE + (s))
/* read 64bit .size from struct */
#define kdbus_size_get_user(_s, _b, _t) \
diff --git a/kdbus.h b/kdbus.h
index cc322f252b8..13f1ddc9a30 100644
--- a/kdbus.h
+++ b/kdbus.h
@@ -21,6 +21,18 @@
#endif
#define KDBUS_IOC_MAGIC 0x95
+#define KDBUS_SRC_ID_KERNEL (0)
+#define KDBUS_DST_ID_WELL_KNOWN_NAME (0)
+#define KDBUS_MATCH_SRC_ID_ANY (~0ULL)
+#define KDBUS_DST_ID_BROADCAST (~0ULL)
+
+/* Common first elements in a structure which are used to iterate over
+ * a list of elements. */
+#define KDBUS_PART_HEADER \
+ struct { \
+ __u64 size; \
+ __u64 type; \
+ }
/* Message sent from kernel to userspace, when the owner or starter of
* a well-known name changes */
@@ -60,10 +72,15 @@ struct kdbus_timestamp {
__u64 realtime_ns;
};
-#define KDBUS_SRC_ID_KERNEL (0)
-#define KDBUS_DST_ID_WELL_KNOWN_NAME (0)
-#define KDBUS_MATCH_SRC_ID_ANY (~0ULL)
-#define KDBUS_DST_ID_BROADCAST (~0ULL)
+struct kdbus_vec {
+ __u64 address;
+ __u64 size;
+};
+
+struct kdbus_memfd {
+ __u64 size;
+ int fd;
+};
/* Message Item Types */
enum {
@@ -100,16 +117,6 @@ enum {
KDBUS_MSG_REPLY_DEAD, /* dito */
};
-struct kdbus_vec {
- __u64 address;
- __u64 size;
-};
-
-struct kdbus_memfd {
- __u64 size;
- int fd;
-};
-
/**
* struct kdbus_item - chain of data blocks
*
@@ -117,8 +124,7 @@ struct kdbus_memfd {
* type: kdbus_item type of data
*/
struct kdbus_item {
- __u64 size;
- __u64 type;
+ KDBUS_PART_HEADER;
union {
/* inline data */
__u8 data[0];
@@ -200,23 +206,25 @@ enum {
KDBUS_POLICY_OWN = 1 << 0,
};
+struct kdbus_policy_access {
+ __u64 type; /* USER, GROUP, WORLD */
+ __u64 bits; /* RECV, SEND, OWN */
+ __u64 id; /* uid, gid, 0 */
+};
+
+//FIXME: convert access to access[]
struct kdbus_policy {
- __u64 size;
- __u64 type; /* NAME or ACCESS */
+ KDBUS_PART_HEADER;
union {
char name[0];
- struct {
- __u32 type; /* USER, GROUP, WORLD */
- __u32 bits; /* RECV, SEND, OWN */
- __u64 id; /* uid, gid, 0 */
- } access;
+ struct kdbus_policy_access access;
};
};
+/* A series of KDBUS_POLICY_NAME, plus one or more KDBUS_POLICY_ACCESS */
struct kdbus_cmd_policy {
__u64 size;
- __u8 data[0]; /* a series of KDBUS_POLICY_NAME plus one or
- * more KDBUS_POLICY_ACCESS each. */
+ struct kdbus_policy policies[0];
};
/* Flags for struct kdbus_cmd_hello */
@@ -332,10 +340,11 @@ enum {
KDBUS_NAME_IN_QUEUE = 1 << 16,
};
+/* We allow (de)regestration of names of other peers */
struct kdbus_cmd_name {
__u64 size;
- __u64 name_flags;
- __u64 id; /* We allow registration/deregestration of names of other peers */
+ __u64 flags;
+ __u64 id;
__u64 conn_flags;
char name[0];
};
@@ -394,7 +403,7 @@ struct kdbus_cmd_monitor {
* starter (via KDBUS_CMD_HELLO with KDBUS_CMD_HELLO_STARTER)
* ep owner (via KDBUS_CMD_EP_MAKE)
*/
-enum kdbus_cmd {
+enum {
/* kdbus control node commands: require unset state */
KDBUS_CMD_BUS_MAKE = _IOWR(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_bus_make),
KDBUS_CMD_NS_MAKE = _IOWR(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_ns_make),
diff --git a/match.c b/match.c
index 4ccec75daf2..1af37b7e3b3 100644
--- a/match.c
+++ b/match.c
@@ -316,12 +316,12 @@ int kdbus_match_db_add(struct kdbus_conn *conn, void __user *buf)
e->src_id = cmd_match->src_id;
e->cookie = cmd_match->cookie;
- KDBUS_ITEM_FOREACH_VALIDATE(item, cmd_match) {
+ KDBUS_PART_FOREACH(item, cmd_match, items) {
struct kdbus_match_db_entry_item *ei;
size_t size;
- if (item->size < sizeof(*item)) {
- ret = -EBADMSG;
+ if (!KDBUS_PART_VALID(item, cmd_match)) {
+ ret = -EINVAL;
break;
}
@@ -364,6 +364,9 @@ int kdbus_match_db_add(struct kdbus_conn *conn, void __user *buf)
list_add_tail(&ei->list_entry, &e->items_list);
}
+ if (!KDBUS_PART_END(item, cmd_match))
+ ret = -EINVAL;
+
if (ret >= 0) {
list_add_tail(&e->list_entry, &db->entries);
} else {
diff --git a/message.c b/message.c
index 823ac464e60..e09c8860e42 100644
--- a/message.c
+++ b/message.c
@@ -50,7 +50,7 @@ static void __maybe_unused kdbus_msg_dump(const struct kdbus_msg *msg)
(unsigned long long) msg->payload_type,
(unsigned long long) msg->timeout_ns);
- KDBUS_ITEM_FOREACH(item, msg) {
+ KDBUS_PART_FOREACH(item, msg, items) {
switch (item->type) {
case KDBUS_MSG_PAYLOAD_VEC:
pr_info("+KDBUS_MSG_PAYLOAD_VEC (%zu bytes) address=%p size=%zu\n",
@@ -104,9 +104,8 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
bool has_name = false;
bool has_bloom = false;
- KDBUS_ITEM_FOREACH_VALIDATE(item, msg) {
- /* empty items are invalid */
- if (item->size <= KDBUS_ITEM_HEADER_SIZE)
+ KDBUS_PART_FOREACH(item, msg, items) {
+ if (!KDBUS_PART_VALID(item, msg))
return -EINVAL;
if (++items_count > KDBUS_MSG_MAX_ITEMS)
@@ -114,7 +113,7 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
switch (item->type) {
case KDBUS_MSG_PAYLOAD_VEC:
- if (item->size != KDBUS_ITEM_HEADER_SIZE +
+ if (item->size != KDBUS_PART_HEADER_SIZE +
sizeof(struct kdbus_vec))
return -EINVAL;
@@ -130,7 +129,7 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
break;
case KDBUS_MSG_PAYLOAD_MEMFD:
- if (item->size != KDBUS_ITEM_HEADER_SIZE +
+ if (item->size != KDBUS_PART_HEADER_SIZE +
sizeof(struct kdbus_memfd))
return -EINVAL;
@@ -160,7 +159,7 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
return -ENOTUNIQ;
- n = (item->size - KDBUS_ITEM_HEADER_SIZE) / sizeof(int);
+ n = (item->size - KDBUS_PART_HEADER_SIZE) / sizeof(int);
if (n > KDBUS_MSG_MAX_FDS)
return -EMFILE;
@@ -180,11 +179,11 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
return -EBADMSG;
/* allow only bloom sizes of a multiple of 64bit */
- if (!KDBUS_IS_ALIGNED8(item->size - KDBUS_ITEM_HEADER_SIZE))
+ if (!KDBUS_IS_ALIGNED8(item->size - KDBUS_PART_HEADER_SIZE))
return -EFAULT;
/* do not allow mismatching bloom filter sizes */
- if (item->size - KDBUS_ITEM_HEADER_SIZE != conn->ep->bus->bloom_size)
+ if (item->size - KDBUS_PART_HEADER_SIZE != conn->ep->bus->bloom_size)
return -EDOM;
kmsg->bloom = item->data64;
@@ -197,7 +196,7 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
has_name = true;
/* enforce NUL-terminated strings */
- if (!kdbus_validate_nul(item->str, item->size - KDBUS_ITEM_HEADER_SIZE))
+ if (!kdbus_validate_nul(item->str, item->size - KDBUS_PART_HEADER_SIZE))
return -EINVAL;
if (!kdbus_name_is_valid(item->str))
@@ -211,8 +210,7 @@ static int kdbus_msg_scan_items(struct kdbus_conn *conn, struct kdbus_kmsg *kmsg
}
}
- /* validate correct padding and size values to match the overall size */
- if ((char *)item - ((char *)msg + msg->size) >= 8)
+ if (!KDBUS_PART_END(item, msg))
return -EINVAL;
/* name is needed if no ID is given */
@@ -371,7 +369,7 @@ static int kdbus_kmsg_append_data(struct kdbus_kmsg *kmsg, u64 type,
return PTR_ERR(item);
item->type = type;
- item->size = KDBUS_ITEM_HEADER_SIZE + len;
+ item->size = KDBUS_PART_HEADER_SIZE + len;
memcpy(item->str, buf, len);
return 0;
@@ -407,7 +405,7 @@ int kdbus_kmsg_append_src_names(struct kdbus_kmsg *kmsg,
}
item->type = KDBUS_MSG_SRC_NAMES;
- item->size = KDBUS_ITEM_HEADER_SIZE + strsize;
+ item->size = KDBUS_PART_HEADER_SIZE + strsize;
list_for_each_entry(name_entry, &conn->names_list, conn_entry) {
strcpy(item->data + pos, name_entry->name);
diff --git a/names.c b/names.c
index e432f8fb29d..8efe7df4dd1 100644
--- a/names.c
+++ b/names.c
@@ -298,7 +298,7 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg,
conn = new_conn;
}
- cmd_name->name_flags &= ~KDBUS_NAME_IN_QUEUE;
+ cmd_name->flags &= ~KDBUS_NAME_IN_QUEUE;
hash = kdbus_str_hash(cmd_name->name);
if (conn->ep->policy_db) {
@@ -313,10 +313,10 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg,
if (e) {
if (e->conn == conn) {
/* just update flags */
- e->flags = cmd_name->name_flags;
+ e->flags = cmd_name->flags;
} else {
ret = kdbus_name_handle_conflict(reg, conn, e,
- &cmd_name->name_flags);
+ &cmd_name->flags);
if (ret < 0)
goto exit_unlock;
}
@@ -339,7 +339,7 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg,
if (conn->flags & KDBUS_HELLO_STARTER)
e->starter = conn;
- e->flags = cmd_name->name_flags;
+ e->flags = cmd_name->flags;
INIT_LIST_HEAD(&e->queue_list);
INIT_LIST_HEAD(&e->conn_entry);
@@ -409,11 +409,6 @@ int kdbus_cmd_name_release(struct kdbus_name_registry *reg,
return ret;
}
-#define KDBUS_NAME_SIZE(s) \
- KDBUS_ALIGN8(sizeof(struct kdbus_cmd_name) + strlen(s) + 1)
-#define KDBUS_NAME_NEXT(n) \
- (struct kdbus_cmd_name *)((u8 *)n + KDBUS_ALIGN8(n->size))
-
int kdbus_cmd_name_list(struct kdbus_name_registry *reg,
struct kdbus_conn *conn,
void __user *buf)
@@ -432,7 +427,8 @@ int kdbus_cmd_name_list(struct kdbus_name_registry *reg,
size = sizeof(struct kdbus_cmd_names);
hash_for_each(reg->entries_hash, tmp, e, hentry)
- size += KDBUS_NAME_SIZE(e->name);
+ size += KDBUS_ALIGN8(sizeof(struct kdbus_cmd_name) +
+ strlen(e->name) + 1);
if (size > user_size) {
kdbus_size_set_user(&size, buf, struct kdbus_cmd_names);
@@ -452,10 +448,10 @@ int kdbus_cmd_name_list(struct kdbus_name_registry *reg,
hash_for_each(reg->entries_hash, tmp, e, hentry) {
cmd_name->size = sizeof(struct kdbus_cmd_name) +
strlen(e->name) + 1;
- cmd_name->name_flags = e->flags;
+ cmd_name->flags = e->flags;
cmd_name->id = e->conn->id;
strcpy(cmd_name->name, e->name);
- cmd_name = KDBUS_NAME_NEXT(cmd_name);
+ cmd_name = KDBUS_PART_NEXT(cmd_name);
}
if (copy_to_user(buf, cmd_names, size)) {
@@ -492,17 +488,17 @@ kdbus_name_fill_info_items(struct kdbus_conn *conn,
return -ENOBUFS;
#ifdef CONFIG_AUDITSYSCALL
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(conn->audit_ids);
+ item->size = KDBUS_PART_HEADER_SIZE + sizeof(conn->audit_ids);
item->type = KDBUS_NAME_INFO_ITEM_AUDIT;
memcpy(item->data, conn->audit_ids, sizeof(conn->audit_ids));
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
#endif
#ifdef CONFIG_SECURITY
- item->size = KDBUS_ITEM_HEADER_SIZE + conn->sec_label_len + 1;
+ item->size = KDBUS_PART_HEADER_SIZE + conn->sec_label_len + 1;
item->type = KDBUS_NAME_INFO_ITEM_SECLABEL;
memcpy(item->data, conn->sec_label, conn->sec_label_len);
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
#endif
return ret;
@@ -538,11 +534,21 @@ int kdbus_cmd_name_query(struct kdbus_name_registry *reg,
owner_conn = kdbus_bus_find_conn_by_id(conn->ep->bus,
cmd_name_info->id);
if (!owner_conn)
- return -ENOENT;
+ return -ENXIO;
} else {
- KDBUS_ITEM_FOREACH_VALIDATE(info_item, cmd_name_info)
+ KDBUS_PART_FOREACH(info_item, cmd_name_info, items) {
+ if (!KDBUS_PART_VALID(info_item, cmd_name_info))
+ return -EINVAL;
+
+ if (name)
+ return -EBADMSG;
+
if (info_item->type == KDBUS_NAME_INFO_ITEM_NAME)
name = info_item->data;
+ }
+
+ if (!KDBUS_PART_END(info_item, cmd_name_info))
+ return -EINVAL;
if (!name)
return -EINVAL;
diff --git a/namespace.c b/namespace.c
index cf6548541fa..d39f95b30c9 100644
--- a/namespace.c
+++ b/namespace.c
@@ -256,9 +256,8 @@ int kdbus_ns_kmake_user(void __user *buf, struct kdbus_cmd_ns_kmake **kmake)
goto exit;
}
- KDBUS_ITEM_FOREACH_VALIDATE(item, &km->make) {
- /* empty items are invalid */
- if (item->size <= KDBUS_ITEM_HEADER_SIZE) {
+ KDBUS_PART_FOREACH(item, &km->make, items) {
+ if (!KDBUS_PART_VALID(item, &km->make)) {
ret = -EINVAL;
goto exit;
}
@@ -270,18 +269,18 @@ int kdbus_ns_kmake_user(void __user *buf, struct kdbus_cmd_ns_kmake **kmake)
goto exit;
}
- if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) {
+ if (item->size < KDBUS_PART_HEADER_SIZE + 2) {
ret = -EINVAL;
goto exit;
}
- if (item->size > KDBUS_ITEM_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
+ if (item->size > KDBUS_PART_HEADER_SIZE + KDBUS_MAKE_MAX_LEN + 1) {
ret = -ENAMETOOLONG;
goto exit;
}
if (!kdbus_validate_nul(item->str,
- item->size - KDBUS_ITEM_HEADER_SIZE)) {
+ item->size - KDBUS_PART_HEADER_SIZE)) {
ret = -EINVAL;
goto exit;
}
@@ -295,9 +294,8 @@ int kdbus_ns_kmake_user(void __user *buf, struct kdbus_cmd_ns_kmake **kmake)
}
}
- /* expect correct padding and size values */
- if ((char *)item - ((char *)&km->make + km->make.size) >= 8)
- return -EINVAL;
+ if (!KDBUS_PART_END(item, &km->make))
+ return EINVAL;
if (!km->name) {
ret = -EBADMSG;
diff --git a/policy.c b/policy.c
index 97ea48cf221..e1aacda02d0 100644
--- a/policy.c
+++ b/policy.c
@@ -226,7 +226,7 @@ static int __kdbus_policy_db_check_send_access(struct kdbus_policy_db *db,
}
}
- return -EPERM;
+ return 0;
}
static struct kdbus_policy_db_cache_entry *
@@ -371,13 +371,13 @@ static int kdbus_policy_db_parse(struct kdbus_policy_db *db,
const struct kdbus_cmd_policy *cmd,
u64 size)
{
- struct kdbus_policy *pol;
+ const struct kdbus_policy *pol;
struct kdbus_policy_db_entry *current_entry = NULL;
- size -= offsetof(struct kdbus_cmd_policy, data);
- pol = (struct kdbus_policy *) cmd->data;
+ KDBUS_PART_FOREACH(pol, cmd, policies) {
+ if (!KDBUS_PART_VALID(pol, cmd))
+ return -EINVAL;
- while (size > 0) {
switch (pol->type) {
case KDBUS_POLICY_NAME: {
struct kdbus_policy_db_entry *e;
@@ -398,6 +398,7 @@ static int kdbus_policy_db_parse(struct kdbus_policy_db *db,
current_entry = e;
break;
}
+
case KDBUS_POLICY_ACCESS: {
struct kdbus_policy_db_entry_access *a;
@@ -416,17 +417,17 @@ static int kdbus_policy_db_parse(struct kdbus_policy_db *db,
mutex_lock(&db->entries_lock);
list_add_tail(&a->list, &current_entry->access_list);
mutex_unlock(&db->entries_lock);
-
break;
}
+
default:
return -EINVAL;
}
-
- size -= pol->size;
- pol = (struct kdbus_policy *) ((u8 *) pol + pol->size);
}
+ if (!KDBUS_PART_END(pol, cmd))
+ return -EINVAL;
+
return 0;
}
diff --git a/test/kdbus-util.c b/test/kdbus-util.c
index c541676b68c..3cc69cf21ee 100644
--- a/test/kdbus-util.c
+++ b/test/kdbus-util.c
@@ -57,7 +57,7 @@ struct conn *connect_to_bus(const char *path)
return NULL;
}
h.v_type = KDBUS_HELLO_POOL;
- h.v_size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
+ h.v_size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
h.vec.address = (uint64_t)buf;
h.vec.size = 16 * 1024 * 1024;
@@ -71,7 +71,7 @@ struct conn *connect_to_bus(const char *path)
KDBUS_HELLO_ATTACH_AUDIT;
h.hello.size = sizeof(struct kdbus_cmd_hello) +
- KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
+ KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
ret = ioctl(fd, KDBUS_CMD_HELLO, &h.hello);
if (ret) {
@@ -104,34 +104,36 @@ int msg_send(const struct conn *conn,
int memfd;
int ret;
- ret = ioctl(conn->fd, KDBUS_CMD_MEMFD_NEW, &memfd);
- if (ret < 0) {
- fprintf(stderr, "KDBUS_CMD_MEMFD_NEW failed: %m\n");
- return EXIT_FAILURE;
- }
-
- if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
- fprintf(stderr, "writing to memfd failed: %m\n");
- return EXIT_FAILURE;
- }
-
- ret = ioctl(memfd, KDBUS_CMD_MEMFD_SEAL_SET, true);
- if (ret < 0) {
- fprintf(stderr, "memfd sealing failed: %m\n");
- return EXIT_FAILURE;
- }
-
size = sizeof(struct kdbus_msg);
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
if (dst_id == KDBUS_DST_ID_BROADCAST)
- size += KDBUS_ITEM_HEADER_SIZE + 64;
+ size += KDBUS_PART_HEADER_SIZE + 64;
+ else {
+ ret = ioctl(conn->fd, KDBUS_CMD_MEMFD_NEW, &memfd);
+ if (ret < 0) {
+ fprintf(stderr, "KDBUS_CMD_MEMFD_NEW failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
+ fprintf(stderr, "writing to memfd failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ ret = ioctl(memfd, KDBUS_CMD_MEMFD_SEAL_SET, true);
+ if (ret < 0) {
+ fprintf(stderr, "memfd sealing failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
+ }
if (name)
- size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
+ size += KDBUS_ITEM_SIZE(strlen(name) + 1);
msg = malloc(size);
if (!msg) {
@@ -150,40 +152,40 @@ int msg_send(const struct conn *conn,
if (name) {
item->type = KDBUS_MSG_DST_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
+ item->size = KDBUS_PART_HEADER_SIZE + strlen(name) + 1;
strcpy(item->str, name);
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
}
item->type = KDBUS_MSG_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
+ item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
item->vec.address = (uint64_t)&ref1;
item->vec.size = sizeof(ref1);
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
/* data padding for ref1 */
item->type = KDBUS_MSG_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
+ item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
item->vec.address = (uint64_t)NULL;
item->vec.size = KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1);
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
item->type = KDBUS_MSG_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
+ item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_vec);
item->vec.address = (uint64_t)&ref2;
item->vec.size = sizeof(ref2);
- item = KDBUS_ITEM_NEXT(item);
-
- item->type = KDBUS_MSG_PAYLOAD_MEMFD;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd);
- item->memfd.size = 16;
- item->memfd.fd = memfd;
- item = KDBUS_ITEM_NEXT(item);
+ item = KDBUS_PART_NEXT(item);
if (dst_id == KDBUS_DST_ID_BROADCAST) {
item->type = KDBUS_MSG_BLOOM;
- item->size = KDBUS_ITEM_HEADER_SIZE + 64;
- item = KDBUS_ITEM_NEXT(item);
+ item->size = KDBUS_PART_HEADER_SIZE + 64;
+ item = KDBUS_PART_NEXT(item);
+ } else {
+ item->type = KDBUS_MSG_PAYLOAD_MEMFD;
+ item->size = KDBUS_PART_HEADER_SIZE + sizeof(struct kdbus_memfd);
+ item->memfd.size = 16;
+ item->memfd.fd = memfd;
+ item = KDBUS_PART_NEXT(item);
}
ret = ioctl(conn->fd, KDBUS_CMD_MSG_SEND, msg);
@@ -219,8 +221,8 @@ void msg_dump(struct kdbus_msg *msg)
msg_id(msg->src_id, buf), msg_id(msg->dst_id, buf),
(unsigned long long) msg->cookie, (unsigned long long) msg->timeout_ns);
- KDBUS_ITEM_FOREACH(item, msg) {
- if (item->size <= KDBUS_ITEM_HEADER_SIZE) {
+ KDBUS_PART_FOREACH(item, msg, items) {
+ if (item->size <= KDBUS_PART_HEADER_SIZE) {
printf(" +%s (%llu bytes) invalid data record\n", enum_MSG(item->type), item->size);
break;
}
@@ -279,7 +281,7 @@ void msg_dump(struct kdbus_msg *msg)
case KDBUS_MSG_SRC_CMDLINE:
case KDBUS_MSG_SRC_NAMES: {
- size_t size = item->size - KDBUS_ITEM_HEADER_SIZE;
+ size_t size = item->size - KDBUS_PART_HEADER_SIZE;
char *str = item->str;
int count = 0;
@@ -309,10 +311,10 @@ void msg_dump(struct kdbus_msg *msg)
printf(" +%s (%llu bytes) len=%llu bytes)\n",
enum_MSG(item->type), item->size,
- (unsigned long long)item->size - KDBUS_ITEM_HEADER_SIZE);
+ (unsigned long long)item->size - KDBUS_PART_HEADER_SIZE);
cap = item->data32;
- n = (item->size - KDBUS_ITEM_HEADER_SIZE) / 4 / sizeof(uint32_t);
+ n = (item->size - KDBUS_PART_HEADER_SIZE) / 4 / sizeof(uint32_t);
printf(" CapInh=");
for (i = 0; i < n; i++)
@@ -463,7 +465,7 @@ int name_list(struct conn *conn)
}
printf("REGISTRY:\n");
- KDBUS_NAME_FOREACH(name, names)
+ KDBUS_PART_FOREACH(name, names, names)
printf(" '%s' is acquired by id %llx\n", name->name, name->id);
printf("\n");
@@ -505,7 +507,8 @@ void append_policy(struct kdbus_cmd_policy *cmd_policy, struct kdbus_policy *pol
return;
memcpy(dst, policy, policy->size);
- cmd_policy->size += policy->size;
+ cmd_policy->size += KDBUS_ALIGN8(policy->size);
+ free(policy);
}
struct kdbus_policy *make_policy_name(const char *name)
@@ -517,7 +520,6 @@ struct kdbus_policy *make_policy_name(const char *name)
p = malloc(size);
if (!p)
return NULL;
-
memset(p, 0, size);
p->size = size;
p->type = KDBUS_POLICY_NAME;
@@ -554,9 +556,10 @@ int upload_policy(int fd)
int size = 0xffff;
cmd_policy = (struct kdbus_cmd_policy *) alloca(size);
+ memset(cmd_policy, 0, size);
- policy = (struct kdbus_policy *) cmd_policy->data;
- cmd_policy->size = offsetof(struct kdbus_cmd_policy, data);
+ policy = (struct kdbus_policy *) cmd_policy->policies;
+ cmd_policy->size = offsetof(struct kdbus_cmd_policy, policies);
policy = make_policy_name("foo.bar.baz");
append_policy(cmd_policy, policy, size);
@@ -576,5 +579,3 @@ int upload_policy(int fd)
return ret;
}
-
-
diff --git a/test/kdbus-util.h b/test/kdbus-util.h
index 34776262c48..3f65154b5c9 100644
--- a/test/kdbus-util.h
+++ b/test/kdbus-util.h
@@ -16,24 +16,16 @@
#define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr))
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
-#define KDBUS_ITEM_NEXT(item) \
- (struct kdbus_item *)(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
-#define KDBUS_ITEM_FOREACH(item, head) \
- for (item = (head)->items; \
- (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
- item = KDBUS_ITEM_NEXT(item))
-#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-
-#define KDBUS_NAME_SIZE(s) \
- KDBUS_ALIGN8(sizeof(struct kdbus_cmd_name) + strlen(s) + 1)
-#define KDBUS_NAME_NEXT(n) \
- (struct kdbus_cmd_name *)((char *)n + KDBUS_ALIGN8(n->size))
-#define KDBUS_NAME_FOREACH(name, names) \
- for (name = names->names; \
- (char *)name < (char *)names + name->size; \
- name = KDBUS_NAME_NEXT(name))
+#define KDBUS_PART_HEADER_SIZE offsetof(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_PART_HEADER_SIZE)
+
+#define KDBUS_PART_NEXT(part) \
+ (typeof(part))(((uint8_t *)part) + KDBUS_ALIGN8((part)->size))
+#define KDBUS_PART_FOREACH(part, head, first) \
+ for (part = (head)->first; \
+ (uint8_t *)(part) < (uint8_t *)(head) + (head)->size; \
+ part = KDBUS_PART_NEXT(part))
struct conn {
int fd;
diff --git a/test/test-kdbus-daemon.c b/test/test-kdbus-daemon.c
index b7caec4c870..6b09e9e1398 100644
--- a/test/test-kdbus-daemon.c
+++ b/test/test-kdbus-daemon.c
@@ -49,11 +49,11 @@ int main(int argc, char *argv[])
bus_make.cgroup_id = cgroup_systemd();
bus_make.c_type = KDBUS_MAKE_CGROUP;
- bus_make.c_size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
+ bus_make.c_size = KDBUS_PART_HEADER_SIZE + sizeof(uint64_t);
snprintf(bus_make.name, sizeof(bus_make.name), "%u-testbus", getuid());
bus_make.n_type = KDBUS_MAKE_NAME;
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.n_size = KDBUS_PART_HEADER_SIZE + strlen(bus_make.name) + 1;
bus_make.head.size = sizeof(struct kdbus_cmd_bus_make) +
bus_make.c_size +
diff --git a/test/test-kdbus.c b/test/test-kdbus.c
index ec0d2af29d3..e1055a5f1d8 100644
--- a/test/test-kdbus.c
+++ b/test/test-kdbus.c
@@ -61,15 +61,15 @@ int main(int argc, char *argv[])
}
memset(&bus_make, 0, sizeof(bus_make));
- bus_make.head.bloom_size = 8;
+ bus_make.head.bloom_size = 64;
bus_make.cgroup_id = cgroup_systemd();
bus_make.c_type = KDBUS_MAKE_CGROUP;
- bus_make.c_size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
+ bus_make.c_size = KDBUS_PART_HEADER_SIZE + sizeof(uint64_t);
snprintf(bus_make.name, sizeof(bus_make.name), "%u-testbus", getuid());
bus_make.n_type = KDBUS_MAKE_NAME;
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
+ bus_make.n_size = KDBUS_PART_HEADER_SIZE + strlen(bus_make.name) + 1;
bus_make.head.size = sizeof(struct kdbus_cmd_bus_make) +
bus_make.c_size +
@@ -100,7 +100,7 @@ int main(int argc, char *argv[])
add_match_empty(conn_b->fd);
cookie = 0;
- msg_send(conn_b, "foo.bar.baz", 0xc0000000 | cookie, KDBUS_DST_ID_BROADCAST);
+ msg_send(conn_b, NULL, 0xc0000000 | cookie, KDBUS_DST_ID_BROADCAST);
fds[0].fd = conn_a->fd;
fds[1].fd = conn_b->fd;