]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Revert "sandbox: Work around extra file descriptor opened by importing ctypes since...
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 12 Sep 2025 09:57:42 +0000 (11:57 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 12 Sep 2025 09:57:42 +0000 (11:57 +0200)
This reverts commit 694c8d2721cd6d1081caf39641f615aa81d5f8a0.

mkosi/sandbox.py

index a265e52764f767e9124d1436bd9b3f5bdd7e968e..d210c8f1de1e0ccb4e74fa7efd295f073874b2be 100755 (executable)
@@ -8,6 +8,7 @@ minimum, please don't import any extra modules if it can be avoided.
 
 """
 
+import ctypes
 import os
 import sys
 import warnings  # noqa: F401 (loaded lazily by os.execvp() which happens too late)
@@ -32,6 +33,7 @@ EPERM = 1
 ENOENT = 2
 ENOSYS = 38
 F_DUPFD = 0
+F_GETFD = 1
 FS_IOC_GETFLAGS = 0x80086601
 FS_IOC_SETFLAGS = 0x40086602
 FS_NOCOW_FL = 0x00800000
@@ -64,59 +66,6 @@ SD_LISTEN_FDS_START = 3
 SIGSTOP = 19
 
 
-def is_valid_fd(fd: int) -> bool:
-    try:
-        os.close(os.dup(fd))
-    except OSError as e:
-        if e.errno != EBADF:
-            raise
-
-        return False
-
-    return True
-
-
-def open_file_descriptors() -> list[int]:
-    fds = []
-
-    with os.scandir("/proc/self/fd") as it:
-        for e in it:
-            if not e.is_symlink() and (e.is_file() or e.is_dir()):
-                continue
-
-            try:
-                fd = int(e.name)
-            except ValueError:
-                continue
-
-            fds.append(fd)
-
-    # os.scandir() either opens a file descriptor to the given path or dups the given file descriptor. Either
-    # way, there will be an extra file descriptor in the fds array that's not valid anymore now, so find out
-    # which one and drop it.
-    return sorted(fd for fd in fds if is_valid_fd(fd))
-
-
-class CloseNewFileDescriptors:
-    def __enter__(self) -> None:
-        self.fds = set(open_file_descriptors())
-
-    def __exit__(self, *args: object, **kwargs: object) -> None:
-        for fd in open_file_descriptors():
-            if fd not in self.fds:
-                os.close(fd)
-
-
-# Since python 3.14, importing ctypes opens an extra file descriptor which is used to allocate libffi
-# closures which are in turn used by ctypes to pass python functions as C callback function pointers. We
-# don't use this functionality, yet the file descriptor is still opened and messes with the file descriptor
-# packing logic since the file descriptor to libffi will be passed as a packed file descriptor to the
-# executable we're invoking. To avoid that from happening, we close libffi's file descriptor after importing
-# ctypes. See https://github.com/python/cpython/issues/135893.
-with CloseNewFileDescriptors():
-    import ctypes
-
-
 class mount_attr(ctypes.Structure):
     _fields_ = [
         ("attr_set", ctypes.c_uint64),
@@ -560,7 +509,27 @@ def is_relative_to(one: str, two: str) -> bool:
 
 
 def pack_file_descriptors() -> int:
-    fds = [fd for fd in open_file_descriptors() if fd >= SD_LISTEN_FDS_START]
+    fds = []
+
+    with os.scandir("/proc/self/fd") as it:
+        for e in it:
+            if not e.is_symlink() and (e.is_file() or e.is_dir()):
+                continue
+
+            try:
+                fd = int(e.name)
+            except ValueError:
+                continue
+
+            if fd < SD_LISTEN_FDS_START:
+                continue
+
+            fds.append(fd)
+
+    # os.scandir() either opens a file descriptor to the given path or dups the given file descriptor. Either
+    # way, there will be an extra file descriptor in the fds array that's not valid anymore now, so find out
+    # which one and drop it.
+    fds = sorted(fd for fd in fds if libc.fcntl(fd, F_GETFD, 0) >= 0)
 
     # The following is a reimplementation of pack_fds() in systemd.