sd-bus: Make sure we can connect to user machines as well (#40698)
Don't unconditionally look into /run/systemd/machines. If we're a connected to a session bus, look at the machines for the current user instead.
This commit is contained in:
+87
-39
@@ -68,6 +68,11 @@ static int pidref_namespace_open_by_type_internal(const PidRef *pidref, Namespac
|
||||
|
||||
if (pidref->fd >= 0) {
|
||||
r = pidfd_get_namespace(pidref->fd, namespace_info[type].pidfd_get_ns_ioctl_cmd);
|
||||
if (r == -ENOPKG)
|
||||
return log_debug_errno(
|
||||
r,
|
||||
"Cannot open %s namespace for PID "PID_FMT" as the namespace type is not supported by the kernel",
|
||||
namespace_info[type].proc_name, pidref->pid);
|
||||
if (!ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return r;
|
||||
}
|
||||
@@ -83,10 +88,17 @@ static int pidref_namespace_open_by_type_internal(const PidRef *pidref, Namespac
|
||||
if (nsfd == -ENOENT) {
|
||||
r = proc_mounted();
|
||||
if (r == 0)
|
||||
return -ENOSYS; /* /proc/ is not available or not set up properly, we're most likely
|
||||
in some chroot environment. */
|
||||
/* /proc/ is not available or not set up properly, we're most likely in some chroot environment. */
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(ENOSYS),
|
||||
"Cannot open %s namespace for PID "PID_FMT" as /proc is not mounted",
|
||||
namespace_info[type].proc_name, pidref->pid);
|
||||
if (r > 0)
|
||||
return -ENOPKG; /* If /proc/ is definitely around then this means the namespace type is not supported */
|
||||
/* If /proc/ is definitely around then this means the namespace type is not supported */
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(ENOPKG),
|
||||
"Cannot open %s namespace for PID "PID_FMT" via /proc as the namespace type is not supported by the kernel",
|
||||
namespace_info[type].proc_name, pidref->pid);
|
||||
|
||||
/* can't determine? then propagate original error */
|
||||
}
|
||||
@@ -216,33 +228,39 @@ int namespace_open(
|
||||
return pidref_namespace_open(&pidref, ret_pidns_fd, ret_mntns_fd, ret_netns_fd, ret_userns_fd, ret_root_fd);
|
||||
}
|
||||
|
||||
static int namespace_enter_one_idempotent(int nsfd, NamespaceType type) {
|
||||
int r;
|
||||
|
||||
/* Join a namespace, but only if we're not part of it already. This is important if we don't necessarily
|
||||
* own the namespace in question, as kernel would unconditionally return EPERM otherwise. */
|
||||
|
||||
assert(nsfd >= 0);
|
||||
assert(type >= 0 && type < _NAMESPACE_TYPE_MAX);
|
||||
|
||||
r = is_our_namespace(nsfd, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
if (setns(nsfd, namespace_info[type].clone_flag) < 0)
|
||||
return -errno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
int r;
|
||||
|
||||
/* Block dlopen() now, to avoid us inadvertently loading shared library from another namespace */
|
||||
block_dlopen();
|
||||
|
||||
/* Join namespaces, but only if we're not part of them already. This is important if we don't
|
||||
* necessarily own the namespace in question, as kernel would unconditionally return EPERM otherwise. */
|
||||
|
||||
if (pidns_fd >= 0) {
|
||||
r = is_our_namespace(pidns_fd, NAMESPACE_PID);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
pidns_fd = -EBADF;
|
||||
}
|
||||
|
||||
if (mntns_fd >= 0) {
|
||||
r = is_our_namespace(mntns_fd, NAMESPACE_MOUNT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
mntns_fd = -EBADF;
|
||||
}
|
||||
|
||||
if (netns_fd >= 0) {
|
||||
r = is_our_namespace(netns_fd, NAMESPACE_NET);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
netns_fd = -EBADF;
|
||||
}
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
/* Can't setns to your own userns, since then you could escalate from non-root to root in
|
||||
* your own namespace, so check if namespaces are equal before attempting to enter. */
|
||||
@@ -275,23 +293,17 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0) {
|
||||
r = namespace_enter_one_idempotent(pidns_fd, NAMESPACE_PID);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (pidns_fd >= 0)
|
||||
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
||||
return -errno;
|
||||
|
||||
if (mntns_fd >= 0) {
|
||||
r = namespace_enter_one_idempotent(mntns_fd, NAMESPACE_MOUNT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (mntns_fd >= 0)
|
||||
if (setns(mntns_fd, CLONE_NEWNS) < 0)
|
||||
return -errno;
|
||||
|
||||
if (netns_fd >= 0) {
|
||||
r = namespace_enter_one_idempotent(netns_fd, NAMESPACE_NET);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (netns_fd >= 0)
|
||||
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (userns_fd >= 0 && have_cap_sys_admin)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
@@ -361,6 +373,42 @@ int is_our_namespace(int fd, NamespaceType type) {
|
||||
return fd_inode_same(fd, our_ns);
|
||||
}
|
||||
|
||||
int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
int r;
|
||||
|
||||
if (pidns_fd >= 0) {
|
||||
r = is_our_namespace(pidns_fd, NAMESPACE_PID);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (mntns_fd >= 0) {
|
||||
r = is_our_namespace(mntns_fd, NAMESPACE_MOUNT);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (netns_fd >= 0) {
|
||||
r = is_our_namespace(netns_fd, NAMESPACE_NET);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
r = is_our_namespace(userns_fd, NAMESPACE_USER);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (root_fd >= 0) {
|
||||
r = dir_fd_is_root(root_fd);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int namespace_is_init(NamespaceType type) {
|
||||
int r;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
||||
|
||||
int fd_is_namespace(int fd, NamespaceType type);
|
||||
int is_our_namespace(int fd, NamespaceType type);
|
||||
int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
int namespace_is_init(NamespaceType type);
|
||||
|
||||
|
||||
@@ -25,13 +25,11 @@
|
||||
#include "cgroup-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "env-file.h"
|
||||
#include "errno-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "io-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "locale-util.h"
|
||||
@@ -53,6 +51,7 @@
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
@@ -349,47 +348,6 @@ int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (streq(machine, ".host")) {
|
||||
*pid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hostname_is_valid(machine, 0))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("/run/systemd/machines/", machine);
|
||||
r = parse_env_file(NULL, p,
|
||||
"LEADER", &s,
|
||||
"CLASS", &class);
|
||||
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 pid_is_kernel_thread(pid_t pid) {
|
||||
int r;
|
||||
|
||||
|
||||
@@ -54,8 +54,6 @@ int pid_get_start_time(pid_t pid, usec_t *ret);
|
||||
int pidref_get_start_time(const PidRef *pid, usec_t *ret);
|
||||
int get_process_umask(pid_t pid, mode_t *ret);
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid);
|
||||
|
||||
static inline bool SIGINFO_CODE_IS_DEAD(int code) {
|
||||
return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user