summaryrefslogtreecommitdiff
path: root/include/uapi
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-09-22 13:40:12 +0200
committerChristian Brauner <brauner@kernel.org>2026-10-05 13:02:41 +0200
commitc73c0e243836d5dfd1c617f73b6003b1ad40b2d1 (patch)
tree0dbbe2d22ab8dc1d281dd3de402863870816750f /include/uapi
parentfd73f4a6659897191fa0d40695fe370925dd3780 (diff)
parent0a0f88fcb434f58fc5b444e7c9eeae791cdbbeda (diff)
Merge patch series "files,close_range: add CLOSE_RANGE_{CLOEXEC_ONLY,EXCEPT}"
Christian Brauner <brauner@kernel.org> says: close_range(CLOSE_RANGE_CLOEXEC) marks a range of file descriptors close-on-exec. It only marks them. The file descriptors are only ever closed during an exec. This series adds two new flags to extend the abilities of close_range(): (1) CLOSE_RANGE_EXCEPT While regular close_range() operates on all file descriptors in the range [fd, max_fd] and not on any others, CLOSE_RANGE_EXCEPT makes close_range() operate on all file descriptors outside of the range. When combined with CLOSE_RANGE_UNSHARE dup_fd() never takes a reference on what is dropped. A task between clone(CLONE_FILES | CLONE_VM | CLONE_VFORK) and execve() that has the descriptors for the child in one window can shed the rest of the shared table in one call: close_range(lo, hi, CLOSE_RANGE_UNSHARE | CLOSE_RANGE_EXCEPT) Nothing outside of the window is referenced by the child at any point. (2) CLOSE_RANGE_CLOEXEC_ONLY closes the close-on-exec file descriptors in the range Whatever the caller deliberately passes down, stdio, LISTEN_FDS, an inherited pipe, remains where it is. The handful of close-on-exec descriptors the caller still needs for the exec such as the executable, an error pipe, can sit in a specific range. A task between clone(CLONE_FILES) and execve() may do: clone(CLONE_FILES | CLONE_VM | CLONE_VFORK) child: close_range(lo, hi, CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC_ONLY | CLOSE_RANGE_EXCEPT) child: rearrange descriptors in the now private table child: execve() Between the clone and the close_range() the child holds no reference of its own on any file because copy_files() only bumps the fdtable refcount. So a close() in the parent takes effect immediately. The unshare also never takes a reference on the fds it leaves behind either. * patches from https://patch.msgid.link/20260921-work-file-close_range_except-v1-0-c20d0b49270d@kernel.org: selftests/core: test CLOSE_RANGE_CLOEXEC_ONLY file: add CLOSE_RANGE_CLOEXEC_ONLY file: let dup_fd() drop only close-on-exec descriptors selftests/core: test CLOSE_RANGE_EXCEPT file: add CLOSE_RANGE_EXCEPT close_range: turn the flags into an enum file: let dup_fd() drop everything outside of the range file: rename dup_fd()'s punch_hole to range selftests/core: test the hole CLOSE_RANGE_UNSHARE leaves behind file: let dup_fd() leave the punched hole behind Link: https://patch.msgid.link/20260921-work-file-close_range_except-v1-0-c20d0b49270d@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'include/uapi')
-rw-r--r--include/uapi/linux/close_range.h31
1 files changed, 27 insertions, 4 deletions
diff --git a/include/uapi/linux/close_range.h b/include/uapi/linux/close_range.h
index 2d804281554c..7da9ed95258a 100644
--- a/include/uapi/linux/close_range.h
+++ b/include/uapi/linux/close_range.h
@@ -2,11 +2,34 @@
#ifndef _UAPI_LINUX_CLOSE_RANGE_H
#define _UAPI_LINUX_CLOSE_RANGE_H
-/* Unshare the file descriptor table before closing file descriptors. */
-#define CLOSE_RANGE_UNSHARE (1U << 1)
+/*
+ * A macro of one of these names defined before this header is parsed, by
+ * a libc or by a program's own fallback, would replace the enumerator.
+ */
+#undef CLOSE_RANGE_UNSHARE
+#undef CLOSE_RANGE_CLOEXEC
+#undef CLOSE_RANGE_EXCEPT
+#undef CLOSE_RANGE_CLOEXEC_ONLY
-/* Set the FD_CLOEXEC bit instead of closing the file descriptor. */
-#define CLOSE_RANGE_CLOEXEC (1U << 2)
+enum close_range_flags {
+ /* Unshare the file descriptor table before closing file descriptors. */
+ CLOSE_RANGE_UNSHARE = (1U << 1),
+
+ /* Set the FD_CLOEXEC bit instead of closing the file descriptor. */
+ CLOSE_RANGE_CLOEXEC = (1U << 2),
+
+ /* Act on every file descriptor outside of the given range instead. */
+ CLOSE_RANGE_EXCEPT = (1U << 3),
+
+ /* Only close file descriptors that have the FD_CLOEXEC bit set. */
+ CLOSE_RANGE_CLOEXEC_ONLY = (1U << 4),
+};
+
+/* Keep #ifdef working and let glibc skip its own definitions. */
+#define CLOSE_RANGE_UNSHARE CLOSE_RANGE_UNSHARE
+#define CLOSE_RANGE_CLOEXEC CLOSE_RANGE_CLOEXEC
+#define CLOSE_RANGE_EXCEPT CLOSE_RANGE_EXCEPT
+#define CLOSE_RANGE_CLOEXEC_ONLY CLOSE_RANGE_CLOEXEC_ONLY
#endif /* _UAPI_LINUX_CLOSE_RANGE_H */