chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
515c883
)
bus: fake client side creds in the proxy to the caller's creds
author
Lennart Poettering
<lennart@poettering.net>
Tue, 24 Dec 2013 14:03:32 +0000
(15:03 +0100)
committer
Lennart Poettering
<lennart@poettering.net>
Tue, 24 Dec 2013 14:27:59 +0000
(15:27 +0100)
src/bus-proxyd/bus-proxyd.c
patch
|
blob
|
history
src/libsystemd-bus/bus-internal.h
patch
|
blob
|
history
src/libsystemd-bus/bus-kernel.c
patch
|
blob
|
history
src/libsystemd-bus/sd-bus.c
patch
|
blob
|
history
diff --git
a/src/bus-proxyd/bus-proxyd.c
b/src/bus-proxyd/bus-proxyd.c
index a425fd2facf764f281dcc1549c5cf83304304cb5..b87dffe0e8b77202d4858feda63e8f3b6858b63e 100644
(file)
--- a/
src/bus-proxyd/bus-proxyd.c
+++ b/
src/bus-proxyd/bus-proxyd.c
@@
-358,6
+358,40
@@
static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hell
return 1;
}
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;
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;
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();
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;
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));
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;
}
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));
r = sd_bus_start(a);
if (r < 0) {
log_error("Failed to start bus client: %s", strerror(-r));
diff --git
a/src/libsystemd-bus/bus-internal.h
b/src/libsystemd-bus/bus-internal.h
index 7af8c1e22d61cd96974ef2dbfbae434f0acefe31..673f30eb912e379ece4a4d597350a59441a3d102 100644
(file)
--- a/
src/libsystemd-bus/bus-internal.h
+++ b/
src/libsystemd-bus/bus-internal.h
@@
-36,6
+36,7
@@
#include "bus-error.h"
#include "bus-match.h"
#include "bus-kernel.h"
#include "bus-error.h"
#include "bus-match.h"
#include "bus-kernel.h"
+#include "kdbus.h"
struct reply_callback {
sd_bus_message_handler_t callback;
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 filter_callbacks_modified:1;
bool nodes_modified:1;
bool trusted:1;
+ bool fake_creds_valid:1;
int use_memfd;
int use_memfd;
@@
-259,6
+261,9
@@
struct sd_bus {
sd_bus **default_bus_ptr;
pid_t tid;
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))
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
diff --git
a/src/libsystemd-bus/bus-kernel.c
b/src/libsystemd-bus/bus-kernel.c
index e53bc51727481f9237af566f1bcd7738968b10b6..fb5266d44e5907da435286f37b69ff511b80a28c 100644
(file)
--- a/
src/libsystemd-bus/bus-kernel.c
+++ b/
src/libsystemd-bus/bus-kernel.c
@@
-317,7
+317,9
@@
fail:
}
int bus_kernel_take_fd(sd_bus *b) {
}
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);
int r;
assert(b);
@@
-327,13
+329,38
@@
int bus_kernel_take_fd(sd_bus *b) {
b->use_memfd = 1;
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));
+
+ 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;
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. */
/* 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;
return -ENOTSUP;
- if (hello
.
bloom_size != BLOOM_SIZE)
+ if (hello
->
bloom_size != BLOOM_SIZE)
return -ENOTSUP;
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;
return -ENOMEM;
- b->unique_id = hello
.
id;
+ b->unique_id = hello
->
id;
b->is_kernel = true;
b->bus_client = true;
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 */
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);
}
return bus_start_running(b);
}
diff --git
a/src/libsystemd-bus/sd-bus.c
b/src/libsystemd-bus/sd-bus.c
index 9dfb6e444215012dfe363660424d54d3179f6dbb..910a5f81361a5f3d65cec026f1086fa9610d22e1 100644
(file)
--- a/
src/libsystemd-bus/sd-bus.c
+++ b/
src/libsystemd-bus/sd-bus.c
@@
-141,6
+141,7
@@
static void bus_free(sd_bus *b) {
free(b->address);
free(b->kernel);
free(b->machine);
free(b->address);
free(b->kernel);
free(b->machine);
+ free(b->fake_label);
free(b->exec_path);
strv_free(b->exec_argv);
free(b->exec_path);
strv_free(b->exec_argv);