#include "bus-kernel.h"
#include "bus-bloom.h"
#include "bus-util.h"
+#include "cgroup-util.h"
#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
e = stpcpy(buf, "arg");
if (i < 10)
- *(e++) = '0' + i;
+ *(e++) = '0' + (char) i;
else {
- *(e++) = '0' + (i / 10);
- *(e++) = '0' + (i % 10);
+ *(e++) = '0' + (char) (i / 10);
+ *(e++) = '0' + (char) (i % 10);
}
*e = 0;
m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
m->kdbus->cookie = m->header->serial;
- m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
+ if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
+ m->kdbus->cookie_reply = m->reply_cookie;
+ else
+ m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
d = m->kdbus->items;
}
int bus_kernel_take_fd(sd_bus *b) {
- struct kdbus_cmd_hello hello;
+ struct kdbus_cmd_hello *hello;
+ struct kdbus_item *item;
+ size_t l = 0, sz;
int r;
assert(b);
b->use_memfd = 1;
- zero(hello);
- hello.size = sizeof(hello);
- hello.conn_flags = b->hello_flags;
- hello.attach_flags = b->attach_flags;
- hello.pool_size = KDBUS_POOL_SIZE;
+ sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items));
+
+ if (b->fake_creds_valid)
+ sz += ALIGN8(offsetof(struct kdbus_item, creds)) + sizeof(struct kdbus_creds);
+
+ if (b->fake_label) {
+ l = strlen(b->fake_label);
+ sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
+ }
+
+ hello = alloca0(sz);
+ hello->size = sz;
+ hello->conn_flags = b->hello_flags;
+ hello->attach_flags = b->attach_flags;
+ hello->pool_size = KDBUS_POOL_SIZE;
+
+ item = hello->items;
- r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
+ if (b->fake_creds_valid) {
+ item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
+ item->type = KDBUS_ITEM_CREDS;
+ item->creds = b->fake_creds;
+
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
+ if (b->fake_label) {
+ item->size = offsetof(struct kdbus_item, str) + l + 1;
+ memcpy(item->str, b->fake_label, l+1);
+ }
+
+ r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
if (r < 0)
return -errno;
/* The higher 32bit of both flags fields are considered
* 'incompatible flags'. Refuse them all for now. */
- if (hello.bus_flags > 0xFFFFFFFFULL ||
- hello.conn_flags > 0xFFFFFFFFULL)
+ if (hello->bus_flags > 0xFFFFFFFFULL ||
+ hello->conn_flags > 0xFFFFFFFFULL)
return -ENOTSUP;
- if (hello.bloom_size != BLOOM_SIZE)
+ if (hello->bloom_size != BLOOM_SIZE)
return -ENOTSUP;
- if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
+ if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
return -ENOMEM;
- b->unique_id = hello.id;
+ b->unique_id = hello->id;
b->is_kernel = true;
b->bus_client = true;
- b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
+ b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD);
b->message_version = 2;
b->message_endian = BUS_NATIVE_ENDIAN;
/* the kernel told us the UUID of the underlying bus */
- memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
+ memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
return bus_start_running(b);
}
r = bus_message_new_synthetic_error(
bus,
- BUS_MESSAGE_SERIAL(m),
+ BUS_MESSAGE_COOKIE(m),
&error,
&reply);
if (r < 0)
return r;
+ /* The well-known names list is different from the other
+ credentials. If we asked for it, but nothing is there, this
+ means that the list of well-known names is simply empty, not
+ that we lack any data */
+
+ m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
+
KDBUS_ITEM_FOREACH(d, k, items) {
size_t l;
}
case KDBUS_ITEM_CREDS:
- m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
- m->creds.uid = d->creds.uid;
- m->creds.gid = d->creds.gid;
- m->creds.pid = d->creds.pid;
- m->creds.tid = d->creds.tid;
- m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask;
+ /* UID/GID/PID are always valid */
+ m->creds.uid = (uid_t) d->creds.uid;
+ m->creds.gid = (gid_t) d->creds.gid;
+ m->creds.pid = (pid_t) d->creds.pid;
+ m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID) & bus->creds_mask;
+
+ /* The PID starttime/TID might be missing
+ * however, when the data is faked by some
+ * data bus proxy and it lacks that
+ * information about the real client since
+ * SO_PEERCRED is used for that */
+
+ if (d->creds.starttime > 0) {
+ m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
+ m->creds.mask |= SD_BUS_CREDS_PID_STARTTIME & bus->creds_mask;
+ }
+
+ if (d->creds.tid > 0) {
+ m->creds.tid = (pid_t) d->creds.tid;
+ m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
+ }
break;
case KDBUS_ITEM_TIMESTAMP:
case KDBUS_ITEM_CGROUP:
m->creds.cgroup = d->str;
m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
+
+ if (!bus->cgroup_root) {
+ r = cg_get_root_path(&bus->cgroup_root);
+ if (r < 0)
+ goto fail;
+ }
+
+ m->creds.cgroup_root = bus->cgroup_root;
+
break;
case KDBUS_ITEM_AUDIT:
- m->creds.audit_session_id = d->audit.sessionid;
- m->creds.audit_login_uid = d->audit.loginuid;
+ m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
+ m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
break;
break;
case KDBUS_ITEM_DST_NAME:
+ if (!service_name_is_valid(d->str))
+ return -EBADMSG;
+
destination = d->str;
break;
case KDBUS_ITEM_NAME:
+ if (!service_name_is_valid(d->name.name))
+ return -EBADMSG;
+
r = strv_extend(&m->creds.well_known_names, d->name.name);
if (r < 0)
goto fail;
- m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask;
break;
case KDBUS_ITEM_FDS:
/* Override information from the user header with data from the kernel */
if (k->src_id == KDBUS_SRC_ID_KERNEL)
- m->sender = "org.freedesktop.DBus";
+ m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
else {
snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
m->sender = m->creds.unique_name = m->sender_buffer;
- m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask;
}
- if (!m->destination) {
- if (destination)
- m->destination = destination;
- else if (k->dst_id != KDBUS_DST_ID_NAME &&
- k->dst_id != KDBUS_DST_ID_BROADCAST) {
- snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
- m->destination = m->destination_buffer;
- }
+ if (destination)
+ m->destination = destination;
+ else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
+ m->destination = NULL;
+ else if (k->dst_id == KDBUS_DST_ID_NAME)
+ m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
+ else {
+ snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
+ m->destination = m->destination_buffer;
}
/* We take possession of the kmsg struct now */
return 0;
}
-int bus_kernel_create_bus(const char *name, char **s) {
+int bus_kernel_create_bus(const char *name, bool world, char **s) {
struct kdbus_cmd_make *make;
struct kdbus_item *n;
int fd;
n->type = KDBUS_ITEM_MAKE_NAME;
make->size += ALIGN8(n->size);
- make->flags = KDBUS_MAKE_POLICY_OPEN;
+ make->flags = KDBUS_MAKE_POLICY_OPEN | (world ? KDBUS_MAKE_ACCESS_WORLD : 0);
if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
close_nointr_nofail(fd);