1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #34258 from yuwata/nspawn-volatile-u

nspawn: make --volatile work with -U
This commit is contained in:
Lennart Poettering 2024-09-09 17:11:11 +02:00 committed by GitHub
commit 7a3223f509
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 89 additions and 15 deletions

View File

@ -1061,19 +1061,30 @@ bool has_custom_root_mount(const CustomMount *mounts, size_t n) {
return false;
}
static int setup_volatile_state(const char *directory, uid_t uid_shift, const char *selinux_apifs_context) {
_cleanup_free_ char *buf = NULL;
const char *p, *options;
static int setup_volatile_state(const char *directory) {
int r;
assert(directory);
/* --volatile=state means we simply overmount /var with a tmpfs, and the rest read-only. */
/* First, remount the root directory. */
r = bind_remount_recursive(directory, MS_RDONLY, MS_RDONLY, NULL);
if (r < 0)
return log_error_errno(r, "Failed to remount %s read-only: %m", directory);
return 0;
}
static int setup_volatile_state_after_remount_idmap(const char *directory, uid_t uid_shift, const char *selinux_apifs_context) {
_cleanup_free_ char *buf = NULL;
const char *p, *options;
int r;
assert(directory);
/* Then, after remount_idmap(), overmount /var/ with a tmpfs. */
p = prefix_roota(directory, "/var");
r = mkdir(p, 0755);
if (r < 0 && errno != EEXIST)
@ -1249,7 +1260,7 @@ int setup_volatile_mode(
return setup_volatile_yes(directory, uid_shift, selinux_apifs_context);
case VOLATILE_STATE:
return setup_volatile_state(directory, uid_shift, selinux_apifs_context);
return setup_volatile_state(directory);
case VOLATILE_OVERLAY:
return setup_volatile_overlay(directory, uid_shift, selinux_apifs_context);
@ -1259,6 +1270,22 @@ int setup_volatile_mode(
}
}
int setup_volatile_mode_after_remount_idmap(
const char *directory,
VolatileMode mode,
uid_t uid_shift,
const char *selinux_apifs_context) {
switch (mode) {
case VOLATILE_STATE:
return setup_volatile_state_after_remount_idmap(directory, uid_shift, selinux_apifs_context);
default:
return 0;
}
}
/* Expects *pivot_root_new and *pivot_root_old to be initialised to allocated memory or NULL. */
int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s) {
_cleanup_free_ char *root_new = NULL, *root_old = NULL;

View File

@ -63,6 +63,11 @@ int mount_custom(const char *dest, CustomMount *mounts, size_t n, uid_t uid_shif
bool has_custom_root_mount(const CustomMount *mounts, size_t n);
int setup_volatile_mode(const char *directory, VolatileMode mode, uid_t uid_shift, const char *selinux_apifs_context);
int setup_volatile_mode_after_remount_idmap(
const char *directory,
VolatileMode mode,
uid_t uid_shift,
const char *selinux_apifs_context);
int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s);
int setup_pivot_root(const char *directory, const char *pivot_root_new, const char *pivot_root_old);

View File

@ -4083,21 +4083,24 @@ static int outer_child(
if (arg_userns_mode != USER_NAMESPACE_NO &&
IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_AUTO) &&
arg_uid_shift != 0) {
_cleanup_free_ char *usr_subtree = NULL;
char *dirs[3];
size_t i = 0;
_cleanup_strv_free_ char **dirs = NULL;
dirs[i++] = (char*) directory;
if (dissected_image && dissected_image->partitions[PARTITION_USR].found) {
usr_subtree = path_join(directory, "/usr");
if (!usr_subtree)
if (arg_volatile_mode != VOLATILE_YES) {
r = strv_extend(&dirs, directory);
if (r < 0)
return log_oom();
dirs[i++] = usr_subtree;
}
dirs[i] = NULL;
if ((dissected_image && dissected_image->partitions[PARTITION_USR].found) ||
arg_volatile_mode == VOLATILE_YES) {
char *s = path_join(directory, "/usr");
if (!s)
return log_oom();
r = strv_consume(&dirs, s);
if (r < 0)
return log_oom();
}
r = remount_idmap(dirs, arg_uid_shift, arg_uid_range, UID_INVALID, UID_INVALID, REMOUNT_IDMAPPING_HOST_ROOT);
if (r == -EINVAL || ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
@ -4118,6 +4121,14 @@ static int outer_child(
}
}
r = setup_volatile_mode_after_remount_idmap(
directory,
arg_volatile_mode,
arg_uid_shift,
arg_selinux_apifs_context);
if (r < 0)
return r;
if (dissected_image) {
/* Now we know the uid shift, let's now mount everything else that might be in the image. */
r = dissected_image_mount_and_warn(

View File

@ -144,6 +144,37 @@ testcase_sanity() {
test ! -e "$root/var/also-nope"
test ! -e "$root/usr/nope-too"
# --volatile= with -U
touch "$root/usr/has-usr"
# volatile(=yes): rootfs is tmpfs, /usr/ from the OS tree is mounted read only
systemd-nspawn --directory="$root"\
--volatile \
-U \
bash -xec 'test -e /usr/has-usr; touch /usr/read-only && exit 1; touch /nope'
test ! -e "$root/nope"
test ! -e "$root/usr/read-only"
systemd-nspawn --directory="$root"\
--volatile=yes \
-U \
bash -xec 'test -e /usr/has-usr; touch /usr/read-only && exit 1; touch /nope'
test ! -e "$root/nope"
test ! -e "$root/usr/read-only"
# volatile=state: rootfs is read-only, /var/ is tmpfs
systemd-nspawn --directory="$root" \
--volatile=state \
-U \
bash -xec 'test -e /usr/has-usr; mountpoint /var; touch /read-only && exit 1; touch /var/nope'
test ! -e "$root/read-only"
test ! -e "$root/var/nope"
# volatile=overlay: tmpfs overlay is mounted over rootfs
systemd-nspawn --directory="$root" \
--volatile=overlay \
-U \
bash -xec 'test -e /usr/has-usr; touch /nope; touch /var/also-nope; touch /usr/nope-too'
test ! -e "$root/nope"
test ! -e "$root/var/also-nope"
test ! -e "$root/usr/nope-too"
# --machine=, --hostname=
systemd-nspawn --directory="$root" \
--machine="foo-bar.baz" \