fstab-generator: clear nosuid/nodev/noexec for root=bind: mounts

A bind mount inherits the mount flags of the file system the source
directory resides on. For root=bind: the source typically lives below
/run/ (e.g. a freshly unpacked tar image in /run/machines/), which is
mounted nosuid,nodev, so those flags propagated to /sysroot and broke
suid binaries (e.g. sudo) and device nodes on the booted system.

Default bind root mounts to dev,suid,exec instead, unless the user
overrides this via rootflags=.

Fixes: https://github.com/systemd/systemd/issues/41352

Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit b77be9f072)
(cherry picked from commit 413e4f34a7)
This commit is contained in:
Daan De Meyer
2026-06-03 13:54:13 +00:00
committed by Luca Boccassi
parent d62e2be6ef
commit 95ba1f2a35
6 changed files with 41 additions and 1 deletions

View File

@@ -105,7 +105,12 @@
<para>Use <literal>bind:…</literal> to bind mount another directory as operating system root
filesystems (added in v258). Expects an absolute path name referencing an existing directory within the initrd's file
hierarchy to boot into.</para>
hierarchy to boot into. Since the resulting root file system is supposed to behave like a regular OS
root, the bind mount is established with the <option>dev</option>, <option>suid</option> and
<option>exec</option> options (i.e. the <option>nodev</option>, <option>nosuid</option> and
<option>noexec</option> flags that would otherwise be inherited from the file system the source
directory resides on, such as <filename>/run/</filename>, are cleared), unless overridden via
<varname>rootflags=</varname>.</para>
<para>Set to <literal>off</literal> to turn off mounting of a root file system.</para>

View File

@@ -1229,6 +1229,26 @@ static int add_sysroot_mount(void) {
if (!strextend_with_separator(&combined_options, ",", extra_opts))
return log_oom();
/* A bind mount inherits the mount flags (nosuid, nodev, noexec, …) of the file system the source
* directory is located on. The source typically lives below /run/ (e.g. a freshly unpacked tar image
* in /run/machines/), which is mounted nosuid,nodev, and these flags would then propagate to our root
* file system, breaking suid binaries (e.g. sudo) and device nodes. Since this is supposed to become a
* regular OS root file system, default to dev,suid,exec instead, unless the user explicitly requested
* otherwise. */
if (bind) {
static const char* const defaults[] = {
"suid", "suid\0" "nosuid\0",
"dev", "dev\0" "nodev\0",
"exec", "exec\0" "noexec\0",
NULL,
};
STRV_FOREACH_PAIR(add, test, defaults)
if (!fstab_test_option(combined_options, *test))
if (!strextend_with_separator(&combined_options, ",", *add))
return log_oom();
}
log_debug("Found entry what=%s where=/sysroot type=%s opts=%s", what, strna(fstype), strempty(combined_options));
/* Only honor x-systemd.makefs and .validatefs here, others are not relevant in initrd/not used

View File

@@ -0,0 +1,12 @@
# Automatically generated by systemd-fstab-generator
[Unit]
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
SourcePath=/proc/cmdline
Before=initrd-root-fs.target
After=imports.target
[Mount]
What=/run/machines/root
Where=/sysroot
Options=rw,bind,suid,dev,exec

View File

@@ -0,0 +1 @@
root=bind:/run/machines/root