From: Daan De Meyer Date: Wed, 20 Dec 2023 20:57:37 +0000 (+0100) Subject: Add SelinuxRelabel= setting X-Git-Tag: v20~44^2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2199%2Fhead;p=thirdparty%2Fmkosi.git Add SelinuxRelabel= setting Let's give users some more control over selinux relabeling. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 9537ebc6d..19401edac 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -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: diff --git a/mkosi/config.py b/mkosi/config.py index 7619cacc6..f9ee8ec47 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -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 ( diff --git a/mkosi/resources/mkosi.md b/mkosi/resources/mkosi.md index 45dc5af7d..4298a5c83 100644 --- a/mkosi/resources/mkosi.md +++ b/mkosi/resources/mkosi.md @@ -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` diff --git a/tests/test_json.py b/tests/test_json.py index 04e5b5cb9..253519e3a 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -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,