Skip to content

Commit 1494375

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 dc2d666 commit 1494375

File tree

3 files changed

+91
-5
lines changed

3 files changed

+91
-5
lines changed

crun.1

+8
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,14 @@ 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 target user namespace.
648+
641649
.SH Automatically create user namespace
642650
.PP
643651
When running as user different than root, an user namespace is

crun.1.md

+8
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ 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 target user namespace.
517+
510518
## Automatically create user namespace
511519

512520
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
@@ -291,6 +291,10 @@ struct mount_attr_s
291291
# define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
292292
#endif
293293

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

366+
static int
367+
get_idmapped_mount (const char *src, pid_t pid, libcrun_error_t *err)
368+
{
369+
cleanup_close int open_tree_fd = -1;
370+
cleanup_close int fd = -1;
371+
int ret;
372+
char proc_path[64];
373+
struct mount_attr_s attr = {
374+
0,
375+
};
376+
377+
sprintf (proc_path, "/proc/%d/ns/user", pid);
378+
fd = open (proc_path, O_RDONLY);
379+
if (UNLIKELY (fd < 0))
380+
return crun_make_error (err, errno, "open `%s`", proc_path);
381+
382+
open_tree_fd = syscall_open_tree (-1, src,
383+
AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
384+
if (UNLIKELY (open_tree_fd < 0))
385+
return crun_make_error (err, errno, "open `/%s`", src);
386+
387+
attr.attr_set = MOUNT_ATTR_IDMAP;
388+
attr.userns_fd = fd;
389+
390+
ret = syscall_mount_setattr (open_tree_fd, "", AT_EMPTY_PATH, &attr);
391+
if (UNLIKELY (ret < 0))
392+
return crun_make_error (err, errno, "mount_setattr `%s`", src);
393+
394+
/*
395+
ret = syscall_fsmount (open_tree_fd, FSMOUNT_CLOEXEC, 0);
396+
if (UNLIKELY (ret < 0))
397+
return crun_make_error (err, errno, "fsmount `%s`", src);
398+
*/
399+
return get_and_reset (&open_tree_fd);
400+
}
401+
362402
int
363403
libcrun_create_keyring (const char *name, const char *label, libcrun_error_t *err)
364404
{
@@ -432,8 +472,11 @@ enum
432472
{
433473
OPTION_TMPCOPYUP = (1 << 0),
434474
OPTION_RRO = (1 << 1),
475+
OPTION_IDMAP = (1 << 2),
435476
};
436477

478+
#define IDMAP "idmap"
479+
437480
static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0 },
438481
{ "bind", 0, MS_BIND, 0 },
439482
{ "rbind", 0, MS_REC | MS_BIND, 0 },
@@ -470,6 +513,7 @@ static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0
470513

471514
{ "tmpcopyup", 0, 0, OPTION_TMPCOPYUP },
472515
{ "rro", 0, 0, OPTION_RRO },
516+
{ IDMAP, 0, 0, OPTION_IDMAP },
473517

474518
{ NULL, 0, 0, 0 } };
475519

@@ -1658,7 +1702,8 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
16581702
ret = fs_move_mount_to (mfd, targetfd, NULL);
16591703
if (LIKELY (ret == 0))
16601704
{
1661-
ret = do_mount (container, NULL, mfd, target, NULL, flags, data, LABEL_NONE, err);
1705+
/* Force no MS_BIND flag to not attempt again the bind mount. */
1706+
ret = do_mount (container, NULL, mfd, target, NULL, flags & ~MS_BIND, data, LABEL_NONE, err);
16621707
if (UNLIKELY (ret < 0))
16631708
return ret;
16641709
mounted = true;
@@ -1711,17 +1756,20 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
17111756
return ret;
17121757
}
17131758

1714-
if (extra_flags & OPTION_RRO)
1759+
if (extra_flags & (OPTION_RRO | OPTION_IDMAP))
17151760
{
17161761
cleanup_close int dfd = -1;
17171762

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

1722-
ret = make_mount_rro (target, dfd, err);
1723-
if (UNLIKELY (ret < 0))
1724-
return ret;
1767+
if (extra_flags & OPTION_RRO)
1768+
{
1769+
ret = make_mount_rro (target, dfd, err);
1770+
if (UNLIKELY (ret < 0))
1771+
return ret;
1772+
}
17251773
}
17261774
}
17271775
return 0;
@@ -3257,6 +3305,17 @@ get_fd_map (libcrun_container_t *container)
32573305
return mount_fds;
32583306
}
32593307

3308+
static bool
3309+
is_idmapped (runtime_spec_schema_defs_mount *mnt)
3310+
{
3311+
size_t i;
3312+
3313+
for (i = 0; i < mnt->options_len; i++)
3314+
if (strcmp (mnt->options[i], IDMAP) == 0)
3315+
return true;
3316+
return false;
3317+
}
3318+
32603319
static int
32613320
prepare_and_send_mounts (libcrun_container_t *container, struct init_status_s *init_status,
32623321
pid_t pid, int sync_socket_host, libcrun_error_t *err)
@@ -3274,6 +3333,17 @@ prepare_and_send_mounts (libcrun_container_t *container, struct init_status_s *i
32743333

32753334
for (i = 0; i < def->mounts_len; i++)
32763335
{
3336+
if (is_idmapped (def->mounts[i]))
3337+
{
3338+
int fd;
3339+
3340+
fd = get_idmapped_mount (def->mounts[i]->source, pid, err);
3341+
if (UNLIKELY (fd < 0))
3342+
return fd;
3343+
3344+
mount_fds->fds[i] = fd;
3345+
}
3346+
32773347
if (mount_fds->fds[i] >= 0)
32783348
how_many++;
32793349
}

0 commit comments

Comments
 (0)