1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

bus: fake client side creds in the proxy to the caller's creds

This commit is contained in:
Lennart Poettering 2013-12-24 15:03:32 +01:00
parent 515c883021
commit 8a0e0ed9dd
4 changed files with 109 additions and 14 deletions

View File

@ -358,6 +358,40 @@ static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hell
return 1;
}
static int getpeersec(int fd, char **ret) {
socklen_t n = 64;
char *s;
int r;
assert(fd >= 0);
assert(ret);
s = new0(char, n);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
if (errno != ERANGE)
return r;
s = new0(char, n);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
return r;
}
}
*ret = s;
return 0;
}
int main(int argc, char *argv[]) {
_cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
@ -365,6 +399,8 @@ int main(int argc, char *argv[]) {
int r, in_fd, out_fd;
bool got_hello = false;
bool is_unix;
struct ucred ucred = {};
_cleanup_free_ char *peersec = NULL;
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_parse_environment();
@ -390,6 +426,20 @@ int main(int argc, char *argv[]) {
sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
if (is_unix) {
socklen_t l = sizeof(ucred);
r = getsockopt(in_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l);
if (r < 0) {
r = -errno;
goto finish;
}
assert(l == sizeof(ucred));
getpeersec(in_fd, &peersec);
}
r = sd_bus_new(&a);
if (r < 0) {
log_error("Failed to allocate bus: %s", strerror(-r));
@ -408,6 +458,18 @@ int main(int argc, char *argv[]) {
goto finish;
}
if (ucred.pid > 0) {
a->fake_creds.pid = ucred.pid;
a->fake_creds.uid = ucred.uid;
a->fake_creds.gid = ucred.gid;
a->fake_creds_valid = true;
}
if (peersec) {
a->fake_label = peersec;
peersec = NULL;
}
r = sd_bus_start(a);
if (r < 0) {
log_error("Failed to start bus client: %s", strerror(-r));

View File

@ -36,6 +36,7 @@
#include "bus-error.h"
#include "bus-match.h"
#include "bus-kernel.h"
#include "kdbus.h"
struct reply_callback {
sd_bus_message_handler_t callback;
@ -161,6 +162,7 @@ struct sd_bus {
bool filter_callbacks_modified:1;
bool nodes_modified:1;
bool trusted:1;
bool fake_creds_valid:1;
int use_memfd;
@ -259,6 +261,9 @@ struct sd_bus {
sd_bus **default_bus_ptr;
pid_t tid;
struct kdbus_creds fake_creds;
char *fake_label;
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))

View File

@ -317,7 +317,9 @@ fail:
}
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, sz;
int r;
assert(b);
@ -327,13 +329,38 @@ int bus_kernel_take_fd(sd_bus *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));
r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
if (b->fake_creds_valid)
sz += ALIGN8(offsetof(struct kdbus_item, 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;
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;
@ -347,26 +374,26 @@ int bus_kernel_take_fd(sd_bus *b) {
/* 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);
}

View File

@ -141,6 +141,7 @@ static void bus_free(sd_bus *b) {
free(b->address);
free(b->kernel);
free(b->machine);
free(b->fake_label);
free(b->exec_path);
strv_free(b->exec_argv);