diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-12-13 22:02:47 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-12-14 05:10:25 +0100 |
commit | bc9fd78c7bfc39881e19457e476393635f8b0442 (patch) | |
tree | 3c4dc6461460a2b4094516eb35424d36f52f455a /src/shared/util.c | |
parent | 3fa5dd6de798e17d93531bc900b8e2dc587c38f3 (diff) |
bus: when connecting to a container's kdbus instance, enter namespace first
Previously we'd open the connection in the originating namespace, which
meant most peers of the bus would not be able to make sense of the
PID/UID/... identity of us since we didn't exist in the namespace they
run in. However they require this identity for privilege decisions,
hence disallowing access to anything from the host.
Instead, when connecting to a container, create a temporary subprocess,
make it join the container's namespace and then connect from there to
the kdbus instance. This is similar to how we do it for socket
conections already.
THis also unifies the namespacing code used by machinectl and the bus
APIs.
Diffstat (limited to 'src/shared/util.c')
-rw-r--r-- | src/shared/util.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index 1c35edfbb1..66276aa54e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5951,3 +5951,76 @@ int proc_cmdline(char **ret) { return 1; } + +int container_get_leader(const char *machine, pid_t *pid) { + _cleanup_free_ char *s = NULL, *class = NULL; + const char *p; + pid_t leader; + int r; + + assert(machine); + assert(pid); + + p = strappenda("/run/systemd/machines/", machine); + r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL); + if (r == -ENOENT) + return -EHOSTDOWN; + if (r < 0) + return r; + if (!s) + return -EIO; + + if (!streq_ptr(class, "container")) + return -EIO; + + r = parse_pid(s, &leader); + if (r < 0) + return r; + if (leader <= 1) + return -EIO; + + *pid = leader; + return 0; +} + +int namespace_open(pid_t pid, int *namespace_fd, int *root_fd) { + _cleanup_close_ int nsfd = -1; + const char *ns, *root; + int rfd; + + assert(pid >= 0); + assert(namespace_fd); + assert(root_fd); + + ns = procfs_file_alloca(pid, "ns/mnt"); + nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (nsfd < 0) + return -errno; + + root = procfs_file_alloca(pid, "root"); + rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (rfd < 0) + return -errno; + + *namespace_fd = nsfd; + *root_fd = rfd; + nsfd = -1; + + return 0; +} + +int namespace_enter(int namespace_fd, int root_fd) { + assert(namespace_fd >= 0); + assert(root_fd >= 0); + + if (setns(namespace_fd, CLONE_NEWNS) < 0) + return -errno; + + if (fchdir(root_fd) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + + return 0; +} |