]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
sandbox: Refactor mount_rbind()
authorDaanDeMeyer <daan.j.demeyer@gmail.com>
Wed, 24 Dec 2025 08:14:13 +0000 (09:14 +0100)
committerDaanDeMeyer <daan.j.demeyer@gmail.com>
Wed, 24 Dec 2025 09:53:51 +0000 (10:53 +0100)
Let's split out separate functions for the mount API syscalls.

mkosi/sandbox.py

index f03029d48d55f9c4b09db7cc5ae98b2d0c7f74cc..373cde39031cf893a862f4149c52d564bfec199f 100755 (executable)
@@ -446,76 +446,91 @@ def join_new_session_keyring() -> None:
         oserror("keyctl")
 
 
-def mount_rbind(src: str, dst: str, attrs: int = 0) -> None:
-    """
-    When using the old mount syscall to do a recursive bind mount, mount options are not
-    applied recursively. Because we want to do recursive read-only bind mounts in some cases, we
-    use the new mount API for that which does allow recursively changing mount options when doing
-    bind mounts.
-    """
-    flags = AT_NO_AUTOMOUNT | AT_RECURSIVE | AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLONE
+def open_tree(dirfd: int, path: str, flags: int = 0) -> int:
+    fd: int
 
     try:
         libc.open_tree.argtypes = (ctypes.c_int, ctypes.c_char_p, ctypes.c_uint)
-        fd = libc.open_tree(AT_FDCWD, src.encode(), flags)
+        fd = libc.open_tree(dirfd, path.encode(), flags)
     except AttributeError:
         libc.syscall.argtypes = (ctypes.c_long, ctypes.c_int, ctypes.c_char_p, ctypes.c_uint)
-        fd = libc.syscall(NR_open_tree, AT_FDCWD, src.encode(), flags)
+        fd = libc.syscall(NR_open_tree, dirfd, path.encode(), flags)
 
     if fd < 0:
-        oserror("open_tree", src)
+        oserror("open_tree", path)
 
-    with close(fd):
-        attr = mount_attr()
-        attr.attr_set = attrs
+    return fd
 
-        flags = AT_EMPTY_PATH | AT_RECURSIVE
 
-        try:
-            libc.mount_setattr.argtypes = (
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_uint,
-                ctypes.c_void_p,
-                ctypes.c_size_t,
-            )
-            r = libc.mount_setattr(fd, b"", flags, ctypes.addressof(attr), MOUNT_ATTR_SIZE_VER0)
-        except AttributeError:
-            libc.syscall.argtypes = (
-                ctypes.c_long,
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_uint,
-                ctypes.c_void_p,
-                ctypes.c_size_t,
-            )
-            r = libc.syscall(NR_mount_setattr, fd, b"", flags, ctypes.addressof(attr), MOUNT_ATTR_SIZE_VER0)
+def mount_setattr(dirfd: int, path: str, flags: int, attr: mount_attr) -> None:
+    try:
+        libc.mount_setattr.argtypes = (
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_uint,
+            ctypes.c_void_p,
+            ctypes.c_size_t,
+        )
+        r = libc.mount_setattr(dirfd, path.encode(), flags, ctypes.addressof(attr), MOUNT_ATTR_SIZE_VER0)
+    except AttributeError:
+        libc.syscall.argtypes = (
+            ctypes.c_long,
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_uint,
+            ctypes.c_void_p,
+            ctypes.c_size_t,
+        )
+        r = libc.syscall(
+            NR_mount_setattr,
+            dirfd,
+            path.encode(),
+            flags,
+            ctypes.addressof(attr),
+            MOUNT_ATTR_SIZE_VER0,
+        )
 
-        if r < 0:
-            oserror("mount_setattr", src)
+    if r < 0:
+        oserror("mount_setattr", path)
 
-        try:
-            libc.move_mount.argtypes = (
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_uint,
-            )
-            r = libc.move_mount(fd, b"", AT_FDCWD, dst.encode(), MOVE_MOUNT_F_EMPTY_PATH)
-        except AttributeError:
-            libc.syscall.argtypes = (
-                ctypes.c_long,
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_int,
-                ctypes.c_char_p,
-                ctypes.c_uint,
-            )
-            r = libc.syscall(NR_move_mount, fd, b"", AT_FDCWD, dst.encode(), MOVE_MOUNT_F_EMPTY_PATH)
 
-        if r < 0:
-            oserror("move_mount", dst)
+def move_mount(from_dirfd: int, from_path: str, to_dirfd: int, to_path: str, flags: int) -> None:
+    try:
+        libc.move_mount.argtypes = (
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_uint,
+        )
+        r = libc.move_mount(from_dirfd, from_path.encode(), to_dirfd, to_path.encode(), flags)
+    except AttributeError:
+        libc.syscall.argtypes = (
+            ctypes.c_long,
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_int,
+            ctypes.c_char_p,
+            ctypes.c_uint,
+        )
+        r = libc.syscall(NR_move_mount, from_dirfd, from_path.encode(), to_dirfd, to_path.encode(), flags)
+
+    if r < 0:
+        oserror("move_mount", to_path)
+
+
+def mount_rbind(src: str, dst: str, attrs: int = 0) -> None:
+    """
+    When using the old mount syscall to do a recursive bind mount, mount options are not
+    applied recursively. Because we want to do recursive read-only bind mounts in some cases, we
+    use the new mount API for that which does allow recursively changing mount options when doing
+    bind mounts.
+    """
+    flags = AT_NO_AUTOMOUNT | AT_RECURSIVE | AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLONE
+
+    with close(open_tree(AT_FDCWD, src, flags)) as fd:
+        mount_setattr(fd, "", AT_EMPTY_PATH | AT_RECURSIVE, mount_attr(attr_set=attrs))
+        move_mount(fd, "", AT_FDCWD, dst, MOVE_MOUNT_F_EMPTY_PATH)
 
 
 class umask: