Skip to content

Commit

Permalink
Merge pull request #1557 from stgraber/main
Browse files Browse the repository at this point in the history
Tweak namespace attach logic in forkproxy and forkfile
  • Loading branch information
hallyn authored Jan 4, 2025
2 parents 0daf049 + 3d6b003 commit fc4d0ca
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 22 deletions.
10 changes: 8 additions & 2 deletions cmd/incusd/main_forkfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,18 @@ void forkfile(void)
// Attach to the container.
if (ns_fd >= 0) {
attach_userns_fd(ns_fd);
int setns_flags = CLONE_NEWNS;
if (!change_namespaces(pidfd, ns_fd, CLONE_NEWNS)) {
if (in_same_namespace(getpid(), ns_fd, "user") > 0)
setns_flags |= CLONE_NEWUSER;
if (!change_namespaces(pidfd, ns_fd, setns_flags)) {
error("error: setns");
_exit(1);
}
if (setns_flags & CLONE_NEWUSER)
finalize_userns();
} else {
if (fchdir(rootfs_fd) < 0) {
error("error: fchdir");
Expand Down
47 changes: 28 additions & 19 deletions cmd/incusd/main_forkproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void forkproxy(void)
if (pid == 0) {
int listen_nsfd;
int setns_flags;
whoami = FORKPROXY_CHILD;
Expand All @@ -134,20 +135,24 @@ void forkproxy(void)
_exit(EXIT_FAILURE);
}
// Attach to the user namespace of the listener
attach_userns_fd(listen_nsfd);
// Attach to the namespaces of the listener
setns_flags = CLONE_NEWNET;
// Attach to the network namespace of the listener
if (!change_namespaces(listen_pidfd, listen_nsfd, CLONE_NEWNET)) {
fprintf(stderr, "Error: %m - Failed setns to listener network namespace\n");
_exit(EXIT_FAILURE);
}
if (in_same_namespace(getpid(), listen_nsfd, "user") > 0)
setns_flags |= CLONE_NEWUSER;
if ((needs_mntns & LISTEN_NEEDS_MNTNS) && !change_namespaces(listen_pidfd, listen_nsfd, CLONE_NEWNS)) {
fprintf(stderr, "Error: %m - Failed setns to listener mount namespace\n");
if (needs_mntns & CONNECT_NEEDS_MNTNS)
setns_flags |= CLONE_NEWNS;
if (!change_namespaces(listen_pidfd, listen_nsfd, setns_flags)) {
fprintf(stderr, "Error: %m - Failed setns to listener namespaces\n");
_exit(EXIT_FAILURE);
}
// Complete switch to the user namespace of the connector
if (setns_flags & CLONE_NEWUSER)
finalize_userns();
close_prot_errno_disarm(listen_nsfd);
close_prot_errno_disarm(listen_pidfd);
Expand All @@ -166,6 +171,7 @@ void forkproxy(void)
} else {
pthread_t thread;
int connect_nsfd;
int setns_flags;
whoami = FORKPROXY_PARENT;
Expand All @@ -180,21 +186,24 @@ void forkproxy(void)
_exit(EXIT_FAILURE);
}
// Attach to the user namespace of the connector
attach_userns_fd(connect_nsfd);
// Attach to the namespaces of the connector
setns_flags = CLONE_NEWNET;
// Attach to the network namespace of the connector
if (!change_namespaces(connect_pidfd, connect_nsfd, CLONE_NEWNET)) {
fprintf(stderr, "Error: %m - Failed setns to connector network namespace\n");
_exit(EXIT_FAILURE);
}
if (in_same_namespace(getpid(), connect_nsfd, "user") > 0)
setns_flags |= CLONE_NEWUSER;
// Attach to the mount namespace of the connector
if ((needs_mntns & CONNECT_NEEDS_MNTNS) && !change_namespaces(connect_pidfd, connect_nsfd, CLONE_NEWNS)) {
fprintf(stderr, "Error: %m - Failed setns to connector mount namespace\n");
if (needs_mntns & CONNECT_NEEDS_MNTNS)
setns_flags |= CLONE_NEWNS;
if (!change_namespaces(connect_pidfd, connect_nsfd, setns_flags)) {
fprintf(stderr, "Error: %m - Failed setns to connector namespaces\n");
_exit(EXIT_FAILURE);
}
// Complete switch to the user namespace of the connector
if (setns_flags & CLONE_NEWUSER)
finalize_userns();
close_prot_errno_disarm(connect_nsfd);
close_prot_errno_disarm(connect_pidfd);
Expand Down
9 changes: 8 additions & 1 deletion cmd/incusd/main_nsexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ int preserve_ns(pid_t pid, int ns_fd, const char *ns)
// If the two processes are not in the same namespace returns an fd to the
// namespace of the second process identified by @pid2. If the two processes are
// in the same namespace returns -EINVAL, -1 if an error occurred.
static int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns)
int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns)
{
__do_close int ns_fd1 = -EBADF, ns_fd2 = -EBADF;
int ret = -1;
Expand Down Expand Up @@ -166,6 +166,13 @@ void attach_userns_fd(int ns_fd)
_exit(EXIT_FAILURE);
}
finalize_userns();
}
void finalize_userns()
{
int ret;
ret = setuid(0);
if (ret < 0) {
fprintf(stderr, "Failed setuid to container root user: %s\n", strerror(errno));
Expand Down
2 changes: 2 additions & 0 deletions shared/cgo/incus.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

__hidden extern char *advance_arg(bool required);
__hidden extern void attach_userns_fd(int ns_fd);
__hidden extern void finalize_userns();
__hidden extern int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns);
__hidden extern int can_inject_uevent(const char *uevent, size_t len);
__hidden extern void checkfeature();
__hidden extern bool change_namespaces(int pidfd, int nsfd, unsigned int flags);
Expand Down

0 comments on commit fc4d0ca

Please sign in to comment.