]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add --acl option
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 27 Mar 2023 08:55:16 +0000 (10:55 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 29 Mar 2023 07:31:27 +0000 (09:31 +0200)
Let's make the usage of ACLs opt-in since they leak into the final
image if the directory output is used.

We move the call to print_output_size() so its executed inside the
user namespace, which is required because we might not have permissions
to read some of the image's directories outside the user namespace.

mkosi.md
mkosi/__init__.py
mkosi/backend.py

index 9e008fbfacd6b4980705d62fd6aba00f943b84ef..24f072021ea98966f4f3b015fa2ec196603f0b7f 100644 (file)
--- a/mkosi.md
+++ b/mkosi.md
@@ -861,6 +861,11 @@ a boolean argument: either "1", "yes", or "true" to enable, or "0",
   OEM string. This will only be picked up by systemd-boot/systemd-stub versions
   newer than or equal to v254.
 
+`Acl=`, `--acl=`
+
+: If specified, ACLs will be set on any generated root filesystem directories that
+  allow the user running mkosi to remove them without needing privileges.
+
 ### Commandline-only Options
 
 Those settings cannot be configured in the configuration files.
index 4b534fbdd2be0043c8d6144601d28787c6f1544d..01ef45c82f4311204efe0fa52d02d861d4a4788c 100644 (file)
@@ -1008,7 +1008,10 @@ def calculate_bmap(state: MkosiState) -> None:
         run(cmdline)
 
 
-def acl_toggle_remove(root: Path, uid: int, *, allow: bool) -> None:
+def acl_toggle_remove(config: MkosiConfig, root: Path, uid: int, *, allow: bool) -> None:
+    if not config.acl:
+        return
+
     ret = run(
         [
             "setfacl",
@@ -1032,12 +1035,12 @@ def save_cache(state: MkosiState) -> None:
     with complete_step("Installing cache copies"):
         unlink_try_hard(final)
         shutil.move(state.root, final)
-        acl_toggle_remove(final, state.uid, allow=True)
+        acl_toggle_remove(state.config, final, state.uid, allow=True)
 
         if state.config.build_script:
             unlink_try_hard(build)
             shutil.move(state.build_overlay, build)
-            acl_toggle_remove(build, state.uid, allow=True)
+            acl_toggle_remove(state.config, build, state.uid, allow=True)
 
 
 def dir_size(path: PathString) -> int:
@@ -1953,6 +1956,12 @@ def create_parser() -> ArgumentParserMkosi:
         default=[],
         help="Append extra entries to the kernel command line when booting the image",
     )
+    group.add_argument(
+        "--acl",
+        metavar="BOOL",
+        action=BooleanAction,
+        help="Set ACLs on generated directories to permit the user running mkosi to remove them",
+    )
 
     group = parser.add_argument_group("Additional configuration options")
     group.add_argument(
@@ -3070,10 +3079,10 @@ def reuse_cache_tree(state: MkosiState) -> bool:
 
     with complete_step("Copying cached trees"):
         copy_path(final, state.root)
-        acl_toggle_remove(state.root, state.uid, allow=False)
+        acl_toggle_remove(state.config, state.root, state.uid, allow=False)
         if state.config.build_script:
             copy_path(build, state.build_overlay)
-            acl_toggle_remove(state.build_overlay, state.uid, allow=False)
+            acl_toggle_remove(state.config, state.build_overlay, state.uid, allow=False)
 
     return True
 
@@ -3327,7 +3336,7 @@ def build_stuff(uid: int, gid: int, config: MkosiConfig) -> None:
         save_manifest(state, manifest)
 
         if state.config.cache_path:
-            acl_toggle_remove(state.config.cache_path, state.uid, allow=True)
+            acl_toggle_remove(state.config, state.config.cache_path, state.uid, allow=True)
 
         for p in state.config.output_paths():
             if state.staging.joinpath(p.name).exists():
@@ -3335,7 +3344,7 @@ def build_stuff(uid: int, gid: int, config: MkosiConfig) -> None:
                 if p != state.config.output or state.config.output_format != OutputFormat.directory:
                     os.chown(p, state.uid, state.gid)
                 else:
-                    acl_toggle_remove(p, uid, allow=True)
+                    acl_toggle_remove(state.config, p, uid, allow=True)
                 if p in (state.config.output, state.config.output_split_kernel):
                     compress_output(state.config, p, uid=state.uid, gid=state.gid)
 
@@ -3345,6 +3354,8 @@ def build_stuff(uid: int, gid: int, config: MkosiConfig) -> None:
             if p.name.startswith(state.config.output.name):
                 compress_output(state.config, p, uid=state.uid, gid=state.gid)
 
+    print_output_size(config)
+
 
 def check_root() -> None:
     if os.getuid() != 0:
@@ -3431,13 +3442,13 @@ def run_shell(config: MkosiConfig) -> None:
     uid, _ = current_user_uid_gid()
 
     if config.output_format == OutputFormat.directory:
-        acl_toggle_remove(config.output, uid, allow=False)
+        acl_toggle_remove(config, config.output, uid, allow=False)
 
     try:
         run(cmdline, stdout=sys.stdout)
     finally:
         if config.output_format == OutputFormat.directory:
-            acl_toggle_remove(config.output, uid, allow=True)
+            acl_toggle_remove(config, config.output, uid, allow=True)
 
 
 def find_qemu_binary(config: MkosiConfig) -> str:
@@ -3872,7 +3883,12 @@ def run_verb(raw: argparse.Namespace) -> None:
                 check_outputs(config)
 
         if needs_build(config) or config.verb == Verb.clean:
-            unlink_output(config)
+            def target() -> None:
+                if os.getuid() != 0:
+                    become_root()
+                unlink_output(config)
+
+            fork_and_wait(target)
 
         if needs_build(config):
             def target() -> None:
@@ -3889,8 +3905,6 @@ def run_verb(raw: argparse.Namespace) -> None:
             if config.auto_bump:
                 bump_image_version(config)
 
-            print_output_size(config)
-
         with suppress_stacktrace():
             if config.verb in (Verb.shell, Verb.boot):
                 run_shell(config)
index dfbdef6331eb55e194b2f8df29d88aad8e7e18e9..94233e4251c3028763fb4b520119e9cce61b40b5 100644 (file)
@@ -307,6 +307,7 @@ class MkosiConfig:
     workspace_dir: Optional[Path]
     initrds: list[Path]
     kernel_command_line_extra: list[str]
+    acl: bool
 
     # QEMU-specific options
     qemu_headless: bool