[pseudo] [PATCH v2 0/2] close_range: implement it rather than return ENOSYS

Babanpreet Singh <[email protected]> Thu, 16 Jul 2026 05:56:31 +0000
Newsgroups org.yoctoproject.lists.yocto-patches
Message-ID <[email protected]>
pseudo's close_range() wrapper has returned ENOSYS unconditionally since
35433e6 ("ports/linux/guts: Add close_range wrapper for glibc 2.34").
systemd v260 deleted its /proc/self/fd fallback and treats a failure as
fatal, so under pseudo every fork+exec dies. That is [YOCTO #16339]. Full
story in v1:

  https://lore.kernel.org/yocto-patches/[email protected]/

Paul, thanks for the review. Changes in v2, both from it:

1/2: no code change apart from one comment. The commit message is
rewritten in plainer language throughout; the "takes descriptors with it
on the way out" sentence and the comment that repeated it now simply say
that invalid arguments are rejected with EINVAL before anything is
closed.

2/2: two real gaps closed.

  - CLOSE_RANGE_CLOEXEC needs a 5.11 kernel while the syscall itself needs
    5.9, so probing only for the syscall made the test fail on 5.9/5.10.
    The shell wrapper now probes for the flag separately, the same
    PSEUDO_DISABLED=1 way, and on such a kernel only the CLOEXEC part of
    the test is left out.

  - CLOSE_RANGE_UNSHARE is now tested against a real sharer, not argued
    from unshare() semantics: a child cloned with CLONE_FILES closes a
    shared descriptor with the flag set, and the parent must still hold it
    afterwards. A second child closes the same descriptor without the flag
    and the parent must see it gone, so a clone that quietly stopped
    sharing the table cannot make the first check pass vacuously.

The new test was checked for sensitivity by deliberately removing the
unshare() call from the wrapper: it fails with "child's CLOSE_RANGE_UNSHARE
closed the parent's fd 3", and passes with the real implementation. The
5.9/5.10 probe path cannot be exercised end to end on this host (6.17
kernel); the --no-cloexec branch it selects was run directly under pseudo
and passes. Full run_tests.sh is unchanged from master apart from the new
test passing (the two pre-existing flaky parallel-* failures show up either
way).

The v1 question about OP_CLOSEFROM stepping around five of pseudo's
descriptors while others exist (pseudo_prefix_dir_fd, pseudo_pwd_lck_fd,
pseudo_util_evlog_fd) still stands; happy to send a follow-up if that list
is short in both places.

Babanpreet Singh (2):
  ports/linux/guts: Implement close_range() instead of returning ENOSYS
  tests: Add close_range() test

 enums/op.in                    |   1 +
 ports/linux/guts/close_range.c |  54 ++++++-
 ports/linux/portdefs.h         |  16 ++
 pseudo_client.c                |  60 +++++++
 test/test-close-range.c        | 283 +++++++++++++++++++++++++++++++++
 test/test-close-range.sh       |  24 +++
 6 files changed, 431 insertions(+), 7 deletions(-)
 create mode 100644 test/test-close-range.c
 create mode 100755 test/test-close-range.sh

-- 
2.43.0