Skip to content

Commit 39e8611

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 39e8611

File tree

3 files changed

+95
-5
lines changed

3 files changed

+95
-5
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

+75-5
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,42 @@ 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+
/*
394+
ret = syscall_fsmount (open_tree_fd, FSMOUNT_CLOEXEC, 0);
395+
if (UNLIKELY (ret < 0))
396+
return crun_make_error (err, errno, "fsmount `%s`", src);
397+
*/
398+
return get_and_reset (&open_tree_fd);
399+
}
400+
361401
int
362402
libcrun_create_keyring (const char *name, const char *label, libcrun_error_t *err)
363403
{
@@ -431,8 +471,11 @@ enum
431471
{
432472
OPTION_TMPCOPYUP = (1 << 0),
433473
OPTION_RRO = (1 << 1),
474+
OPTION_IDMAP = (1 << 2),
434475
};
435476

477+
#define IDMAP "idmap"
478+
436479
static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0 },
437480
{ "bind", 0, MS_BIND, 0 },
438481
{ "rbind", 0, MS_REC | MS_BIND, 0 },
@@ -469,6 +512,7 @@ static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0
469512

470513
{ "tmpcopyup", 0, 0, OPTION_TMPCOPYUP },
471514
{ "rro", 0, 0, OPTION_RRO },
515+
{ IDMAP, 0, 0, OPTION_IDMAP },
472516

473517
{ NULL, 0, 0, 0 } };
474518

@@ -1657,7 +1701,8 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
16571701
ret = fs_move_mount_to (mfd, targetfd, NULL);
16581702
if (LIKELY (ret == 0))
16591703
{
1660-
ret = do_mount (container, NULL, mfd, target, NULL, flags, data, LABEL_NONE, err);
1704+
/* Force no MS_BIND flag to not attempt again the bind mount. */
1705+
ret = do_mount (container, NULL, mfd, target, NULL, flags & ~MS_BIND, data, LABEL_NONE, err);
16611706
if (UNLIKELY (ret < 0))
16621707
return ret;
16631708
mounted = true;
@@ -1710,17 +1755,20 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
17101755
return ret;
17111756
}
17121757

1713-
if (extra_flags & OPTION_RRO)
1758+
if (extra_flags & (OPTION_RRO | OPTION_IDMAP))
17141759
{
17151760
cleanup_close int dfd = -1;
17161761

17171762
dfd = safe_openat (rootfsfd, rootfs, rootfs_len, target, O_DIRECTORY, 0, err);
17181763
if (UNLIKELY (dfd < 0))
17191764
return crun_make_error (err, errno, "open mount target `/%s`", target);
17201765

1721-
ret = make_mount_rro (target, dfd, err);
1722-
if (UNLIKELY (ret < 0))
1723-
return ret;
1766+
if (extra_flags & OPTION_RRO)
1767+
{
1768+
ret = make_mount_rro (target, dfd, err);
1769+
if (UNLIKELY (ret < 0))
1770+
return ret;
1771+
}
17241772
}
17251773
}
17261774
return 0;
@@ -3256,6 +3304,17 @@ get_fd_map (libcrun_container_t *container)
32563304
return mount_fds;
32573305
}
32583306

3307+
static bool
3308+
is_idmapped (runtime_spec_schema_defs_mount *mnt)
3309+
{
3310+
size_t i;
3311+
3312+
for (i = 0; i < mnt->options_len; i++)
3313+
if (strcmp (mnt->options[i], IDMAP) == 0)
3314+
return true;
3315+
return false;
3316+
}
3317+
32593318
static int
32603319
prepare_and_send_mounts (libcrun_container_t *container, pid_t pid, int sync_socket_host, libcrun_error_t *err)
32613320
{
@@ -3272,6 +3331,17 @@ prepare_and_send_mounts (libcrun_container_t *container, pid_t pid, int sync_soc
32723331

32733332
for (i = 0; i < def->mounts_len; i++)
32743333
{
3334+
if (is_idmapped (def->mounts[i]))
3335+
{
3336+
int fd;
3337+
3338+
fd = get_idmapped_mount (def->mounts[i]->source, pid, err);
3339+
if (UNLIKELY (fd < 0))
3340+
return fd;
3341+
3342+
mount_fds->fds[i] = fd;
3343+
}
3344+
32753345
if (mount_fds->fds[i] >= 0)
32763346
how_many++;
32773347
}

0 commit comments

Comments
 (0)