Skip to content

Commit fc4d0ca

Browse files
authored
Merge pull request #1557 from stgraber/main
Tweak namespace attach logic in forkproxy and forkfile
2 parents 0daf049 + 3d6b003 commit fc4d0ca

File tree

4 files changed

+46
-22
lines changed

4 files changed

+46
-22
lines changed

cmd/incusd/main_forkfile.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,18 @@ void forkfile(void)
5858
5959
// Attach to the container.
6060
if (ns_fd >= 0) {
61-
attach_userns_fd(ns_fd);
61+
int setns_flags = CLONE_NEWNS;
6262
63-
if (!change_namespaces(pidfd, ns_fd, CLONE_NEWNS)) {
63+
if (in_same_namespace(getpid(), ns_fd, "user") > 0)
64+
setns_flags |= CLONE_NEWUSER;
65+
66+
if (!change_namespaces(pidfd, ns_fd, setns_flags)) {
6467
error("error: setns");
6568
_exit(1);
6669
}
70+
71+
if (setns_flags & CLONE_NEWUSER)
72+
finalize_userns();
6773
} else {
6874
if (fchdir(rootfs_fd) < 0) {
6975
error("error: fchdir");

cmd/incusd/main_forkproxy.go

+28-19
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ void forkproxy(void)
120120
121121
if (pid == 0) {
122122
int listen_nsfd;
123+
int setns_flags;
123124
124125
whoami = FORKPROXY_CHILD;
125126
@@ -134,20 +135,24 @@ void forkproxy(void)
134135
_exit(EXIT_FAILURE);
135136
}
136137
137-
// Attach to the user namespace of the listener
138-
attach_userns_fd(listen_nsfd);
138+
// Attach to the namespaces of the listener
139+
setns_flags = CLONE_NEWNET;
139140
140-
// Attach to the network namespace of the listener
141-
if (!change_namespaces(listen_pidfd, listen_nsfd, CLONE_NEWNET)) {
142-
fprintf(stderr, "Error: %m - Failed setns to listener network namespace\n");
143-
_exit(EXIT_FAILURE);
144-
}
141+
if (in_same_namespace(getpid(), listen_nsfd, "user") > 0)
142+
setns_flags |= CLONE_NEWUSER;
145143
146-
if ((needs_mntns & LISTEN_NEEDS_MNTNS) && !change_namespaces(listen_pidfd, listen_nsfd, CLONE_NEWNS)) {
147-
fprintf(stderr, "Error: %m - Failed setns to listener mount namespace\n");
144+
if (needs_mntns & CONNECT_NEEDS_MNTNS)
145+
setns_flags |= CLONE_NEWNS;
146+
147+
if (!change_namespaces(listen_pidfd, listen_nsfd, setns_flags)) {
148+
fprintf(stderr, "Error: %m - Failed setns to listener namespaces\n");
148149
_exit(EXIT_FAILURE);
149150
}
150151
152+
// Complete switch to the user namespace of the connector
153+
if (setns_flags & CLONE_NEWUSER)
154+
finalize_userns();
155+
151156
close_prot_errno_disarm(listen_nsfd);
152157
close_prot_errno_disarm(listen_pidfd);
153158
@@ -166,6 +171,7 @@ void forkproxy(void)
166171
} else {
167172
pthread_t thread;
168173
int connect_nsfd;
174+
int setns_flags;
169175
170176
whoami = FORKPROXY_PARENT;
171177
@@ -180,21 +186,24 @@ void forkproxy(void)
180186
_exit(EXIT_FAILURE);
181187
}
182188
183-
// Attach to the user namespace of the connector
184-
attach_userns_fd(connect_nsfd);
189+
// Attach to the namespaces of the connector
190+
setns_flags = CLONE_NEWNET;
185191
186-
// Attach to the network namespace of the connector
187-
if (!change_namespaces(connect_pidfd, connect_nsfd, CLONE_NEWNET)) {
188-
fprintf(stderr, "Error: %m - Failed setns to connector network namespace\n");
189-
_exit(EXIT_FAILURE);
190-
}
192+
if (in_same_namespace(getpid(), connect_nsfd, "user") > 0)
193+
setns_flags |= CLONE_NEWUSER;
191194
192-
// Attach to the mount namespace of the connector
193-
if ((needs_mntns & CONNECT_NEEDS_MNTNS) && !change_namespaces(connect_pidfd, connect_nsfd, CLONE_NEWNS)) {
194-
fprintf(stderr, "Error: %m - Failed setns to connector mount namespace\n");
195+
if (needs_mntns & CONNECT_NEEDS_MNTNS)
196+
setns_flags |= CLONE_NEWNS;
197+
198+
if (!change_namespaces(connect_pidfd, connect_nsfd, setns_flags)) {
199+
fprintf(stderr, "Error: %m - Failed setns to connector namespaces\n");
195200
_exit(EXIT_FAILURE);
196201
}
197202
203+
// Complete switch to the user namespace of the connector
204+
if (setns_flags & CLONE_NEWUSER)
205+
finalize_userns();
206+
198207
close_prot_errno_disarm(connect_nsfd);
199208
close_prot_errno_disarm(connect_pidfd);
200209

cmd/incusd/main_nsexec.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ int preserve_ns(pid_t pid, int ns_fd, const char *ns)
111111
// If the two processes are not in the same namespace returns an fd to the
112112
// namespace of the second process identified by @pid2. If the two processes are
113113
// in the same namespace returns -EINVAL, -1 if an error occurred.
114-
static int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns)
114+
int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns)
115115
{
116116
__do_close int ns_fd1 = -EBADF, ns_fd2 = -EBADF;
117117
int ret = -1;
@@ -166,6 +166,13 @@ void attach_userns_fd(int ns_fd)
166166
_exit(EXIT_FAILURE);
167167
}
168168
169+
finalize_userns();
170+
}
171+
172+
void finalize_userns()
173+
{
174+
int ret;
175+
169176
ret = setuid(0);
170177
if (ret < 0) {
171178
fprintf(stderr, "Failed setuid to container root user: %s\n", strerror(errno));

shared/cgo/incus.h

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
__hidden extern char *advance_arg(bool required);
77
__hidden extern void attach_userns_fd(int ns_fd);
8+
__hidden extern void finalize_userns();
9+
__hidden extern int in_same_namespace(pid_t pid1, int ns_fd_pid2, const char *ns);
810
__hidden extern int can_inject_uevent(const char *uevent, size_t len);
911
__hidden extern void checkfeature();
1012
__hidden extern bool change_namespaces(int pidfd, int nsfd, unsigned int flags);

0 commit comments

Comments
 (0)