]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add SelinuxRelabel= setting 2199/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 20 Dec 2023 20:57:37 +0000 (21:57 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 21 Dec 2023 12:29:45 +0000 (13:29 +0100)
Let's give users some more control over selinux relabeling.

mkosi/__init__.py
mkosi/config.py
mkosi/resources/mkosi.md
tests/test_json.py

index 9537ebc6d5ded9109c17f7e0dcac3b78c8f22e75..19401edac678e5f938e3430a8f71fd6f78ceec28 100644 (file)
@@ -1936,11 +1936,17 @@ def systemd_tool_version(tool: PathString) -> GenericVersion:
     return GenericVersion(run([tool, "--version"], stdout=subprocess.PIPE).stdout.split()[2].strip("()"))
 
 
-def check_systemd_tool(*tools: PathString, version: str, reason: str, hint: Optional[str] = None) -> None:
+def check_tool(*tools: PathString, reason: str, hint: Optional[str] = None) -> Path:
     tool = find_binary(*tools)
     if not tool:
         die(f"Could not find '{tools[0]}' which is required to {reason}.", hint=hint)
 
+    return tool
+
+
+def check_systemd_tool(*tools: PathString, version: str, reason: str, hint: Optional[str] = None) -> None:
+    tool = check_tool(*tools, reason=reason, hint=hint)
+
     v = systemd_tool_version(tool)
     if v < version:
         die(f"Found '{tool}' with version {v} but version {version} or newer is required to {reason}.",
@@ -1960,6 +1966,9 @@ def check_tools(verb: Verb, config: MkosiConfig) -> None:
         if config.output_format in (OutputFormat.disk, OutputFormat.esp):
             check_systemd_tool("systemd-repart", version="254", reason="build disk images")
 
+        if config.selinux_relabel == ConfigFeature.enabled:
+            check_tool("setfiles", reason="relabel files")
+
     if verb == Verb.boot:
         check_systemd_tool("systemd-nspawn", version="254", reason="boot images")
 
@@ -2157,12 +2166,19 @@ def run_firstboot(state: MkosiState) -> None:
 
 
 def run_selinux_relabel(state: MkosiState) -> None:
+    if state.config.selinux_relabel == ConfigFeature.disabled:
+        return
+
     selinux = state.root / "etc/selinux/config"
     if not selinux.exists():
+        if state.config.selinux_relabel == ConfigFeature.enabled:
+            die("SELinux relabel is requested but could not find selinux config at /etc/selinux/config")
         return
 
     policy = run(["sh", "-c", f". {selinux} && echo $SELINUXTYPE"], stdout=subprocess.PIPE).stdout.strip()
     if not policy:
+        if state.config.selinux_relabel == ConfigFeature.enabled:
+            die("SELinux relabel is requested but no selinux policy is configured in /etc/selinux/config")
         return
 
     if not shutil.which("setfiles"):
@@ -2180,7 +2196,8 @@ def run_selinux_relabel(state: MkosiState) -> None:
         die(f"SELinux binary policy not found in {binpolicydir}")
 
     with complete_step(f"Relabeling files using {policy} policy"):
-        run(["setfiles", "-mFr", state.root, "-c", binpolicy, fc, state.root])
+        run(["setfiles", "-mFr", state.root, "-c", binpolicy, fc, state.root],
+            check=state.config.selinux_relabel == ConfigFeature.enabled)
 
 
 def need_build_overlay(config: MkosiConfig) -> bool:
index 7619cacc6a3574e3245025088f78f7c5d4be7f76..f9ee8ec47af33fd30c85a6dc0bd91b0192e8c5df 100644 (file)
@@ -1160,6 +1160,7 @@ class MkosiConfig:
     autologin: bool
     make_initrd: bool
     ssh: bool
+    selinux_relabel: ConfigFeature
 
     secure_boot: bool
     secure_boot_auto_enroll: bool
@@ -2076,6 +2077,14 @@ SETTINGS = (
         parse=config_parse_boolean,
         help="Set up SSH access from the host to the final image via 'mkosi ssh'",
     ),
+    MkosiConfigSetting(
+        dest="selinux_relabel",
+        name="SELinuxRelabel",
+        metavar="FEATURE",
+        section="Content",
+        parse=config_parse_feature,
+        help="Specify whether to relabel all files with setfiles",
+    ),
 
     MkosiConfigSetting(
         dest="secure_boot",
@@ -3325,6 +3334,7 @@ def summary(config: MkosiConfig) -> str:
                           Autologin: {yes_no(config.autologin)}
                         Make Initrd: {yes_no(config.make_initrd)}
                                 SSH: {yes_no(config.ssh)}
+                    SELinux Relabel: {config.selinux_relabel}
 """
 
     if config.output_format.is_extension_image() or config.output_format in (
index 45dc5af7db245b9e0ad75309501345f606b67db3..4298a5c837c104a6b3f4f35f2cb8bca319f3b3c9 100644 (file)
@@ -1200,6 +1200,23 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
   enable SSH access to any virtual machines via `mkosi ssh`. To access
   images booted using `mkosi boot`, use `machinectl`.
 
+`SELinuxRelabel=`, `--selinux-relabel=`
+
+: Specifies whether to relabel files to match the image's SELinux
+  policy. Takes a boolean value or `auto`. Defaults to `auto`. If
+  disabled, files will not relabeled. If enabled, an SELinux policy has
+  to be installed in the image and `setfiles` has to be available to
+  relabel files. If any errors occur during `setfiles`, the build will
+  fail. If set to `auto`, files will be relabeled if an SELinux policy
+  is installed in the image and if `setfiles` is available. Any errors
+  occurred during `setfiles` will be ignored.
+
+: Note that when running unprivileged, `setfiles` will fail to set any
+  labels that are not in the host's SELinux policy. To ensure `setfiles`
+  succeeds without errors, make sure to run mkosi as root or build from
+  a host system with the same SELinux policy as the image you're
+  building.
+
 ### [Validation] Section
 
 `SecureBoot=`, `--secure-boot`
index 04e5b5cb921b6bf20d4f537ed337e3ce0cb125cb..253519e3a7bb7aa087e290434dfd41bf445da297 100644 (file)
@@ -246,6 +246,7 @@ def test_config() -> None:
                     "target": "/qux"
                 }
             ],
+            "SELinuxRelabel": "disabled",
             "SectorSize": null,
             "SecureBoot": true,
             "SecureBootAutoEnroll": true,
@@ -386,6 +387,7 @@ def test_config() -> None:
         secure_boot_key = Path("/path/to/keyfile"),
         secure_boot_sign_tool = SecureBootSignTool.pesign,
         seed = uuid.UUID("7496d7d8-7f08-4a2b-96c6-ec8c43791b60"),
+        selinux_relabel = ConfigFeature.disabled,
         shim_bootloader = ShimBootloader.none,
         sign = False,
         sign_expected_pcr = ConfigFeature.disabled,