linux-man.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: bugzilla-daemon@kernel.org
To: linux-man@vger.kernel.org
Subject: [Bug 220845] New: imprecise 'close_range' description of 'CLOSE_RANGE_UNSHARE'
Date: Mon, 08 Dec 2025 04:15:04 +0000	[thread overview]
Message-ID: <bug-220845-11311@https.bugzilla.kernel.org/> (raw)

https://bugzilla.kernel.org/show_bug.cgi?id=220845

            Bug ID: 220845
           Summary: imprecise 'close_range' description of
                    'CLOSE_RANGE_UNSHARE'
           Product: Documentation
           Version: unspecified
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P3
         Component: man-pages
          Assignee: documentation_man-pages@kernel-bugs.osdl.org
          Reporter: matthew.fernandez@gmail.com
        Regression: No

I’m looking into some more subtle behaviours of `close_range`. The man page
describes the effect of the `CLOSE_RANGE_UNSHARE` flag as:

> Unshare the specified file descriptors from any other processes before
> closing them, avoiding races with other threads sharing the file descriptor
> table.

This sounds as if it unshares _only_ the file descriptors included in the given
range. E.g. `close_range(1, 2, CLOSE_RANGE_UNSHARE)` would unshare FDs 1 and 2
but not 3. This surprised me as I thought it was only possible to share an
entire file descriptor table, not only certain file descriptors within that
table.

I wrote the attached program below to confirm my understanding; `close_range(…,
CLOSE_RANGE_UNSHARE)` appears to unshare the entire file descriptor table, not
just the specified range. Is this correct? If so, do you think the wording
should be adjusted to make this more precise? I’m not sure if my misreading
here is a common misunderstanding.

--

// $ gcc -std=c23 -Wall -Wextra main.c
// $ ./a.out
// a.out: main.c:69: main: Assertion `r1 == 0' failed.
// [2]    7961 IOT instruction (core dumped)  ./a.out
// $ gcc -DCLOSE_RANGE -std=c23 -Wall -Wextra main.c
// $ ./a.out
//

#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <linux/close_range.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>

static int a;
static int b;

static int child(void *) {

  // close both FDs
#ifdef CLOSE_RANGE
  const int r1 = close_range(a, a, CLOSE_RANGE_UNSHARE);
#else
  const int r1 = close(a);
#endif
  assert(r1 == 0);
  const int r2 = close(b);
  assert(r2 == 0);

  return 0;
}

int main(void) {

  // create two FDs we’ll share to the child
  a = open("/dev/null", O_RDONLY);
  assert(a >= 0);
  b = open("/dev/null", O_RDONLY);
  assert(b >= 0);
  assert(b > a);

  // create a stack for our upcoming child
  enum { STACK_SIZE = 1024 * 1024 };
  char *const stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  assert(stack != MAP_FAILED);

#ifdef __hppa__
  char *const stack_top = stack;
#else
  char *const stack_top = stack + STACK_SIZE;
#endif

  // create a child who shares our file descriptor table
  const pid_t pid = clone(child, stack_top, CLONE_FILES, NULL);
  assert(pid >= 0);

  // wait for the child to finish
  int status;
  const pid_t r = waitpid(pid, &status, __WALL);
  assert(r == pid);
  assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);

  // try closing our shared files
  const int r1 = close(a);
  assert(r1 == 0);
  const int r2 = close(b);
  assert(r2 == 0);

  (void)munmap(stack, STACK_SIZE);

  return 0;
}

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

                 reply	other threads:[~2025-12-08  4:15 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-220845-11311@https.bugzilla.kernel.org/ \
    --to=bugzilla-daemon@kernel.org \
    --cc=linux-man@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).