From: DaanDeMeyer Date: Wed, 24 Dec 2025 08:14:13 +0000 (+0100) Subject: sandbox: Refactor mount_rbind() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dbac129054ec9bc21a0948aed16ad135227a4482;p=thirdparty%2Fmkosi.git sandbox: Refactor mount_rbind() Let's split out separate functions for the mount API syscalls. --- diff --git a/mkosi/sandbox.py b/mkosi/sandbox.py index f03029d48..373cde390 100755 --- a/mkosi/sandbox.py +++ b/mkosi/sandbox.py @@ -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: