Merge pull request #977 from richardmaw-codethink/machinectl-userns-login-v2
Fix machinectl login with containers in user namespaces (v2)
This commit is contained in:
+38
-7
@@ -4950,8 +4950,8 @@ int container_get_leader(const char *machine, pid_t *pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
|
||||
int rfd = -1;
|
||||
|
||||
assert(pid >= 0);
|
||||
@@ -4983,6 +4983,15 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (userns_fd) {
|
||||
const char *userns;
|
||||
|
||||
userns = procfs_file_alloca(pid, "ns/user");
|
||||
usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (usernsfd < 0 && errno != ENOENT)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (root_fd) {
|
||||
const char *root;
|
||||
|
||||
@@ -5001,15 +5010,33 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
|
||||
if (netns_fd)
|
||||
*netns_fd = netnsfd;
|
||||
|
||||
if (userns_fd)
|
||||
*userns_fd = usernsfd;
|
||||
|
||||
if (root_fd)
|
||||
*root_fd = rfd;
|
||||
|
||||
pidnsfd = mntnsfd = netnsfd = -1;
|
||||
pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
||||
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 equal before attempting to enter. */
|
||||
_cleanup_free_ char *userns_fd_path = NULL;
|
||||
int r;
|
||||
if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = files_same(userns_fd_path, "/proc/self/ns/user");
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r)
|
||||
userns_fd = -1;
|
||||
}
|
||||
|
||||
if (pidns_fd >= 0)
|
||||
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
||||
@@ -5023,6 +5050,10 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
|
||||
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
||||
return -errno;
|
||||
|
||||
if (userns_fd >= 0)
|
||||
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (root_fd >= 0) {
|
||||
if (fchdir(root_fd) < 0)
|
||||
return -errno;
|
||||
@@ -6038,7 +6069,7 @@ int ptsname_malloc(int fd, char **ret) {
|
||||
}
|
||||
|
||||
int openpt_in_namespace(pid_t pid, int flags) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
@@ -6055,7 +6086,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
|
||||
|
||||
assert(pid > 0);
|
||||
|
||||
r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
|
||||
r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -6071,7 +6102,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
|
||||
+2
-2
@@ -803,8 +803,8 @@ int get_proc_cmdline_key(const char *parameter, char **value);
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid);
|
||||
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
|
||||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user