Skip to content

Commit d3803e0

Browse files
committed
linux: new mount option "idmap"
when the "idmap" mount option is specified, create the mount outside of the container user namespace context and pass the mount fd to the container init process. Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent 02938ac commit d3803e0

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

crun.1

+10
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,16 @@ itself.
638638
.PP
639639
If the \fB\fCrro\fR option is specified then the mount is made recursively read-only.
640640

641+
.SH rro mount options
642+
.PP
643+
If the \fB\fCrro\fR option is specified then the mount is made recursively read-only.
644+
645+
.SH idmap mount options
646+
.PP
647+
If the \fB\fCidmap\fR option is specified then the mount is ID mapped using the container
648+
target user namespace. This is an experimental feature and can change at any time
649+
without notice.
650+
641651
.SH Automatically create user namespace
642652
.PP
643653
When running as user different than root, an user namespace is

crun.1.md

+10
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,16 @@ itself.
507507

508508
If the `rro` option is specified then the mount is made recursively read-only.
509509

510+
## rro mount options
511+
512+
If the `rro` option is specified then the mount is made recursively read-only.
513+
514+
## idmap mount options
515+
516+
If the `idmap` option is specified then the mount is ID mapped using the container
517+
target user namespace. This is an experimental feature and can change at any time
518+
without notice.
519+
510520
## Automatically create user namespace
511521

512522
When running as user different than root, an user namespace is

src/libcrun/linux.c

+63-1
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ struct mount_attr_s
290290
# define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
291291
#endif
292292

293+
#ifndef MOUNT_ATTR_IDMAP
294+
# define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
295+
#endif
296+
293297
static int
294298
syscall_mount_setattr (int dfd, const char *path, unsigned int flags,
295299
struct mount_attr_s *attr)
@@ -358,6 +362,37 @@ make_mount_rro (const char *target, int targetfd, libcrun_error_t *err)
358362
return 0;
359363
}
360364

365+
static int
366+
get_idmapped_mount (const char *src, pid_t pid, libcrun_error_t *err)
367+
{
368+
cleanup_close int open_tree_fd = -1;
369+
cleanup_close int fd = -1;
370+
int ret;
371+
char proc_path[64];
372+
struct mount_attr_s attr = {
373+
0,
374+
};
375+
376+
sprintf (proc_path, "/proc/%d/ns/user", pid);
377+
fd = open (proc_path, O_RDONLY);
378+
if (UNLIKELY (fd < 0))
379+
return crun_make_error (err, errno, "open `%s`", proc_path);
380+
381+
open_tree_fd = syscall_open_tree (-1, src,
382+
AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
383+
if (UNLIKELY (open_tree_fd < 0))
384+
return crun_make_error (err, errno, "open `/%s`", src);
385+
386+
attr.attr_set = MOUNT_ATTR_IDMAP;
387+
attr.userns_fd = fd;
388+
389+
ret = syscall_mount_setattr (open_tree_fd, "", AT_EMPTY_PATH, &attr);
390+
if (UNLIKELY (ret < 0))
391+
return crun_make_error (err, errno, "mount_setattr `%s`", src);
392+
393+
return get_and_reset (&open_tree_fd);
394+
}
395+
361396
int
362397
libcrun_create_keyring (const char *name, const char *label, libcrun_error_t *err)
363398
{
@@ -431,8 +466,11 @@ enum
431466
{
432467
OPTION_TMPCOPYUP = (1 << 0),
433468
OPTION_RRO = (1 << 1),
469+
OPTION_IDMAP = (1 << 2),
434470
};
435471

472+
#define IDMAP "idmap"
473+
436474
static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0 },
437475
{ "bind", 0, MS_BIND, 0 },
438476
{ "rbind", 0, MS_REC | MS_BIND, 0 },
@@ -469,6 +507,7 @@ static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0
469507

470508
{ "tmpcopyup", 0, 0, OPTION_TMPCOPYUP },
471509
{ "rro", 0, 0, OPTION_RRO },
510+
{ IDMAP, 0, 0, OPTION_IDMAP },
472511

473512
{ NULL, 0, 0, 0 } };
474513

@@ -1657,7 +1696,8 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
16571696
ret = fs_move_mount_to (mfd, targetfd, NULL);
16581697
if (LIKELY (ret == 0))
16591698
{
1660-
ret = do_mount (container, NULL, mfd, target, NULL, flags, data, LABEL_NONE, err);
1699+
/* Force no MS_BIND flag to not attempt again the bind mount. */
1700+
ret = do_mount (container, NULL, mfd, target, NULL, flags & ~MS_BIND, data, LABEL_NONE, err);
16611701
if (UNLIKELY (ret < 0))
16621702
return ret;
16631703
mounted = true;
@@ -3256,6 +3296,17 @@ get_fd_map (libcrun_container_t *container)
32563296
return mount_fds;
32573297
}
32583298

3299+
static bool
3300+
is_idmapped (runtime_spec_schema_defs_mount *mnt)
3301+
{
3302+
size_t i;
3303+
3304+
for (i = 0; i < mnt->options_len; i++)
3305+
if (strcmp (mnt->options[i], IDMAP) == 0)
3306+
return true;
3307+
return false;
3308+
}
3309+
32593310
static int
32603311
prepare_and_send_mounts (libcrun_container_t *container, pid_t pid, int sync_socket_host, libcrun_error_t *err)
32613312
{
@@ -3272,6 +3323,17 @@ prepare_and_send_mounts (libcrun_container_t *container, pid_t pid, int sync_soc
32723323

32733324
for (i = 0; i < def->mounts_len; i++)
32743325
{
3326+
if (is_idmapped (def->mounts[i]))
3327+
{
3328+
int fd;
3329+
3330+
fd = get_idmapped_mount (def->mounts[i]->source, pid, err);
3331+
if (UNLIKELY (fd < 0))
3332+
return fd;
3333+
3334+
mount_fds->fds[i] = fd;
3335+
}
3336+
32753337
if (mount_fds->fds[i] >= 0)
32763338
how_many++;
32773339
}

0 commit comments

Comments
 (0)