]> git.feebdaed.xyz Git - 0xmirror/runc.git/commitdiff
ci: detect file descriptor leaks as comprehensively as possible
authorlifubang <lifubang@acmcoder.com>
Wed, 19 Nov 2025 02:46:17 +0000 (02:46 +0000)
committerlfbzhm <lifubang@acmcoder.com>
Thu, 20 Nov 2025 11:43:22 +0000 (19:43 +0800)
Co-authored-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: lifubang <lifubang@acmcoder.com>
tests/integration/create.bats

index b1693518a993cd274037484a6f557d00a29eda70..48b665dc04fba888ede350c5f82f0b731d06b697 100644 (file)
@@ -10,6 +10,70 @@ function teardown() {
        teardown_bundle
 }
 
+# is_allowed_fdtarget checks whether the target of a file descriptor symlink
+# conforms to the allowed whitelist.
+#
+# This whitelist reflects the set of file descriptors that runc legitimately
+# opens during container lifecycle operations (e.g., exec, create, and run).
+# If runc's internal behavior changes (e.g., new FD types are introduced),
+# this function MUST be updated accordingly to avoid false positives.
+#
+is_allowed_fdtarget() {
+       local target="$1"
+       {
+               # pty devices for stdio
+               grep -Ex "/dev/pts/[0-9]+" <<<"$target" ||
+                       # eventfd, eventpoll, signalfd, etc.
+                       grep -Ex "anon_inode:\[.+\]" <<<"$target" ||
+                       # procfs handle cache (pathrs-lite / libpathrs)
+                       grep -Ex "/(proc)?" <<<"$target" ||
+                       # anonymous sockets used for IPC
+                       grep -Ex "socket:\[[0-9]+\]" <<<"$target" ||
+                       # anonymous pipes used for I/O forwarding
+                       grep -Ex "pipe:\[[0-9]+\]" <<<"$target" ||
+                       # "runc start" synchronisation barrier FIFO
+                       grep -Ex ".*/exec\.fifo" <<<"$target" ||
+                       # temporary internal fd used in exec.fifo FIFO reopen (pathrs-lite / libpathrs)
+                       grep -Ex "(/proc)?/1/task/1/fd" <<<"$target" ||
+                       # overlayfs binary reference (CVE-2019-5736)
+                       grep -Ex "/runc" <<<"$target" ||
+                       # memfd cloned binary (CVE-2019-5736)
+                       grep -Fx "/memfd:runc_cloned:/proc/self/exe (deleted)" <<<"$target"
+       } >/dev/null
+       return "$?"
+}
+
+@test "runc create[detect fd leak as comprehensively as possible]" {
+       runc create --console-socket "$CONSOLE_SOCKET" test_busybox
+       [ "$status" -eq 0 ]
+
+       testcontainer test_busybox created
+
+       pid=$(__runc state test_busybox | jq '.pid')
+       violation_found=0
+
+       while IFS= read -rd '' link; do
+               fd_name=$(basename "$link")
+               # Skip . and ..
+               if [[ "$fd_name" == "." || "$fd_name" == ".." ]]; then
+                       continue
+               fi
+
+               # Resolve symlink target (use readlink)
+               target=$(readlink "$link" 2>/dev/null)
+               if [[ -z "$target" ]]; then
+                       echo "Warning: Cannot read target of $link"
+                       continue
+               fi
+
+               if ! is_allowed_fdtarget "$target"; then
+                       echo "Violation: FD $fd_name -> '$target'"
+                       violation_found=1
+               fi
+       done < <(find "/proc/$pid/fd" -type l -print0)
+       [ "$violation_found" -eq 0 ]
+}
+
 @test "runc create" {
        runc create --console-socket "$CONSOLE_SOCKET" test_busybox
        [ "$status" -eq 0 ]