Skip to content

Commit 3ce50af

Browse files
mrunalpruncom
authored andcommitted
Fix setting SELinux label for mqueue when user namespaces are enabled
If one tries to user SELinux with user namespaces, then labeling of /dev/mqueue fails because the IPC namespace belongs to the root in init_user_ns. This commit fixes that by unsharing IPC namespace after we clone into a new USER namespace so the IPC namespace is owned by the root inside the new USER namespace as opposed to init_user_ns. Signed-off-by: Mrunal Patel <[email protected]>
1 parent f59ba3c commit 3ce50af

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

libcontainer/nsenter/nsexec.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,20 @@ static int child_func(void *arg)
9494
longjmp(*ca->env, JUMP_VAL);
9595
}
9696

97-
static int clone_parent(jmp_buf *env, int flags) __attribute__ ((noinline));
98-
static int clone_parent(jmp_buf *env, int flags)
97+
static int clone_parent(jmp_buf *env, int flags, bool delay_ipc_unshare) __attribute__ ((noinline));
98+
static int clone_parent(jmp_buf *env, int flags, bool delay_ipc_unshare)
9999
{
100100
int child;
101101
struct clone_arg ca = {
102102
.env = env,
103103
};
104104

105+
// Don't clone into NEWIPC at the same time as cloning into NEWUSER.
106+
// This way we can ensure that NEWIPC namespace belongs to the root in new user namespace.
107+
if (delay_ipc_unshare) {
108+
flags &= ~CLONE_NEWIPC;
109+
}
110+
105111
child = clone(child_func, ca.stack_ptr, CLONE_PARENT | SIGCHLD | flags, &ca);
106112

107113
/*
@@ -227,7 +233,7 @@ static void update_gidmap(int pid, char *map, int map_len)
227233

228234
#define JSON_MAX 4096
229235

230-
static void start_child(int pipenum, jmp_buf *env, int syncpipe[2], struct nlconfig_t *config)
236+
static void start_child(int pipenum, jmp_buf *env, int syncpipe[2], struct nlconfig_t *config, bool delay_ipc_unshare)
231237
{
232238
int len, childpid;
233239
char buf[JSON_MAX];
@@ -239,7 +245,7 @@ static void start_child(int pipenum, jmp_buf *env, int syncpipe[2], struct nlcon
239245
* (the bootstrap process). Also so we don't need to forward the
240246
* child's exit code or resend its death signal.
241247
*/
242-
childpid = clone_parent(env, config->cloneflags);
248+
childpid = clone_parent(env, config->cloneflags, delay_ipc_unshare);
243249
if (childpid < 0)
244250
bail("unable to fork");
245251

@@ -415,6 +421,9 @@ void nsexec(void)
415421
if (config.cloneflags == -1)
416422
bail("missing clone_flags");
417423

424+
bool delay_ipc_unshare = ((config.cloneflags & CLONE_NEWUSER) == CLONE_NEWUSER)
425+
&& ((config.cloneflags & CLONE_NEWIPC) == CLONE_NEWIPC);
426+
418427
/* Pipe so we can tell the child when we've finished setting up. */
419428
if (pipe(syncpipe) < 0)
420429
bail("failed to setup sync pipe between parent and child");
@@ -447,6 +456,12 @@ void nsexec(void)
447456
if (setgroups(0, NULL) < 0)
448457
bail("setgroups failed");
449458

459+
if (delay_ipc_unshare) {
460+
if (unshare(CLONE_NEWIPC)) {
461+
bail("unable to unshare IPC namespace");
462+
}
463+
}
464+
450465
if (consolefd != -1) {
451466
if (ioctl(consolefd, TIOCSCTTY, 0) < 0)
452467
bail("ioctl TIOCSCTTY failed");
@@ -466,7 +481,7 @@ void nsexec(void)
466481
}
467482

468483
/* Run the parent code. */
469-
start_child(pipenum, &env, syncpipe, &config);
484+
start_child(pipenum, &env, syncpipe, &config, delay_ipc_unshare);
470485

471486
/* Should never be reached. */
472487
bail("should never be reached");

0 commit comments

Comments
 (0)