return ret;
}
+static int kdbus_handle_hello(struct kdbus_handle *handle,
+ struct kdbus_cmd_hello *hello)
+{
+ const struct kdbus_item *item;
+ const struct kdbus_creds *creds = NULL;
+ const char *seclabel = NULL;
+
+ if (!kdbus_check_flags(hello->conn_flags))
+ return -ENOTSUPP;
+
+ if (hello->pool_size == 0 ||
+ !IS_ALIGNED(hello->pool_size, PAGE_SIZE))
+ return -EFAULT;
+
+ KDBUS_ITEM_FOREACH(item, hello, items) {
+ if (!KDBUS_ITEM_VALID(item, hello))
+ return -EFAULT;
+
+ switch (item->type) {
+ case KDBUS_ITEM_CREDS:
+ if (!capable(CAP_IPC_OWNER))
+ return -EPERM;
+
+ if (item->size !=
+ KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)))
+ return -EINVAL;
+
+ creds = &item->creds;
+ break;
+
+ case KDBUS_ITEM_SECLABEL:
+ if (!capable(CAP_IPC_OWNER))
+ return -EPERM;
+
+ if (!kdbus_validate_nul(item->str,
+ item->size - KDBUS_ITEM_HEADER_SIZE))
+ return -EINVAL;
+
+ seclabel = item->data;
+ break;
+ }
+ }
+
+ /* privileged processes can impersonate somebody else */
+ if (creds || seclabel) {
+ int ret;
+
+ /*
+ * Replace the connection's metadata gathered at open()
+ * time, with the information provided with the HELLO call.
+ */
+ kdbus_meta_free(&handle->meta);
+
+ ret = kdbus_meta_append_data(&handle->meta,
+ KDBUS_ITEM_SECLABEL, item->data,
+ item->size - KDBUS_ITEM_HEADER_SIZE);
+ if (ret < 0)
+ return ret;
+
+ ret = kdbus_meta_append_data(&handle->meta,
+ KDBUS_ITEM_CREDS, &item->creds,
+ item->size - KDBUS_ITEM_HEADER_SIZE);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!KDBUS_ITEM_END(item, hello))
+ return -EINVAL;
+
+ return kdbus_conn_new(handle->ep, hello, &handle->meta,
+ &handle->conn);
+}
+
/* kdbus endpoint make commands */
static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
void __user *buf)
}
hello = v;
- if (!kdbus_check_flags(hello->conn_flags)) {
- ret = -ENOTSUPP;
- break;
- }
-
- if (hello->pool_size == 0 ||
- !IS_ALIGNED(hello->pool_size, PAGE_SIZE)) {
- ret = -EFAULT;
- break;
- }
-
- ret = kdbus_conn_new(handle->ep, hello, &handle->meta,
- &handle->conn);
+ ret = kdbus_handle_hello(handle, hello);
if (ret < 0)
break;
* struct kdbus_cmd_match - struct to add or remove matches
* @size: The total size of the struct
* @owner_id: Privileged users may (de)register matches on behalf
- * of other peers. In other cases, set to 0.
+ * of other peers
* @cookie: Userspace supplied cookie. When removing, the cookie
- * identifies the match to remove.
+ * identifies the match to remove
* @items: A list of items for additional information
*
* This structure is used with the KDBUS_CMD_ADD_MATCH and
return item;
}
-static int kdbus_meta_append_data(struct kdbus_meta *meta, u64 type,
+/**
+ * kdbus_meta_append_data() - append given raw data to metadata object
+ * @meta: Metadata object
+ * @type: KDBUS_ITEM_* type
+ * @data: pointer to data to copy from
+ * @len: number of bytes to copy
+ *
+ * Returns: 0 on success, negative errno on failure.
+ */
+int kdbus_meta_append_data(struct kdbus_meta *meta, u64 type,
const void *buf, size_t len)
{
struct kdbus_item *item;