diff --git a/man/systemd-sysext.xml b/man/systemd-sysext.xml
index 6e164077e2..5e8d11ef3d 100644
--- a/man/systemd-sysext.xml
+++ b/man/systemd-sysext.xml
@@ -151,7 +151,8 @@
confext will extend only /etc. Files and directories contained
in the confext images outside of the /etc/ hierarchy are not
merged, and hence have no effect when included in the image. Formats for these images are of the
- same as sysext images.
+ same as sysext images. The merged hierarchy will be mounted with nosuid and
+ (if not disabled via ) noexec.
Confexts are looked for in the directories /run/confexts/,
/var/lib/confexts/, /usr/lib/confexts/ and
@@ -290,6 +291,14 @@
see above for details.
+
+ BOOL
+
+ When merging configuration extensions into /etc/ the
+ MS_NOEXEC mount flag is used by default. This option can be used to disable
+ it.
+
+
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index e23785cc56..27ab57e119 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -45,6 +45,7 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
static bool arg_legend = true;
static bool arg_force = false;
+static int arg_noexec = -1;
static ImagePolicy *arg_image_policy = NULL;
/* Is set to IMAGE_CONFEXT when systemd is called with the confext functionality instead of the default */
@@ -64,6 +65,7 @@ static const struct {
const char *scope_env;
const char *name_env;
const ImagePolicy *default_image_policy;
+ unsigned long default_mount_flags;
} image_class_info[_IMAGE_CLASS_MAX] = {
[IMAGE_SYSEXT] = {
.dot_directory_name = ".systemd-sysext",
@@ -74,6 +76,7 @@ static const struct {
.scope_env = "SYSEXT_SCOPE",
.name_env = "SYSTEMD_SYSEXT_HIERARCHIES",
.default_image_policy = &image_policy_sysext,
+ .default_mount_flags = MS_RDONLY|MS_NODEV,
},
[IMAGE_CONFEXT] = {
.dot_directory_name = ".systemd-confext",
@@ -84,6 +87,7 @@ static const struct {
.scope_env = "CONFEXT_SCOPE",
.name_env = "SYSTEMD_CONFEXT_HIERARCHIES",
.default_image_policy = &image_policy_confext,
+ .default_mount_flags = MS_RDONLY|MS_NODEV|MS_NOSUID|MS_NOEXEC,
}
};
@@ -288,6 +292,7 @@ static int mount_overlayfs(
_cleanup_free_ char *options = NULL;
bool separator = false;
+ unsigned long flags;
int r;
assert(where);
@@ -309,8 +314,12 @@ static int mount_overlayfs(
separator = true;
}
+ flags = image_class_info[arg_image_class].default_mount_flags;
+ if (arg_noexec >= 0)
+ SET_FLAG(flags, MS_NOEXEC, arg_noexec);
+
/* Now mount the actual overlayfs */
- r = mount_nofollow_verbose(LOG_ERR, image_class_info[arg_image_class].short_identifier, where, "overlay", MS_RDONLY, options);
+ r = mount_nofollow_verbose(LOG_ERR, image_class_info[arg_image_class].short_identifier, where, "overlay", flags, options);
if (r < 0)
return r;
@@ -948,6 +957,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
" --force Ignore version incompatibilities\n"
" --image-policy=POLICY\n"
" Specify disk image dissection policy\n"
+ " --noexec=BOOL Whether to mount extension overlay with noexec\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
@@ -969,6 +979,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_JSON,
ARG_FORCE,
ARG_IMAGE_POLICY,
+ ARG_NOEXEC,
};
static const struct option options[] = {
@@ -980,6 +991,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "json", required_argument, NULL, ARG_JSON },
{ "force", no_argument, NULL, ARG_FORCE },
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
+ { "noexec", required_argument, NULL, ARG_NOEXEC },
{}
};
@@ -1029,6 +1041,14 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
+ case ARG_NOEXEC:
+ r = parse_boolean_argument("--noexec", optarg, NULL);
+ if (r < 0)
+ return r;
+
+ arg_noexec = r;
+ break;
+
case '?':
return -EINVAL;
diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh
index 52634c64b2..f6b2467a98 100755
--- a/test/units/testsuite-50.sh
+++ b/test/units/testsuite-50.sh
@@ -515,8 +515,14 @@ mkdir -p /run/confexts/test/etc/extension-release.d
echo "ID=_any" >/run/confexts/test/etc/extension-release.d/extension-release.test
echo "ARCHITECTURE=_any" >>/run/confexts/test/etc/extension-release.d/extension-release.test
echo "MARKER_CONFEXT_123" >/run/confexts/test/etc/testfile
+cat </run/confexts/test/etc/testscript
+#!/bin/bash
+echo "This should not happen"
+EOF
+chmod +x /run/confexts/test/etc/testscript
systemd-confext merge
grep -q -F "MARKER_CONFEXT_123" /etc/testfile
+/etc/testscript && { echo 'unexpected success'; exit 1; }
systemd-confext status
systemd-confext unmerge
rm -rf /run/confexts/