linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC POC 00/50] file: handle files on syscall exit
@ 2026-09-15 11:30 Christian Brauner
  2026-09-15 11:30 ` [PATCH RFC POC 01/50] file: install " Christian Brauner
                   ` (51 more replies)
  0 siblings, 52 replies; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Hey,

The idea in this series is old-ish and really never let go of me and so
I wanted to at least dump it onto the list once even if it's just for
illustrative purposes.

I still had parts of an implementation laying around that I started
montsh ago alongside FD_PREPARE()/FD_ADD(). I sat down and finished it.

We've spoken about this idea a few times over the years that we could
reserve fds and files on a task and then install or a clean them up on
syscall success or error and get rid of most of the complicated cleanup
dance that we have in a lot of code. In particular drm. It last came up
during the Rust file descriptor reservation discussion quite some time
ago.

TL;DR, this lets arch code handle fd install and cleanup. fd_prepare()
allocates a descriptor like get_unused_fd_flags() does and records it in
a slot on the task. fd_stage() attaches the file to that slot and
returns the number.

When the syscall returns success the exit path installs every staged
file. When it returns an error it drops the descriptors and the files.

So a caller reserves, hands the number to userspace whenever it wants,
creates the file, stages it and returns errors without unwinding
anything.

fd_prepare() returns the slot itself, as a const pointer. The
preexisting fd_prepare_fd() and fd_prepare_file() give access to the fd
and file.

get_unused_fd_flags() and fd_install() don't change. A descriptor is
only reserved where a caller asks for it. And open(), dup() and all
other syscalls that maximize speed simply use FD_ADD().

The task keeps two slots inline. For SCM_RIGHTS and multi-descriptor
ioctls a spill array is added. It stick with the task.

Reservations belong to the thread and the syscall that made them. A
child of fork() starts without any. A thread can't unshare its fdtagble
with outstanding reservations. Kernel threads never return to userspace
so nothing would commit. Anything left at exit is a bug and gets warned
about and dropped.

Christian

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
Christian Brauner (50):
      file: install files on syscall exit
      entry: commit fds on syscall exit
      alpha: commit fds on syscall exit
      ARC: commit fds on syscall exit
      ARM: commit fds on syscall exit
      arm64: commit fds on syscall exit
      csky: commit fds on syscall exit
      hexagon: commit fds on syscall exit
      m68k: commit fds on syscall exit
      microblaze: commit fds on syscall exit
      MIPS: commit fds on syscall exit
      nios2: commit fds on syscall exit
      openrisc: commit fds on syscall exit
      parisc: commit fds on syscall exit
      sh: commit fds on syscall exit
      sparc: commit fds on syscall exit
      um: commit fds on syscall exit
      xtensa: commit fds on syscall exit
      file: require the syscall exit hook from every architecture
      file: warn when the descriptor table is unshared with slots
      io_uring: commit fds per request
      net: install SCM_RIGHTS descriptors when recvmsg() returns
      file: open-code receive_fd()'s immediate install
      file: make FD_ADD() a standalone immediate install
      file: reimplement FD_PREPARE() on the deferred fd_prepare() path
      dma-buf: stop unwinding sync file descriptors by hand
      drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install
      drm/msm: install the out-fence descriptor when the ioctl returns
      drm/virtio: install the out-fence descriptor when the ioctl returns
      drm/vmwgfx: install the out-fence descriptor when the ioctl returns
      vfio: install the migration data descriptor when the ioctl returns
      liveupdate: install the session descriptors when the ioctl returns
      io_uring/zcrx: install the exported descriptor when the request returns
      sctp: install the peeloff descriptor when the syscall returns
      ALSA: compress: install the task descriptors when the ioctl returns
      nitro_enclaves: install the enclave descriptor when the ioctl returns
      tpm: vtpm_proxy: install the server descriptor when the ioctl returns
      perf: stop putting the event descriptor back on failure
      seccomp: stop putting the listener descriptor back on failure
      KVM: stop putting descriptors back on failure
      KVM: guest_memfd: stop putting the descriptor back on failure
      drm: stop unwinding descriptors by hand
      drm/amdgpu: stop unwinding the fence descriptor by hand
      drm/etnaviv: install the out-fence descriptor when the ioctl returns
      accel/habanalabs: stop putting the dma-buf descriptor back on failure
      xen/gntdev-dmabuf: stop putting the descriptor back on failure
      iio: buffer: install the buffer descriptor when the ioctl returns
      misc: fastrpc: install the dma-buf descriptor when the ioctl returns
      iommufd: stop putting descriptors back on failure
      Drivers: hv: mshv: stop putting descriptors back on failure

 arch/alpha/include/asm/thread_info.h         |   2 +
 arch/alpha/kernel/entry.S                    |  24 ++-
 arch/alpha/kernel/ptrace.c                   |   3 +
 arch/arc/include/asm/thread_info.h           |   2 +
 arch/arc/kernel/entry.S                      |   5 +
 arch/arc/kernel/ptrace.c                     |   4 +
 arch/arm/include/asm/thread_info.h           |   2 +
 arch/arm/kernel/entry-common.S               |   2 +
 arch/arm/kernel/ptrace.c                     |   4 +
 arch/arm64/include/asm/thread_info.h         |   4 +-
 arch/arm64/kernel/ptrace.c                   |   4 +
 arch/csky/include/asm/thread_info.h          |   2 +
 arch/csky/kernel/entry.S                     |   9 +
 arch/csky/kernel/ptrace.c                    |   4 +
 arch/hexagon/include/asm/thread_info.h       |   2 +
 arch/hexagon/kernel/traps.c                  |   4 +
 arch/m68k/68000/entry.S                      |  10 ++
 arch/m68k/coldfire/entry.S                   |  12 ++
 arch/m68k/include/asm/thread_info.h          |   2 +
 arch/m68k/kernel/entry.S                     |   2 +
 arch/m68k/kernel/ptrace.c                    |   3 +
 arch/microblaze/include/asm/thread_info.h    |   5 +-
 arch/microblaze/kernel/ptrace.c              |   4 +
 arch/mips/include/asm/thread_info.h          |   5 +-
 arch/mips/kernel/ptrace.c                    |   4 +
 arch/nios2/include/asm/thread_info.h         |   2 +
 arch/nios2/kernel/entry.S                    |   5 +
 arch/nios2/kernel/ptrace.c                   |   3 +
 arch/openrisc/include/asm/thread_info.h      |   5 +-
 arch/openrisc/kernel/entry.S                 |   5 +-
 arch/openrisc/kernel/ptrace.c                |   4 +
 arch/parisc/include/asm/thread_info.h        |   2 +
 arch/parisc/kernel/entry.S                   |  12 ++
 arch/parisc/kernel/ptrace.c                  |   4 +
 arch/powerpc/platforms/cell/spufs/inode.c    |  12 +-
 arch/sh/include/asm/thread_info.h            |  10 +-
 arch/sh/kernel/entry-common.S                |   8 +-
 arch/sh/kernel/ptrace_32.c                   |   4 +
 arch/sparc/include/asm/thread_info_32.h      |   2 +
 arch/sparc/include/asm/thread_info_64.h      |   9 +-
 arch/sparc/kernel/entry.S                    |   2 +-
 arch/sparc/kernel/ptrace_32.c                |   4 +
 arch/sparc/kernel/ptrace_64.c                |   4 +
 arch/sparc/kernel/syscalls.S                 |   4 +-
 arch/um/include/asm/thread_info.h            |   2 +
 arch/um/kernel/ptrace.c                      |   4 +
 arch/xtensa/include/asm/thread_info.h        |   2 +
 arch/xtensa/kernel/entry.S                   |   5 +
 arch/xtensa/kernel/ptrace.c                  |   4 +
 drivers/accel/habanalabs/common/memory.c     |  13 +-
 drivers/char/tpm/tpm_vtpm_proxy.c            |  30 +---
 drivers/dma-buf/dma-buf.c                    |  33 ++--
 drivers/dma-buf/sw_sync.c                    |  40 ++---
 drivers/dma-buf/sync_file.c                  |  52 ++----
 drivers/gpio/gpiolib-cdev.c                  |  18 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c       |  16 +-
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c     |  67 ++------
 drivers/gpu/drm/drm_lease.c                  |  20 +--
 drivers/gpu/drm/drm_prime.c                  |  13 +-
 drivers/gpu/drm/drm_syncobj.c                |  44 ++---
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c |  14 +-
 drivers/gpu/drm/msm/msm_gem_submit.c         |  22 +--
 drivers/gpu/drm/msm/msm_gem_vma.c            |  22 +--
 drivers/gpu/drm/msm/msm_perfcntr.c           |   6 +-
 drivers/gpu/drm/virtio/virtgpu_submit.c      |  32 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c      |  29 ++--
 drivers/hv/mshv_root_main.c                  |  27 +--
 drivers/hv/mshv_vtl_main.c                   |  20 +--
 drivers/iio/industrialio-buffer.c            |  26 +--
 drivers/iommu/iommufd/eventq.c               |  39 ++---
 drivers/media/mc/mc-request.c                |   6 +-
 drivers/misc/fastrpc.c                       |  19 +--
 drivers/misc/ntsync.c                        |   6 +-
 drivers/vfio/vfio_main.c                     |  25 +--
 drivers/virt/nitro_enclaves/ne_misc_dev.c    |  33 ++--
 drivers/xen/gntdev-dmabuf.c                  |  14 +-
 fs/eventfd.c                                 |   6 +-
 fs/eventpoll.c                               |   6 +-
 fs/exec.c                                    |   3 +
 fs/file.c                                    | 245 +++++++++++++++++++++++++--
 fs/namespace.c                               |  12 +-
 fs/nsfs.c                                    |   6 +-
 fs/xfs/xfs_handle.c                          |   6 +-
 include/linux/entry-common.h                 |   8 +-
 include/linux/file.h                         | 160 +++++------------
 include/linux/sched.h                        |  21 +++
 include/linux/thread_info.h                  |   2 +
 io_uring/io_uring.c                          |  27 +++
 io_uring/mock_file.c                         |   5 +-
 io_uring/zcrx.c                              |  25 +--
 kernel/bpf/bpf_iter.c                        |   6 +-
 kernel/bpf/token.c                           |   6 +-
 kernel/events/core.c                         |  31 ++--
 kernel/exit.c                                |   1 +
 kernel/fork.c                                |   3 +
 kernel/liveupdate/luo_core.c                 |  48 ++----
 kernel/liveupdate/luo_session.c              |  24 +--
 kernel/seccomp.c                             |  13 +-
 mm/userfaultfd.c                             |   6 +-
 net/core/scm.c                               |  13 +-
 net/handshake/netlink.c                      |  20 ++-
 net/kcm/kcmsock.c                            |   5 +-
 net/sctp/socket.c                            |  78 ++++-----
 sound/core/compress_offload.c                |  24 ++-
 virt/kvm/guest_memfd.c                       |  20 +--
 virt/kvm/kvm_main.c                          |  65 +++----
 106 files changed, 962 insertions(+), 861 deletions(-)
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260915-work-fd-reserve-unify-folded-b89d3154b3d0


^ permalink raw reply	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 01/50] file: install files on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:55   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 02/50] entry: commit fds " Christian Brauner
                   ` (50 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

So we've spoken about this idea quite a few times over the years that
we could reserve fds and files on a task and then install or a clean
them up on syscall success or error and get rid of most of the
complicated cleanup dance that we have.

My original approach to this had been to implement FD_PREPARE() based on
cleanup guards and use scopes to make this happen. The other idea was
what I'm illustrating here. It is overall equally robust and makes the
install fd and file pattern work even if it there's a ton of cleanup or
setup work happening in the middle. This is particular evident in the
conversions of various dma/drm code later in the series.

So this lets the syscall path do the install. fd_prepare() allocates a
descriptor like get_unused_fd_flags() does and records it in a slot on
the task. fd_stage() attaches the file to that slot and returns the
number.

When the syscall returns success the exit path installs every staged
file. When it returns an error it drops the descriptors and the files.

So a caller reserves, hands the number to userspace whenever it wants,
creates the file, stages it and returns errors without unwinding
anything.

fd_prepare() returns the slot itself, as a const pointer. The
preexisting fd_prepare_fd() and fd_prepare_file() give access to the fd
and file.

get_unused_fd_flags() and fd_install() don't change. A descriptor is
only reserved where a caller asks for it. And open(), dup() and all
other syscalls that maximize speed simply use FD_ADD().

The task keeps two slots inline. For SCM_RIGHTS and multi-descriptor
ioctls a spill array is added. It stick with the task.

Reservations belong to the thread and the syscall that made them. A
child of fork() starts without any. A thread can't unshare its
fdtagble with outstanding reservations. Kernel threads never return to
userspace so nothing would commit. Anything left at exit is a bug and
gets warned about and dropped.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/file.c             | 203 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/file.h  |  37 +++++++--
 include/linux/sched.h |  21 ++++++
 kernel/exit.c         |   1 +
 kernel/fork.c         |   1 +
 5 files changed, 256 insertions(+), 7 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 628ca07dc4b1..90351241bb07 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -630,14 +630,215 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd)
 		files->next_fd = fd;
 }
 
-void put_unused_fd(unsigned int fd)
+/* Release @fd in the table, its slot is the caller's business. */
+static void fd_release(unsigned int fd)
 {
 	struct files_struct *files = current->files;
+
 	spin_lock(&files->file_lock);
 	__put_unused_fd(files, fd);
 	spin_unlock(&files->file_lock);
 }
 
+/* Enough for SCM_MAX_FD, and a page of slots on 4K pages. */
+#define FD_SLOTS_SPILL_MIN	256
+
+static struct fd_slot *fd_slot(struct fd_slots *slots, unsigned int idx)
+{
+	if (idx < FD_SLOTS_INLINE)
+		return &slots->inline_slots[idx];
+	return &slots->spill[idx - FD_SLOTS_INLINE];
+}
+
+/* Room for slot @idx in the spill array, doubling as it fills up. */
+static noinline struct fd_slot *fd_slots_spill(struct fd_slots *slots,
+					      unsigned int idx)
+{
+	unsigned int max = slots->spill_max;
+	struct fd_slot *spill;
+
+	idx -= FD_SLOTS_INLINE;
+	if (idx < max)
+		return &slots->spill[idx];
+
+	max = max ? max * 2 : FD_SLOTS_SPILL_MIN;
+	spill = kvrealloc(slots->spill, array_size(max, sizeof(*spill)),
+			  GFP_KERNEL_ACCOUNT);
+	if (!spill)
+		return NULL;
+	slots->spill = spill;
+	slots->spill_max = max;
+	return &spill[idx];
+}
+
+/* Record @fd in the next slot, returns the slot. */
+static struct fd_slot *fd_slot_record(int fd)
+{
+	struct fd_slots *slots = &current->fd_slots;
+	unsigned int idx = slots->nr;
+	struct fd_slot *slot;
+
+	/* Nothing would ever commit what a kernel thread prepares. */
+	VFS_WARN_ON_ONCE(current->flags & PF_KTHREAD);
+
+	if (likely(idx < FD_SLOTS_INLINE)) {
+		slot = &slots->inline_slots[idx];
+	} else {
+		slot = fd_slots_spill(slots, idx);
+		if (!slot)
+			return ERR_PTR(-ENOMEM);
+	}
+	ACCESS_PRIVATE(slot, fd) = fd;
+	ACCESS_PRIVATE(slot, file) = NULL;
+	slots->nr = idx + 1;
+	return slot;
+}
+
+/* The slot holding @fd, if this syscall prepared it. */
+static inline int fd_slot_find(struct fd_slots *slots, unsigned int fd)
+{
+	unsigned int idx = slots->nr;
+
+	while (idx--) {
+		if (ACCESS_PRIVATE(fd_slot(slots, idx), fd) == fd)
+			return idx;
+	}
+	return -1;
+}
+
+/**
+ * fd_prepare - allocate a descriptor that the syscall exit installs
+ * @flags: O_CLOEXEC or 0
+ *
+ * Returns the prepared slot as a const handle or an error pointer.
+ */
+const struct fd_slot *fd_prepare(unsigned flags)
+{
+	struct fd_slot *slot;
+	int fd;
+
+	fd = get_unused_fd_flags(flags);
+	if (fd < 0)
+		return ERR_PTR(fd);
+
+	slot = fd_slot_record(fd);
+	if (IS_ERR(slot))
+		fd_release(fd);
+	return slot;
+}
+EXPORT_SYMBOL(fd_prepare);
+
+/**
+ * fd_stage - attach the file to a prepared slot
+ * @slot: slot from fd_prepare()
+ * @file: the file to install, consumed
+ *
+ * Returns the number. The syscall exit installs @file there when the syscall
+ * returns success and drops it when the syscall returns an error.
+ */
+int fd_stage(const struct fd_slot *slot, struct file *file)
+{
+	struct fd_slot *s = (struct fd_slot *)slot;
+
+	VFS_WARN_ON_ONCE(ACCESS_PRIVATE(s, file));
+	ACCESS_PRIVATE(s, file) = file;
+	return ACCESS_PRIVATE(s, fd);
+}
+EXPORT_SYMBOL(fd_stage);
+
+/**
+ * __fd_slot_fd - the descriptor number of a prepared slot
+ * @slot: slot from fd_prepare()
+ */
+int __fd_slot_fd(const struct fd_slot *slot)
+{
+	return ACCESS_PRIVATE(slot, fd);
+}
+EXPORT_SYMBOL(__fd_slot_fd);
+
+/**
+ * __fd_slot_file - the file staged into a slot, to configure before install
+ * @slot: slot from fd_prepare()
+ *
+ * Returns the file handed to fd_stage(), or NULL before one is staged.
+ */
+struct file *__fd_slot_file(const struct fd_slot *slot)
+{
+	return ACCESS_PRIVATE(slot, file);
+}
+EXPORT_SYMBOL(__fd_slot_file);
+
+/* Install every staged file, release the slots that never got one. */
+static void fd_slots_install(struct fd_slots *slots)
+{
+	unsigned int idx;
+
+	for (idx = 0; idx < slots->nr; idx++) {
+		struct fd_slot *slot = fd_slot(slots, idx);
+
+		if (ACCESS_PRIVATE(slot, file))
+			fd_install(ACCESS_PRIVATE(slot, fd),
+				   ACCESS_PRIVATE(slot, file));
+		else
+			fd_release(ACCESS_PRIVATE(slot, fd));
+	}
+}
+
+/* Release every slot's descriptor and drop the staged files. */
+static void fd_slots_drop(struct fd_slots *slots)
+{
+	struct files_struct *files = current->files;
+	unsigned int idx;
+
+	spin_lock(&files->file_lock);
+	for (idx = 0; idx < slots->nr; idx++)
+		__put_unused_fd(files, ACCESS_PRIVATE(fd_slot(slots, idx), fd));
+	spin_unlock(&files->file_lock);
+	for (idx = 0; idx < slots->nr; idx++) {
+		struct fd_slot *slot = fd_slot(slots, idx);
+
+		if (ACCESS_PRIVATE(slot, file))
+			fput(ACCESS_PRIVATE(slot, file));
+	}
+}
+
+static __always_inline void fd_slots_finish(struct fd_slots *slots, bool failed)
+{
+	if (likely(!failed))
+		fd_slots_install(slots);
+	else
+		fd_slots_drop(slots);
+	slots->nr = 0;
+}
+
+/* Install or drop the prepared descriptors based on @ret. */
+void __fd_slots_commit(long ret)
+{
+	fd_slots_finish(&current->fd_slots, IS_ERR_VALUE(ret));
+}
+
+void exit_fd_slots(void)
+{
+	struct fd_slots *slots = &current->fd_slots;
+
+	/* A syscall must not exit with prepared descriptors outstanding. */
+	if (WARN_ON_ONCE(slots->nr))
+		fd_slots_finish(slots, true);
+	kvfree(slots->spill);
+}
+
+/**
+ * put_unused_fd - give a descriptor back before it got a file
+ * @fd: descriptor returned by get_unused_fd_flags()
+ *
+ * Not for a prepared descriptor, the syscall exit releases that one.
+ */
+void put_unused_fd(unsigned int fd)
+{
+	VFS_WARN_ON_ONCE(fd_slot_find(&current->fd_slots, fd) >= 0);
+	fd_release(fd);
+}
+
 EXPORT_SYMBOL(put_unused_fd);
 
 /*
diff --git a/include/linux/file.h b/include/linux/file.h
index 27484b444d31..fe2893eea945 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -91,6 +91,8 @@ extern bool get_close_on_exec(unsigned int fd);
 extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);
 extern int get_unused_fd_flags(unsigned flags);
 extern void put_unused_fd(unsigned int fd);
+void __fd_slots_commit(long ret);
+void exit_fd_slots(void);
 
 DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
 	     get_unused_fd_flags(flags), unsigned flags)
@@ -118,6 +120,12 @@ DEFINE_FREE(fput, struct file *, if (!IS_ERR_OR_NULL(_T)) fput(_T))
 
 extern void fd_install(unsigned int fd, struct file *file);
 
+struct fd_slot;
+const struct fd_slot *fd_prepare(unsigned flags);
+int fd_stage(const struct fd_slot *slot, struct file *file);
+int __fd_slot_fd(const struct fd_slot *slot);
+struct file *__fd_slot_file(const struct fd_slot *slot);
+
 int receive_fd(struct file *file, int __user *ufd, unsigned int o_flags);
 
 int receive_fd_replace(int new_fd, struct file *file, unsigned int o_flags);
@@ -148,15 +156,32 @@ struct fd_prepare {
 /* Typedef for fd_prepare cleanup guards. */
 typedef struct fd_prepare class_fd_prepare_t;
 
+/* Do not use directly. */
+static inline int __fd_prepare_fd_old(struct fd_prepare fdf)
+{
+	return fdf.__fd;
+}
+
+/* Do not use directly. */
+static inline struct file *__fd_prepare_file_old(struct fd_prepare fdf)
+{
+	return fdf.__file;
+}
+
 /*
- * Accessors for fd_prepare class members.
- * _Generic() is used for zero-cost type safety.
+ * Accessors for a prepared descriptor. _Generic() bridges struct fd_prepare
+ * (the cleanup class below) and struct fd_slot (fd_prepare()) while callers are
+ * converted; the struct fd_prepare arm goes away with FD_PREPARE().
  */
-#define fd_prepare_fd(_fdf) \
-	(_Generic((_fdf), struct fd_prepare: (_fdf).__fd))
+#define fd_prepare_fd(_x) _Generic((_x),				\
+	struct fd_prepare:	__fd_prepare_fd_old,			\
+	struct fd_slot *:	__fd_slot_fd,				\
+	const struct fd_slot *:	__fd_slot_fd)(_x)
 
-#define fd_prepare_file(_fdf) \
-	(_Generic((_fdf), struct fd_prepare: (_fdf).__file))
+#define fd_prepare_file(_x) _Generic((_x),				\
+	struct fd_prepare:	__fd_prepare_file_old,			\
+	struct fd_slot *:	__fd_slot_file,				\
+	const struct fd_slot *:	__fd_slot_file)(_x)
 
 /* Do not use directly. */
 static inline void class_fd_prepare_destructor(const struct fd_prepare *fdf)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8b3d47a325cc..52bbf9931908 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -832,6 +832,24 @@ struct task_ipi_mask {
 struct task_ipi_mask { };
 #endif
 
+/* Descriptors this syscall prepared, installed when it returns. */
+#define FD_SLOTS_INLINE	2
+
+struct file;
+
+struct fd_slot {
+	struct file			* __private file;
+	int				__private fd;
+};
+
+/* Inline up to FD_SLOTS_INLINE slots, the rest in the spill. */
+struct fd_slots {
+	unsigned int			nr;
+	unsigned int			spill_max;
+	struct fd_slot			*spill;
+	struct fd_slot			inline_slots[FD_SLOTS_INLINE];
+};
+
 struct task_struct {
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 	/*
@@ -1206,6 +1224,9 @@ struct task_struct {
 	/* Open file information: */
 	struct files_struct		*files;
 
+	/* Descriptors prepared by the current syscall: */
+	struct fd_slots			fd_slots;
+
 #ifdef CONFIG_IO_URING
 	struct io_uring_task		*io_uring;
 	struct io_restriction		*io_uring_restrict;
diff --git a/kernel/exit.c b/kernel/exit.c
index 97686af89501..ee108353a62c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1000,6 +1000,7 @@ void __noreturn do_exit(long code)
 
 	exit_sem(tsk);
 	exit_shm(tsk);
+	exit_fd_slots();
 	exit_files(tsk);
 	exit_fs(tsk);
 	if (group_dead)
diff --git a/kernel/fork.c b/kernel/fork.c
index 416758c8a3d4..59c5cfa3e482 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -980,6 +980,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 	tsk->btrace_seq = 0;
 #endif
 	tsk->splice_pipe = NULL;
+	memset(&tsk->fd_slots, 0, sizeof(tsk->fd_slots));
 	tsk->task_frag.page = NULL;
 	tsk->wake_q.next = NULL;
 	tsk->worker_private = NULL;

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 02/50] entry: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
  2026-09-15 11:30 ` [PATCH RFC POC 01/50] file: install " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:52   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 03/50] alpha: " Christian Brauner
                   ` (49 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Reserving a descriptor with fd_prepare() marks the task with
SYSCALL_WORK_FD_SLOTS. The syscall exit path already tests the
syscall work bits so a syscall that deferred nothing pays nothing new
and one that did takes the slow path. syscall_exit_work() commits the
reservations before audit and ptrace.

Architectures without the generic entry code grow TIF_FD_SLOTS bit in
their syscall exit work in the following patches.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/file.c                    | 24 ++++++++++++++++++++++++
 include/linux/entry-common.h |  8 +++++++-
 include/linux/file.h         |  2 ++
 include/linux/thread_info.h  |  2 ++
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/fs/file.c b/fs/file.c
index 90351241bb07..6fa481d63dcf 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -23,6 +23,7 @@
 #include <linux/file_ref.h>
 #include <net/sock.h>
 #include <linux/init_task.h>
+#include <asm/syscall.h>
 
 #include "internal.h"
 
@@ -643,6 +644,19 @@ static void fd_release(unsigned int fd)
 /* Enough for SCM_MAX_FD, and a page of slots on 4K pages. */
 #define FD_SLOTS_SPILL_MIN	256
 
+/* Make the syscall exit path call fd_slots_commit(). */
+#if defined(CONFIG_GENERIC_ENTRY)
+#define fd_slots_set_work()	set_syscall_work(FD_SLOTS)
+#define fd_slots_clear_work()	clear_syscall_work(FD_SLOTS)
+#elif defined(TIF_FD_SLOTS)
+#define fd_slots_set_work()	set_thread_flag(TIF_FD_SLOTS)
+#define fd_slots_clear_work()	clear_thread_flag(TIF_FD_SLOTS)
+#else
+/* Nothing commits until the architecture provides the flag. */
+#define fd_slots_set_work()	do { } while (0)
+#define fd_slots_clear_work()	do { } while (0)
+#endif
+
 static struct fd_slot *fd_slot(struct fd_slots *slots, unsigned int idx)
 {
 	if (idx < FD_SLOTS_INLINE)
@@ -690,6 +704,8 @@ static struct fd_slot *fd_slot_record(int fd)
 	}
 	ACCESS_PRIVATE(slot, fd) = fd;
 	ACCESS_PRIVATE(slot, file) = NULL;
+	if (!idx)
+		fd_slots_set_work();
 	slots->nr = idx + 1;
 	return slot;
 }
@@ -809,6 +825,14 @@ static __always_inline void fd_slots_finish(struct fd_slots *slots, bool failed)
 	else
 		fd_slots_drop(slots);
 	slots->nr = 0;
+	fd_slots_clear_work();
+}
+
+/* Syscall exit hook, keyed on the return value the caller will see. */
+void fd_slots_commit(struct pt_regs *regs)
+{
+	fd_slots_finish(&current->fd_slots,
+			syscall_get_error(current, regs) != 0);
 }
 
 /* Install or drop the prepared descriptors based on @ret. */
diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index 6574b7183c01..2da30e50cf59 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -3,6 +3,7 @@
 #define __LINUX_ENTRYCOMMON_H
 
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <linux/irq-entry-common.h>
 #include <linux/livepatch.h>
 #include <linux/ptrace.h>
@@ -36,7 +37,8 @@
 				 SYSCALL_WORK_SYSCALL_TRACE |		\
 				 SYSCALL_WORK_SYSCALL_AUDIT |		\
 				 SYSCALL_WORK_SYSCALL_USER_DISPATCH |	\
-				 SYSCALL_WORK_SYSCALL_EXIT_TRAP)
+				 SYSCALL_WORK_SYSCALL_EXIT_TRAP |	\
+				 SYSCALL_WORK_FD_SLOTS)
 
 /**
  * arch_ptrace_report_syscall_permit_entry - Architecture specific wrapper for
@@ -245,6 +247,10 @@ static __always_inline void syscall_exit_work(struct pt_regs *regs, unsigned lon
 {
 	bool step;
 
+	/* Install or drop the descriptors the syscall prepared. */
+	if (work & SYSCALL_WORK_FD_SLOTS)
+		fd_slots_commit(regs);
+
 	/*
 	 * If the syscall was rolled back due to syscall user dispatching,
 	 * then the tracers below are not invoked for the same reason as
diff --git a/include/linux/file.h b/include/linux/file.h
index fe2893eea945..04dd85cdd9bf 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -92,6 +92,8 @@ extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);
 extern int get_unused_fd_flags(unsigned flags);
 extern void put_unused_fd(unsigned int fd);
 void __fd_slots_commit(long ret);
+struct pt_regs;
+void fd_slots_commit(struct pt_regs *regs);
 void exit_fd_slots(void);
 
 DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 307b8390fc67..c80a87444286 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -47,6 +47,7 @@ enum syscall_work_bit {
 	SYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH,
 	SYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP,
 	SYSCALL_WORK_BIT_SYSCALL_RSEQ_SLICE,
+	SYSCALL_WORK_BIT_FD_SLOTS,
 };
 
 #define SYSCALL_WORK_SECCOMP			BIT(SYSCALL_WORK_BIT_SECCOMP)
@@ -57,6 +58,7 @@ enum syscall_work_bit {
 #define SYSCALL_WORK_SYSCALL_USER_DISPATCH	BIT(SYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH)
 #define SYSCALL_WORK_SYSCALL_EXIT_TRAP		BIT(SYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP)
 #define SYSCALL_WORK_SYSCALL_RSEQ_SLICE		BIT(SYSCALL_WORK_BIT_SYSCALL_RSEQ_SLICE)
+#define SYSCALL_WORK_FD_SLOTS			BIT(SYSCALL_WORK_BIT_FD_SLOTS)
 #endif
 
 #include <asm/thread_info.h>

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 03/50] alpha: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
  2026-09-15 11:30 ` [PATCH RFC POC 01/50] file: install " Christian Brauner
  2026-09-15 11:30 ` [PATCH RFC POC 02/50] entry: commit fds " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:50   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 04/50] ARC: " Christian Brauner
                   ` (48 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it once the untraced system call has stored
its result. A task that reserved descriptors calls syscall_trace_leave()
and joins ret_from_sys_call with the flag gone.

We mirror the traced error path where the switch stack is set up and the
return address and the syscall restart state are placed in callee-saved
registers.

Btw, let's remove alpha... It's a pain.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/alpha/include/asm/thread_info.h |  2 ++
 arch/alpha/kernel/entry.S            | 24 +++++++++++++++++++++++-
 arch/alpha/kernel/ptrace.c           |  3 +++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index 1552ecca8520..db8465f5fabb 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -67,6 +67,7 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
 #define TIF_NOTIFY_SIGNAL	5	/* signal notifications exist */
 #define TIF_SECCOMP		6	/* seccomp syscall filtering active */
 #define	TIF_SYSCALL_TRACEPOINT	7	/* syscall tracepoint instrumentation */
+#define TIF_FD_SLOTS		8	/* syscall prepared descriptors */
 #define TIF_DIE_IF_KERNEL	9	/* dik recursion lock */
 #define TIF_MEMDIE		13	/* is terminating due to OOM killer */
 #define TIF_POLLING_NRFLAG	14	/* idle is polling for TIF_NEED_RESCHED */
@@ -80,6 +81,7 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 
 /*
  * Work to do on syscall entry (in entry.S).
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 9f2608de2544..20372e926359 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -569,6 +569,13 @@ entSys:
 $ret_success:
 	stq	$0, 0($sp)
 	stq	$31, 72($sp)		/* a3=0 => no error */
+$syscall_exit:
+	/* Descriptors reserved by the syscall are committed in
+	   syscall_trace_leave, off the return path interrupts share.  */
+	ldl	$17, TI_FLAGS($8)
+	lda	$2, _TIF_FD_SLOTS
+	and	$17, $2, $2
+	bne	$2, $fd_slots_exit
 
 	.align	4
 	.globl	ret_from_sys_call
@@ -612,7 +619,7 @@ $syscall_error:
 	stq	$0, 0($sp)
 	mov	$31, $26	/* tell "ret_from_sys_call" we can restart */
 	stq	$1, 72($sp)	/* a3 for return */
-	br	ret_from_sys_call
+	br	$syscall_exit
 
 /*
  * Do all cleanup when returning from all interrupts and system calls.
@@ -648,6 +655,21 @@ $work_notifysig:
 	UNDO_SWITCH_STACK
 	br	restore_all
 
+	.align	4
+$fd_slots_exit:
+	/* Keep the return address and the syscall restart state in
+	   $26/$18/$19 across the call.  */
+	DO_SWITCH_STACK
+	mov	$26, $9
+	mov	$18, $10
+	mov	$19, $11
+	jsr	$26, syscall_trace_leave
+	mov	$9, $26
+	mov	$10, $18
+	mov	$11, $19
+	UNDO_SWITCH_STACK
+	br	ret_from_sys_call
+
 /*
  * PTRACE syscall handler
  */
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index fc8f6cedbb28..736218b34601 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -6,6 +6,7 @@
 /* more mutilation by David Mosberger (davidm@azstarnet.com) */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/mm.h>
@@ -507,6 +508,8 @@ asmlinkage unsigned long syscall_trace_enter(void)
 asmlinkage void
 syscall_trace_leave(void)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(current_pt_regs());
 	audit_syscall_exit(current_pt_regs());
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		ptrace_report_syscall_exit(current_pt_regs(), 0);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 04/50] ARC: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (2 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 03/50] alpha: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:48   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 05/50] ARM: " Christian Brauner
                   ` (47 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it on the untraced return from a system
call. A task that reserved descriptors takes the tracesys_exit path,
where syscall_trace_exit() commits them before the ptrace exit stop.
The traced path already ends up there.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/arc/include/asm/thread_info.h | 2 ++
 arch/arc/kernel/entry.S            | 5 +++++
 arch/arc/kernel/ptrace.c           | 4 ++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h
index 255d2c774219..4c67d4eb434b 100644
--- a/arch/arc/include/asm/thread_info.h
+++ b/arch/arc/include/asm/thread_info.h
@@ -77,6 +77,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
 #define TIF_NOTIFY_SIGNAL	5	/* signal notifications exist */
+#define TIF_FD_SLOTS		6	/* syscall prepared descriptors */
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		16
@@ -88,6 +89,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_NOTIFY_SIGNAL	(1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 #define _TIF_MEMDIE		(1<<TIF_MEMDIE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 3c7e74aba679..f436391526e1 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -241,6 +241,11 @@ ENTRY(EV_Trap)
 	jl      [r9]
 
 .Lret_from_system_call:
+	; descriptors reserved by the syscall are committed in syscall_trace_exit()
+	GET_CURR_THR_INFO_FLAGS   r10
+	and.f 0, r10, _TIF_FD_SLOTS
+	bnz   tracesys_exit
+
 	st  r0, [sp, PT_r0]     ; sys call return value in pt_regs
 
 	; fall through to ret_from_exception
diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c
index fe2b6572e919..0a0d74b9c7c4 100644
--- a/arch/arc/kernel/ptrace.c
+++ b/arch/arc/kernel/ptrace.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  */
 
+#include <linux/file.h>
 #include <linux/ptrace.h>
 #include <linux/sched/task_stack.h>
 #include <linux/regset.h>
@@ -355,6 +356,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		ptrace_report_syscall_exit(regs, 0);
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 05/50] ARM: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (3 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 04/50] ARC: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:59   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 06/50] arm64: " Christian Brauner
                   ` (46 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it where the syscall return path decides
between the syscall work and the plain work pending slow path. A task
that reserved descriptors goes through __sys_trace_return_nosave
where syscall_trace_exit() commits them before audit and the ptrace
exit stop. The traced path already ends up there.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/arm/include/asm/thread_info.h | 2 ++
 arch/arm/kernel/entry-common.S     | 2 ++
 arch/arm/kernel/ptrace.c           | 4 ++++
 3 files changed, 8 insertions(+)

diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 943ffcf069d2..5337449e8409 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -144,6 +144,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_UPROBE		3	/* breakpointed or singlestepping */
 #define TIF_NOTIFY_SIGNAL	4	/* signal notifications exist */
+#define TIF_FD_SLOTS		5	/* syscall prepared descriptors, entry-common.S needs it below 16 */
 
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
@@ -163,6 +164,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 
 /* Checks for any syscall work in entry-common.S */
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 88336a1292bb..59a70d90b0b6 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -83,6 +83,8 @@ ENDPROC(ret_fast_syscall)
 
 	tst	r1, #_TIF_SYSCALL_WORK
 	bne	__sys_trace_return_nosave
+	tst	r1, #(_TIF_FD_SLOTS << 16)	@ r1 holds TI_FLAGS << 16
+	bne	__sys_trace_return_nosave
 slow_work_pending:
 	mov	r0, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index ed7a2a87a670..75fe26012fcb 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -11,6 +11,7 @@
 #include <linux/sched/task_stack.h>
 #include <linux/mm.h>
 #include <linux/elf.h>
+#include <linux/file.h>
 #include <linux/smp.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -876,6 +877,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	/*
 	 * Audit the syscall before anything else, as a debugger may
 	 * come in and change the current registers.

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 06/50] arm64: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (4 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 05/50] ARM: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:48   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 07/50] csky: " Christian Brauner
                   ` (45 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS to the syscall work bits. el0_svc_common() rereads
the flags after the system call and takes the trace exit for any of
them. So a task that reserved descriptors ends up in
syscall_trace_exit() which commits them before audit and the ptrace exit
stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/arm64/include/asm/thread_info.h | 4 +++-
 arch/arm64/kernel/ptrace.c           | 4 ++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 5d7fe3e153c8..e48006eb98a8 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -74,6 +74,7 @@ void arch_setup_new_exec(void);
 #define TIF_SECCOMP		11	/* syscall secure computing */
 #define TIF_SYSCALL_EMU		12	/* syscall emulation active */
 #define TIF_PATCH_PENDING	13	/* pending live patching update */
+#define TIF_FD_SLOTS		14	/* syscall prepared descriptors */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
@@ -107,10 +108,11 @@ void arch_setup_new_exec(void);
 #define _TIF_MTE_ASYNC_FAULT	(1 << TIF_MTE_ASYNC_FAULT)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
 #define _TIF_TSC_SIGSEGV	(1 << TIF_TSC_SIGSEGV)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
-				 _TIF_SYSCALL_EMU)
+				 _TIF_SYSCALL_EMU | _TIF_FD_SLOTS)
 
 #ifdef CONFIG_SHADOW_CALL_STACK
 #define INIT_SCS							\
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index f743cbec1c3a..3bedfed977d4 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -28,6 +28,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/regset.h>
 #include <linux/elf.h>
+#include <linux/file.h>
 #include <linux/rseq.h>
 
 #include <asm/compat.h>
@@ -2486,6 +2487,9 @@ void syscall_trace_exit(struct pt_regs *regs)
 {
 	unsigned long flags = read_thread_flags();
 
+	if (flags & _TIF_FD_SLOTS)
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (flags & _TIF_SYSCALL_TRACEPOINT)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 07/50] csky: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (5 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 06/50] arm64: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:47   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 08/50] hexagon: " Christian Brauner
                   ` (44 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it after the untraced system call has
stored its return value. A task that reserved descriptors joins the
traced path, where syscall_trace_exit() commits them before audit and
the ptrace exit stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/csky/include/asm/thread_info.h | 2 ++
 arch/csky/kernel/entry.S            | 9 +++++++++
 arch/csky/kernel/ptrace.c           | 4 ++++
 3 files changed, 15 insertions(+)

diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h
index fdd4f8ad45ac..59109ce64695 100644
--- a/arch/csky/include/asm/thread_info.h
+++ b/arch/csky/include/asm/thread_info.h
@@ -61,6 +61,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACEPOINT	5       /* syscall tracepoint instrumentation */
 #define TIF_SYSCALL_AUDIT	6	/* syscall auditing */
 #define TIF_NOTIFY_SIGNAL	7	/* signal notifications exist */
+#define TIF_FD_SLOTS		8	/* syscall prepared descriptors */
 #define TIF_POLLING_NRFLAG	16	/* poll_idle() is TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	20	/* restore signal mask in do_signal() */
@@ -73,6 +74,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S
index 3261f46f2244..6ff3074b9787 100644
--- a/arch/csky/kernel/entry.S
+++ b/arch/csky/kernel/entry.S
@@ -80,6 +80,15 @@ ENTRY(csky_systemcall)
 	jsr     syscallid
 #endif
 	stw     a0, (sp, LSAVE_A0)      /* Save return value */
+	/* descriptors reserved by the syscall are committed in syscall_trace_exit() */
+	mov     r9, sp
+	bmaski  r10, THREAD_SHIFT
+	andn    r9, r10
+	ldw     r10, (r9, TINFO_FLAGS)
+	lrw	r9, _TIF_FD_SLOTS
+	and	r10, r9
+	cmpnei	r10, 0
+	bt      1f
 	jmpi    ret_from_exception
 
 csky_syscall_trace:
diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c
index ee2867a1576e..b19fef9d396d 100644
--- a/arch/csky/kernel/ptrace.c
+++ b/arch/csky/kernel/ptrace.c
@@ -4,6 +4,7 @@
 #include <linux/audit.h>
 #include <linux/elf.h>
 #include <linux/errno.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
@@ -335,6 +336,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE))

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 08/50] hexagon: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (6 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 07/50] csky: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:49   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 09/50] m68k: " Christian Brauner
                   ` (43 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it in do_trap0() once the system call has
returned, before the ptrace exit stop gets to see the result.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/hexagon/include/asm/thread_info.h | 2 ++
 arch/hexagon/kernel/traps.c            | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
index e90f280b9ce3..8558d2d147f8 100644
--- a/arch/hexagon/include/asm/thread_info.h
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -88,6 +88,7 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define TIF_SIGPENDING          2       /* signal pending */
 #define TIF_NEED_RESCHED        3       /* rescheduling necessary */
 #define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
+#define TIF_FD_SLOTS          5       /* syscall prepared descriptors */
 #define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
 #define TIF_NOTIFY_SIGNAL	7       /* signal notifications exist */
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
@@ -98,6 +99,7 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
+#define _TIF_FD_SLOTS         (1 << TIF_FD_SLOTS)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
 
 /* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
index 6fe0c1b62c1b..4d15c5212fd7 100644
--- a/arch/hexagon/kernel/traps.c
+++ b/arch/hexagon/kernel/traps.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/file.h>
 #include <linux/sched/signal.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
@@ -381,6 +382,9 @@ void do_trap0(struct pt_regs *regs)
 				   regs->r04, regs->r05);
 		}
 
+		if (unlikely(test_thread_flag(TIF_FD_SLOTS)))
+			fd_slots_commit(regs);
+
 		/* allow strace to get the syscall return state  */
 		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
 			ptrace_report_syscall_exit(regs, 0);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 09/50] m68k: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (7 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 08/50] hexagon: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:50   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 10/50] microblaze: " Christian Brauner
                   ` (42 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it on the untraced return from a system
call in all three entry paths. A task that reserved descriptors calls
syscall_trace_leave(), which commits them before the ptrace exit stop.
The traced paths already end up there.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/m68k/68000/entry.S             | 10 ++++++++++
 arch/m68k/coldfire/entry.S          | 12 ++++++++++++
 arch/m68k/include/asm/thread_info.h |  2 ++
 arch/m68k/kernel/entry.S            |  2 ++
 arch/m68k/kernel/ptrace.c           |  3 +++
 5 files changed, 29 insertions(+)

diff --git a/arch/m68k/68000/entry.S b/arch/m68k/68000/entry.S
index c257cc415c47..479032af2f2f 100644
--- a/arch/m68k/68000/entry.S
+++ b/arch/m68k/68000/entry.S
@@ -89,6 +89,16 @@ ENTRY(system_call)
 	jbsr	%a0@
 	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
 
+	/* descriptors reserved by the syscall are committed in syscall_trace_leave */
+	getthreadinfo
+	btst	#(TIF_FD_SLOTS%8),%a2@(TINFO_FLAGS+(31-TIF_FD_SLOTS)/8)
+	jeq	ret_from_exception
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_leave
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+
 ret_from_exception:
 	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
 	jeq	Luser_return		/* if so, skip resched, signals*/
diff --git a/arch/m68k/coldfire/entry.S b/arch/m68k/coldfire/entry.S
index 4ea08336e2fb..43e47d4c0018 100644
--- a/arch/m68k/coldfire/entry.S
+++ b/arch/m68k/coldfire/entry.S
@@ -78,6 +78,18 @@ ENTRY(system_call)
 	movel	%d3,%a0
 	jbsr	%a0@
 	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
+
+	/* descriptors reserved by the syscall are committed in syscall_trace_leave */
+	movel	%sp,%d2			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d2	/* at start of kernel stack */
+	movel	%d2,%a0
+	btst	#(TIF_FD_SLOTS%8),%a0@(TINFO_FLAGS+(31-TIF_FD_SLOTS)/8)
+	jeq	ret_from_exception
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_leave
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
 	jra	ret_from_exception
 1:
 	movel	#-ENOSYS,%d2		/* strace needs -ENOSYS in PT_OFF_D0 */
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index 5cb3ace55622..861b6f523bda 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -62,6 +62,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME	5	/* callback before returning to user */
 #define TIF_SIGPENDING		6	/* signal pending */
 #define TIF_NEED_RESCHED	7	/* rescheduling necessary */
+#define TIF_FD_SLOTS		12	/* syscall prepared descriptors */
 #define TIF_SECCOMP		13	/* seccomp syscall filtering active */
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
@@ -71,6 +72,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_DELAYED_TRACE	(1 << TIF_DELAYED_TRACE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 338b474910f7..9e4471f68165 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -229,6 +229,8 @@ ret_from_syscall:
 syscall_exit_work:
 	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
 	bnes	1b			| if so, skip resched, signals
+	btst	#4,%a1@(TINFO_FLAGS+2)	| TIF_FD_SLOTS: commit descriptors
+	jne	do_trace_exit
 	lslw	#1,%d0
 	jcs	do_trace_exit
 	jmi	do_delayed_trace
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 4575f6487a9a..07103e6ddeb0 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/mm.h>
@@ -289,6 +290,8 @@ asmlinkage int syscall_trace_enter(void)
 
 asmlinkage void syscall_trace_leave(void)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(task_pt_regs(current));
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		ptrace_report_syscall_exit(task_pt_regs(current), 0);
 }

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 10/50] microblaze: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (8 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 09/50] m68k: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:48   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 11/50] MIPS: " Christian Brauner
                   ` (41 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS to the syscall work mask. The return path rereads
the flags after the system call and calls do_syscall_trace_leave()
for any of them which commits the reservations before audit and the
ptrace exit stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/microblaze/include/asm/thread_info.h | 5 ++++-
 arch/microblaze/kernel/ptrace.c           | 4 ++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h
index 0153f7c2717c..ee2f76589696 100644
--- a/arch/microblaze/include/asm/thread_info.h
+++ b/arch/microblaze/include/asm/thread_info.h
@@ -103,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SINGLESTEP		4
 #define TIF_NOTIFY_SIGNAL	5	/* signal notifications exist */
 #define TIF_MEMDIE		6	/* is terminating due to OOM killer */
+#define TIF_FD_SLOTS		7	/* syscall prepared descriptors */
 #define TIF_SYSCALL_AUDIT	9       /* syscall auditing active */
 #define TIF_SECCOMP		10      /* secure computing */
 
@@ -118,10 +119,12 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK  (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
-				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
+				 _TIF_FD_SLOTS)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		0x0000FFFE
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 236264e932d6..e6951fea8593 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
@@ -156,6 +157,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
 	int step;
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	step = test_thread_flag(TIF_SINGLESTEP);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 11/50] MIPS: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (9 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 10/50] microblaze: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:45   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 12/50] nios2: " Christian Brauner
                   ` (40 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS to the syscall exit work. The return path rereads
the flags after the system call and calls syscall_trace_leave() for
any of the exit work bits which commits the reservations before audit
and the ptrace exit stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/mips/include/asm/thread_info.h | 5 ++++-
 arch/mips/kernel/ptrace.c           | 4 ++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 2707dad260dd..79c81696e9c1 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -114,6 +114,7 @@ register unsigned long current_stack_pointer __asm__("sp");
 #define TIF_NOTIFY_RESUME	5	/* callback before returning to user */
 #define TIF_UPROBE		6	/* breakpointed or singlestepping */
 #define TIF_NOTIFY_SIGNAL	7	/* signal notifications exist */
+#define TIF_FD_SLOTS		8	/* syscall prepared descriptors */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
@@ -152,6 +153,7 @@ register unsigned long current_stack_pointer __asm__("sp");
 #define _TIF_USEDMSA		(1<<TIF_USEDMSA)
 #define _TIF_MSA_CTX_LIVE	(1<<TIF_MSA_CTX_LIVE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 
 #define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
 				 _TIF_SYSCALL_AUDIT | \
@@ -159,7 +161,8 @@ register unsigned long current_stack_pointer __asm__("sp");
 
 /* work to do in syscall_trace_leave() */
 #define _TIF_WORK_SYSCALL_EXIT	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
+				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT | \
+				 _TIF_FD_SLOTS)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		\
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 17dc7249b8ca..d68eab59bcc2 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -17,6 +17,7 @@
 #include <linux/compiler.h>
 #include <linux/context_tracking.h>
 #include <linux/elf.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
@@ -1364,6 +1365,9 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 	 */
 	user_exit();
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 12/50] nios2: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (10 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 11/50] MIPS: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 11:54   ` sashiko-bot
  2026-09-15 11:30 ` [PATCH RFC POC 13/50] openrisc: " Christian Brauner
                   ` (39 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it once the untraced system call has had
its return code translated into the r2 and r7 pair userspace sees.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/nios2/include/asm/thread_info.h | 2 ++
 arch/nios2/kernel/entry.S            | 5 +++++
 arch/nios2/kernel/ptrace.c           | 3 +++
 3 files changed, 10 insertions(+)

diff --git a/arch/nios2/include/asm/thread_info.h b/arch/nios2/include/asm/thread_info.h
index 83df79286d62..7f5816e1b3d6 100644
--- a/arch/nios2/include/asm/thread_info.h
+++ b/arch/nios2/include/asm/thread_info.h
@@ -78,6 +78,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SECCOMP		5	/* secure computing */
 #define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
 #define TIF_NOTIFY_SIGNAL	7	/* signal notifications exist */
+#define TIF_FD_SLOTS		8	/* syscall prepared descriptors */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
@@ -90,6 +91,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S
index dd40dfd908e5..b3a99a6db379 100644
--- a/arch/nios2/kernel/entry.S
+++ b/arch/nios2/kernel/entry.S
@@ -222,6 +222,11 @@ translate_rc_and_ret:
 	stw	r2, PT_R2(sp)
 	stw	r1, PT_R7(sp)
 end_translate_rc_and_ret:
+	/* Descriptors reserved by the syscall are committed in
+	 * do_syscall_trace_exit, take the traced exit path for them. */
+	GET_THREAD_INFO r11
+	ldw	r11, TI_FLAGS(r11)
+	BTBNZ	r11, r11, TIF_FD_SLOTS, end_translate_rc_and_ret2
 
 ret_from_exception:
 	ldw	r1, PT_ESTATUS(sp)
diff --git a/arch/nios2/kernel/ptrace.c b/arch/nios2/kernel/ptrace.c
index 2cd7e1ecbd74..5cee1b717662 100644
--- a/arch/nios2/kernel/ptrace.c
+++ b/arch/nios2/kernel/ptrace.c
@@ -9,6 +9,7 @@
 
 #include <linux/elf.h>
 #include <linux/errno.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
@@ -140,6 +141,8 @@ asmlinkage int do_syscall_trace_enter(void)
 
 asmlinkage void do_syscall_trace_exit(void)
 {
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(task_pt_regs(current));
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		ptrace_report_syscall_exit(task_pt_regs(current), 0);
 }

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 13/50] openrisc: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (11 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 12/50] nios2: " Christian Brauner
@ 2026-09-15 11:30 ` Christian Brauner
  2026-09-15 12:02   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 14/50] parisc: " Christian Brauner
                   ` (38 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it together with TIF_SYSCALL_TRACE on the
way out of a system call. The check used to rely on the flags r30 had
been loaded with before the call. Reload them. The syscall may have set
the new bit. A task that reserved descriptors calls
do_syscall_trace_leave() which commits them before audit and the ptrace
exit stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/openrisc/include/asm/thread_info.h | 5 ++++-
 arch/openrisc/kernel/entry.S            | 5 +++--
 arch/openrisc/kernel/ptrace.c           | 4 ++++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
index e338fff7efb0..3d8a710a809d 100644
--- a/arch/openrisc/include/asm/thread_info.h
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -92,6 +92,7 @@ register struct thread_info *current_thread_info_reg asm("r10");
 					 * mode
 					 */
 #define TIF_NOTIFY_SIGNAL	5	/* signal notifications exist */
+#define TIF_FD_SLOTS		6	/* syscall prepared descriptors */
 #define TIF_SYSCALL_TRACEPOINT  8       /* for ftrace syscall instrumentation */
 #define TIF_RESTORE_SIGMASK     9
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling						 * TIF_NEED_RESCHED
@@ -104,12 +105,14 @@ register struct thread_info *current_thread_info_reg asm("r10");
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_NOTIFY_SIGNAL	(1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 
 /* Work to do when returning from interrupt/exception */
 /* For OpenRISC, this is anything in the LSW other than syscall trace */
-#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
+#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP| \
+				 _TIF_FD_SLOTS))
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index 18e68680471e..c70265c4fe55 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -701,10 +701,11 @@ _syscall_show_regs:
 #endif
 
 _syscall_check_trace_leave:
-	/* r30 is a callee-saved register so this should still hold the
-	 * _TIF_SYSCALL_TRACE flag from _syscall_check_trace_enter above...
+	/* Reload the flags, the syscall may have set TIF_FD_SLOTS.
 	 * _syscall_trace_leave expects syscall result to be in pt_regs->r11.
 	 */
+	l.lwz	r30,TI_FLAGS(r10)
+	l.andi	r30,r30,(_TIF_SYSCALL_TRACE|_TIF_FD_SLOTS)
 	l.sfne	r30,r0
 	l.bf	_syscall_trace_leave
 	 l.nop
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
index 287a9718f0c6..71614b36e516 100644
--- a/arch/openrisc/kernel/ptrace.c
+++ b/arch/openrisc/kernel/ptrace.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/string.h>
@@ -311,6 +312,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
 	int step;
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	step = test_thread_flag(TIF_SINGLESTEP);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 14/50] parisc: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (12 preceding siblings ...)
  2026-09-15 11:30 ` [PATCH RFC POC 13/50] openrisc: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 11:59   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 15/50] sh: " Christian Brauner
                   ` (37 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it in syscall_exit once the return value
has been saved to pt_regs. A task that reserved descriptors calls
do_syscall_trace_exit() and then continues with the usual reschedule and
signal checks. The traced path already ends up there.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/parisc/include/asm/thread_info.h |  2 ++
 arch/parisc/kernel/entry.S            | 12 ++++++++++++
 arch/parisc/kernel/ptrace.c           |  4 ++++
 3 files changed, 18 insertions(+)

diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h
index b283738bb6da..14a40c53689f 100644
--- a/arch/parisc/include/asm/thread_info.h
+++ b/arch/parisc/include/asm/thread_info.h
@@ -52,6 +52,7 @@ struct thread_info {
 #define TIF_SECCOMP		11	/* secure computing */
 #define TIF_SYSCALL_TRACEPOINT	12	/* syscall tracepoint instrumentation */
 #define TIF_NONBLOCK_WARNING	13	/* warned about wrong O_NONBLOCK usage */
+#define TIF_FD_SLOTS		14	/* syscall prepared descriptors */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -65,6 +66,7 @@ struct thread_info {
 #define _TIF_BLOCKSTEP		(1 << TIF_BLOCKSTEP)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED | _TIF_NOTIFY_SIGNAL)
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index e04c5d806c10..c5807cf6fbd8 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1732,6 +1732,8 @@ syscall_check_resched:
 	/* check for reschedule */
 	mfctl	%cr30,%r19
 	LDREG	TASK_TI_FLAGS(%r19),%r19	/* long */
+	/* descriptors reserved by the syscall are committed in do_syscall_trace_exit */
+	bb,<,n	%r19, 31-TIF_FD_SLOTS, syscall_do_fd_slots /* forward */
 	bb,<,n	%r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
 
 	.import do_signal,code
@@ -1765,6 +1767,16 @@ syscall_do_signal:
 
 	b,n     syscall_check_sig
 
+syscall_do_fd_slots:
+	mfctl	%cr30,%r1
+#ifdef CONFIG_64BIT
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#endif
+	ldo	TASK_REGS(%r1),%r26		/* struct pt_regs *regs */
+	BL	do_syscall_trace_exit,%r2
+	nop
+	b,n	syscall_check_resched
+
 syscall_restore:
 	mfctl	%cr30,%r1
 
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 1d9e210702e1..f142766792af 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -381,6 +382,9 @@ void do_syscall_trace_exit(struct pt_regs *regs)
 	int stepping = test_thread_flag(TIF_SINGLESTEP) ||
 		test_thread_flag(TIF_BLOCKSTEP);
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 15/50] sh: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (13 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 14/50] parisc: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 11:55   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 16/50] sparc: " Christian Brauner
                   ` (36 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS to the syscall work mask. syscall_exit rereads the
flags after the system call and goes to syscall_exit_work for any bit
in the all-work mask, but hands over a copy shifted right by eight
when the bit was in the upper byte. Reload the flags there and test
the full mask, so that the bit reaches do_syscall_trace_leave().

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/sh/include/asm/thread_info.h | 10 +++++++---
 arch/sh/kernel/entry-common.S     |  8 ++++++--
 arch/sh/kernel/ptrace_32.c        |  4 ++++
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index 471db5173036..d976cf21f346 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -106,6 +106,7 @@ extern void init_thread_xstate(void);
 #define TIF_SECCOMP		6	/* secure computing */
 #define TIF_NOTIFY_RESUME	7	/* callback before returning to user */
 #define TIF_SYSCALL_TRACEPOINT	8	/* for ftrace syscall instrumentation */
+#define TIF_FD_SLOTS		9	/* syscall prepared descriptors */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 
@@ -118,22 +119,25 @@ extern void init_thread_xstate(void);
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK	(_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
 				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP    | \
-				 _TIF_SYSCALL_TRACEPOINT)
+				 _TIF_SYSCALL_TRACEPOINT | _TIF_FD_SLOTS)
 
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	(_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
 				 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
 				 _TIF_SINGLESTEP    | _TIF_NOTIFY_RESUME   | \
-				 _TIF_SYSCALL_TRACEPOINT | _TIF_NOTIFY_SIGNAL)
+				 _TIF_SYSCALL_TRACEPOINT | _TIF_NOTIFY_SIGNAL | \
+				 _TIF_FD_SLOTS)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		(_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
-				 _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP))
+				 _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \
+				 _TIF_FD_SLOTS))
 
 /*
  * Thread-synchronous status.
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index 91ab2607a1ff..593a482e85f5 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -164,9 +164,13 @@ work_resched:
 
 	.align	2
 syscall_exit_work:
-	! r0: current_thread_info->flags
 	! r8: current_thread_info
-	tst	#(_TIF_WORK_SYSCALL_MASK & 0xff), r0
+	mov.l	@(TI_FLAGS,r8), r0		! current_thread_info->flags
+	mov	#(_TIF_WORK_SYSCALL_MASK & 0xff), r1
+	mov	#(_TIF_WORK_SYSCALL_MASK >> 8), r2
+	shll8	r2
+	or	r2, r1
+	tst	r1, r0
 	bt/s	work_pending
 	 tst	#_TIF_NEED_RESCHED, r0
 	TRACE_IRQS_ON
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 8794081483fb..3deadd71f464 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -8,6 +8,7 @@
  * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  */
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/mm.h>
@@ -476,6 +477,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
 {
 	int step;
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 16/50] sparc: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (14 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 15/50] sh: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 11:57   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 17/50] um: " Christian Brauner
                   ` (35 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it together with the other syscall exit
work on the way out of a system call. A task that reserved
descriptors calls syscall_trace() on sparc32 and syscall_trace_leave()
on sparc64.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/sparc/include/asm/thread_info_32.h | 2 ++
 arch/sparc/include/asm/thread_info_64.h | 9 ++++++++-
 arch/sparc/kernel/entry.S               | 2 +-
 arch/sparc/kernel/ptrace_32.c           | 4 ++++
 arch/sparc/kernel/ptrace_64.c           | 4 ++++
 arch/sparc/kernel/syscalls.S            | 4 +++-
 6 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index fdaf7b171e0a..fbd7af6bb427 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -105,6 +105,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
 #define TIF_NOTIFY_SIGNAL	5	/* signal notifications exist */
+#define TIF_FD_SLOTS		6	/* syscall prepared descriptors */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -117,6 +118,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_SIGNAL	(1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index c8a73dff27f8..890ee65d9029 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -180,7 +180,7 @@ extern struct thread_info *current_thread_info(void);
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_NOTIFY_SIGNAL	4	/* signal notifications exist */
-#define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
+#define TIF_FD_SLOTS		5	/* syscall prepared descriptors */
 #define TIF_UPROBE		6	/* breakpointed or singlestepped */
 #define TIF_32BIT		7	/* 32-bit binary */
 #define TIF_NOHZ		8	/* in adaptive nohz mode */
@@ -194,12 +194,14 @@ extern struct thread_info *current_thread_info(void);
 #define TIF_MCDPER		12	/* Precise MCD exception */
 #define TIF_MEMDIE		13	/* is terminating due to OOM killer */
 #define TIF_POLLING_NRFLAG	14
+#define TIF_UNALIGNED		15	/* allowed to do unaligned accesses */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_SIGNAL	(1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
 #define _TIF_UPROBE		(1<<TIF_UPROBE)
 #define _TIF_32BIT		(1<<TIF_32BIT)
@@ -209,6 +211,11 @@ extern struct thread_info *current_thread_info(void);
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
+/* work to do in syscall_trace_leave() */
+#define _TIF_SYSCALL_EXIT_WORK	(_TIF_SYSCALL_TRACE | _TIF_SECCOMP | \
+				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT | \
+				 _TIF_NOHZ | _TIF_FD_SLOTS)
+
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
 				 _TIF_DO_NOTIFY_RESUME_MASK | \
 				 _TIF_NEED_RESCHED)
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index ea51ef52c952..d2023b84db9e 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1023,7 +1023,7 @@ ret_sys_call:
 	ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
 	set	PSR_C, %g2
 	bgeu	1f
-	 andcc	%l5, _TIF_SYSCALL_TRACE, %g0
+	 andcc	%l5, (_TIF_SYSCALL_TRACE | _TIF_FD_SLOTS), %g0
 
 	/* System call success, clear Carry condition code. */
 	andn	%g3, %g2, %g3
diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c
index 5991b1731fee..042e60685418 100644
--- a/arch/sparc/kernel/ptrace_32.c
+++ b/arch/sparc/kernel/ptrace_32.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
@@ -437,6 +438,9 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p)
 {
 	int ret = 0;
 
+	if (syscall_exit_p && test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 		if (syscall_exit_p)
 			ptrace_report_syscall_exit(regs, 0);
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 825ddf55fece..499b30c505fd 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/file.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/mm.h>
@@ -1110,6 +1111,9 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 	if (test_thread_flag(TIF_NOHZ))
 		user_exit();
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 96fe8763d70c..086fb8eaf133 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -269,10 +269,12 @@ ret_sys_call:
 	ldx	[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
 	mov	%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
 	sllx	%g2, 32, %g2
+	/* Reload the flags, the syscall may have set TIF_FD_SLOTS. */
+	ldx	[%g6 + TI_FLAGS], %l0
 
 	cmp	%o0, -ERESTART_RESTARTBLOCK
 	bgeu,pn	%xcc, 1f
-	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0
+	 andcc	%l0, _TIF_SYSCALL_EXIT_WORK, %g0
 	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 
 2:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 17/50] um: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (15 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 16/50] sparc: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 11:55   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 18/50] xtensa: " Christian Brauner
                   ` (34 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS. handle_syscall() calls syscall_trace_leave() after
every system call, so test the flag there and commit the reservations
before audit and the ptrace exit stop.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/um/include/asm/thread_info.h | 2 ++
 arch/um/kernel/ptrace.c           | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index 7a6f4dc99fa1..7140516ee0b6 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -44,6 +44,7 @@ struct thread_info {
 #define TIF_SECCOMP		9	/* secure computing */
 #define TIF_SINGLESTEP		10	/* single stepping userspace */
 #define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
+#define TIF_FD_SLOTS		12	/* syscall prepared descriptors */
 
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -55,6 +56,7 @@ struct thread_info {
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
+#define _TIF_FD_SLOTS		(1 << TIF_FD_SLOTS)
 
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \
 				 _TIF_NOTIFY_RESUME)
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 7da0a5223aa6..f1f89181fb7e 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
@@ -142,6 +143,9 @@ void syscall_trace_leave(struct pt_regs *regs)
 {
 	int ptraced = current->ptrace;
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	/* Fake a debug trap */

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 18/50] xtensa: commit fds on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (16 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 17/50] um: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:00   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture Christian Brauner
                   ` (33 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Add TIF_FD_SLOTS and test it once the system call has stored its
return value. A task that reserved descriptors uses the traced path.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/xtensa/include/asm/thread_info.h | 2 ++
 arch/xtensa/kernel/entry.S            | 5 +++++
 arch/xtensa/kernel/ptrace.c           | 4 ++++
 3 files changed, 11 insertions(+)

diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 5b74dfc35ef9..0c8eb5dc8398 100644
--- a/arch/xtensa/include/asm/thread_info.h
+++ b/arch/xtensa/include/asm/thread_info.h
@@ -124,6 +124,7 @@ static __always_inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
 #define TIF_SECCOMP		10	/* secure computing */
 #define TIF_MEMDIE		11	/* is terminating due to OOM killer */
+#define TIF_FD_SLOTS		12	/* syscall prepared descriptors */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -134,6 +135,7 @@ static __always_inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_FD_SLOTS		(1<<TIF_FD_SLOTS)
 
 #define _TIF_WORK_MASK		(_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
 				 _TIF_SYSCALL_TRACEPOINT | \
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 272fff587907..4b95f48736e6 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1976,6 +1976,11 @@ ENTRY(system_call)
 1:	/* regs->areg[2] = return_value */
 
 	s32i	abi_rv, abi_saved0, PT_AREG2
+
+	/* descriptors reserved by the syscall are committed in do_syscall_trace_leave */
+	GET_THREAD_INFO(a4, a1)
+	l32i	a4, a4, TI_FLAGS
+	bbsi.l	a4, TIF_FD_SLOTS, 1f
 	bnez	abi_saved1, 1f
 .Lsyscall_exit:
 #if defined(__XTENSA_WINDOWED_ABI__)
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 364e4fdabb00..d44d62a56b85 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <linux/errno.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/kernel.h>
@@ -571,6 +572,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
 {
 	int step;
 
+	if (test_thread_flag(TIF_FD_SLOTS))
+		fd_slots_commit(regs);
+
 	audit_syscall_exit(regs);
 
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (17 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 18/50] xtensa: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 11:54   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots Christian Brauner
                   ` (32 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Every architecture now either uses the generic entry code or provides
TIF_FD_SLOTS. The fallback that deferred without ever committing
can go. Make it a build error instead. A new architecture can't grow
fd_prepare() callers without the syscall exit hook.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/file.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 6fa481d63dcf..2b041b45f225 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -652,9 +652,7 @@ static void fd_release(unsigned int fd)
 #define fd_slots_set_work()	set_thread_flag(TIF_FD_SLOTS)
 #define fd_slots_clear_work()	clear_thread_flag(TIF_FD_SLOTS)
 #else
-/* Nothing commits until the architecture provides the flag. */
-#define fd_slots_set_work()	do { } while (0)
-#define fd_slots_clear_work()	do { } while (0)
+#error "the syscall exit path must commit prepared file descriptors"
 #endif
 
 static struct fd_slot *fd_slot(struct fd_slots *slots, unsigned int idx)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (18 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:02   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 21/50] io_uring: commit fds per request Christian Brauner
                   ` (31 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

If the fdtable is unshared or the task exits we can't install
reservations. The reserved fd isn't reserved anymore. execve() would
leak the reservation into the child.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/exec.c     | 3 +++
 kernel/fork.c | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 745f6eb5279e..1aa0f7b99fc3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1159,6 +1159,9 @@ int begin_new_exec(struct linux_binprm * bprm)
 	 */
 	io_uring_task_cancel();
 
+	/* A prepared descriptor would be installed into the new program. */
+	VFS_WARN_ON_ONCE(me->fd_slots.nr);
+
 	/* Ensure the files table is not shared. */
 	retval = unshare_files();
 	if (retval)
diff --git a/kernel/fork.c b/kernel/fork.c
index 59c5cfa3e482..bd0e1e85abb0 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -3217,6 +3217,8 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
 
 	if ((unshare_flags & CLONE_FILES) &&
 	    (fd && atomic_read(&fd->count) > 1)) {
+		/* Prepared descriptors live in the table we are about to leave. */
+		VFS_WARN_ON_ONCE(current->fd_slots.nr);
 		fd = dup_fd(fd, NULL);
 		if (IS_ERR(fd))
 			return PTR_ERR(fd);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 21/50] io_uring: commit fds per request
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (19 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:11   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns Christian Brauner
                   ` (30 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

io_uring requests don't complete on syscall exit of the task that
submitted them. They complete:

- inline from io_uring_enter()
- from task_work on any return to userspace
- from io-wq workers and from the SQPOLL thread

The CQEs are visible to other threads before any syscall returns. So
commit the reserved descriptors before the completion is posted. Commit
them after ->issue() based on the request's result and before every CQE
they post.

Nothing reachable from io_uring reserves yet. Once SCM_RIGHTS is
converted this keeps IORING_OP_RECVMSG working from io-wq workers and
the SQPOLL thread.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 io_uring/io_uring.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 61053421d809..001c3683bf00 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -870,6 +870,10 @@ bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags)
 	lockdep_assert(!io_wq_current_is_worker());
 	lockdep_assert_held(&ctx->uring_lock);
 
+	/* Descriptors this CQE reports must be installed before it is visible. */
+	if (unlikely(current->fd_slots.nr))
+		__fd_slots_commit(res);
+
 	if (!(ctx->int_flags & IO_RING_F_LOCKLESS_CQ)) {
 		spin_lock(&ctx->completion_lock);
 		posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags);
@@ -895,6 +899,8 @@ bool io_req_post_cqe32(struct io_kiocb *req, struct io_uring_cqe cqe[2])
 	lockdep_assert_held(&ctx->uring_lock);
 
 	cqe[0].user_data = req->cqe.user_data;
+	if (unlikely(current->fd_slots.nr))
+		__fd_slots_commit(cqe[0].res);
 	if (!(ctx->int_flags & IO_RING_F_LOCKLESS_CQ)) {
 		spin_lock(&ctx->completion_lock);
 		posted = io_fill_cqe_aux32(ctx, cqe);
@@ -1365,6 +1371,24 @@ static bool io_assign_file(struct io_kiocb *req, const struct io_issue_def *def,
 
 #define REQ_ISSUE_SLOW_FLAGS	(REQ_F_CREDS | REQ_F_ARM_LTIMEOUT)
 
+/*
+ * Requests complete from io_uring_enter(), task_work, io-wq workers and the
+ * SQPOLL thread, and their CQEs are visible before any syscall returns. So
+ * the descriptors a request reserved are committed per request, before its
+ * completion is posted.
+ */
+static void io_req_fd_reservations(struct io_kiocb *req, int ret)
+{
+	long res = ret;
+
+	/* A request holding reservations must not go async or be reissued. */
+	WARN_ON_ONCE(ret == IOU_ISSUE_SKIP_COMPLETE || ret == IOU_RETRY ||
+		     ret == IOU_REQUEUE);
+	if (ret == IOU_COMPLETE)
+		res = req->cqe.res;
+	__fd_slots_commit(res);
+}
+
 static inline int __io_issue_sqe(struct io_kiocb *req,
 				 unsigned int issue_flags,
 				 const struct io_issue_def *def)
@@ -1385,6 +1409,9 @@ static inline int __io_issue_sqe(struct io_kiocb *req,
 
 	ret = def->issue(req, issue_flags);
 
+	if (unlikely(current->fd_slots.nr))
+		io_req_fd_reservations(req, ret);
+
 	if (!def->audit_skip)
 		audit_uring_exit(!ret, ret);
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (20 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 21/50] io_uring: commit fds per request Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:03   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install Christian Brauner
                   ` (29 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

scm_recv_one_fd() allocates a descriptor, writes the number into the
control message and installs the file right there, one descriptor at a
time. Everything that recvmsg() does after scm_detach_fds() can still
fail though. When it does the syscall returns -EFAULT while the received
descriptors are already in the table and the caller has no way to tell.

Reserve the descriptor with fd_prepare() and stage the file with
fd_stage(). The number is written to userspace as before, but the file
is only installed when recvmsg() returns success and dropped together
with the descriptor when it returns an error.

A control message that doesn't fit still gets only the descriptors it
can report and MSG_CTRUNC.

IORING_OP_RECVMSG reaches the same code from io-wq workers and the
SQPOLL thread. io_uring requests commit their reservations before the
completion is posted.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 net/core/scm.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/net/core/scm.c b/net/core/scm.c
index f0d44ecdb11f..f05931eef54d 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -355,6 +355,7 @@ int scm_recv_one_fd(struct file *f, int __user *ufd, unsigned int flags,
 		    bool notrunc)
 {
 	int error;
+	const struct fd_slot *fd;
 
 	if (!ufd)
 		return -EFAULT;
@@ -363,16 +364,16 @@ int scm_recv_one_fd(struct file *f, int __user *ufd, unsigned int flags,
 	if (error)
 		return notrunc ? put_user(error, ufd) : error;
 
-	FD_PREPARE(fdf, flags, get_file(f));
-	if (fdf.err)
-		return fdf.err;
+	fd = fd_prepare(flags);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
-	error = put_user(fd_prepare_fd(fdf), ufd);
+	error = put_user(fd_prepare_fd(fd), ufd);
 	if (error)
 		return error;
 
-	__receive_sock(fd_prepare_file(fdf));
-	return fd_publish(fdf);
+	__receive_sock(f);
+	return fd_stage(fd, get_file(f));
 }
 
 void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm, bool notrunc)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (21 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:00   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 24/50] file: make FD_ADD() a standalone " Christian Brauner
                   ` (28 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

receive_fd() cannot defer to syscall exit as SECCOMP_IOCTL_NOTIF_ADDFD
installs into the target task and hands the number to the supervisor
and IORING_OP_FIXED_FD_INSTALL runs from an io_uring op. Open-code the
get_unused_fd_flags() + fd_install() it did through FD_PREPARE().

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/file.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/fs/file.c b/fs/file.c
index 2b041b45f225..1f06d0c846c2 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -1607,25 +1607,27 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
  */
 int receive_fd(struct file *file, int __user *ufd, unsigned int o_flags)
 {
-	int error;
+	int fd, error;
 
 	error = security_file_receive(file);
 	if (error)
 		return error;
 
-	FD_PREPARE(fdf, o_flags, file);
-	if (fdf.err)
-		return fdf.err;
-	get_file(file);
+	fd = get_unused_fd_flags(o_flags);
+	if (fd < 0)
+		return fd;
 
 	if (ufd) {
-		error = put_user(fd_prepare_fd(fdf), ufd);
-		if (error)
+		error = put_user(fd, ufd);
+		if (error) {
+			put_unused_fd(fd);
 			return error;
+		}
 	}
 
-	__receive_sock(fd_prepare_file(fdf));
-	return fd_publish(fdf);
+	__receive_sock(file);
+	fd_install(fd, get_file(file));
+	return fd;
 }
 EXPORT_SYMBOL_GPL(receive_fd);
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 24/50] file: make FD_ADD() a standalone immediate install
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (22 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:01   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path Christian Brauner
                   ` (27 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

FD_ADD() was built on FD_PREPARE() + fd_publish(). Give it its own small
macro that allocates the descriptor so it stays an immediate one-shot
for the hot descriptor-is-the-result paths (open, socket, accept, memfd
etc.).

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 include/linux/file.h | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/include/linux/file.h b/include/linux/file.h
index 04dd85cdd9bf..1ee7f058a882 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -259,24 +259,30 @@ static inline int class_fd_prepare_lock_err(const struct fd_prepare *fdf)
 		take_fd(fdp->__fd);                            \
 	})
 
-/* Do not use directly. */
-#define __FD_ADD(_fdf, _fd_flags, _file_owned)            \
-	({                                                \
-		FD_PREPARE(_fdf, _fd_flags, _file_owned); \
-		s32 ret = _fdf.err;                       \
-		if (likely(!ret))                         \
-			ret = fd_publish(_fdf);           \
-		ret;                                      \
-	})
-
 /*
- * FD_ADD - Allocate and install an fd and file in one step.
+ * FD_ADD - allocate a descriptor, build the file and install it in one step.
  * @_fd_flags: flags for get_unused_fd_flags()
- * @_file_owned: struct file to take ownership of
+ * @_file_owned: struct file to take ownership of (can be an expression)
  *
- * Returns the allocated fd number, or negative error code on failure.
+ * The file expression is evaluated only after the descriptor is allocated, so
+ * a full table does not run its side effects. Drops the file and returns a
+ * negative errno on failure. Installs immediately: for anything more than a
+ * bare install-and-return (reporting the number, configuring the file,
+ * installing several descriptors) use fd_prepare()/fd_stage().
  */
-#define FD_ADD(_fd_flags, _file_owned) \
-	__FD_ADD(__UNIQUE_ID(fd_prepare), _fd_flags, _file_owned)
+#define FD_ADD(_fd_flags, _file_owned)					\
+({									\
+	int __fd = get_unused_fd_flags(_fd_flags);			\
+	if (likely(__fd >= 0)) {					\
+		struct file *__file = (_file_owned);			\
+		if (unlikely(IS_ERR_OR_NULL(__file))) {			\
+			put_unused_fd(__fd);				\
+			__fd = __file ? PTR_ERR(__file) : -ENOMEM;	\
+		} else {						\
+			fd_install(__fd, __file);			\
+		}							\
+	}								\
+	__fd;								\
+})
 
 #endif /* __LINUX_FILE_H */

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (23 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 24/50] file: make FD_ADD() a standalone " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:05   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand Christian Brauner
                   ` (26 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

The FD_PREPARE() cleanup class allocated and installed immediately and
required fd_publish() to be the last thing that could fail. Reimplement
it on the deferred path. FD_PREPARE() reserves a slot with fd_prepare()
and stages the file on it. The syscall exit installs on success and
drops on error. fd_prepare_fd() and fd_prepare_file() now read the slot.
fd_publish() is gone.

Convert every FD_PREPARE() user since fdf.err can now become a simple
IS_ERR(fdf).

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 arch/powerpc/platforms/cell/spufs/inode.c |  12 +--
 drivers/gpio/gpiolib-cdev.c               |  18 ++--
 drivers/gpu/drm/msm/msm_perfcntr.c        |   6 +-
 drivers/media/mc/mc-request.c             |   6 +-
 drivers/misc/ntsync.c                     |   6 +-
 fs/eventfd.c                              |   6 +-
 fs/eventpoll.c                            |   6 +-
 fs/file.c                                 |  12 +--
 fs/namespace.c                            |  12 +--
 fs/nsfs.c                                 |   6 +-
 fs/xfs/xfs_handle.c                       |   6 +-
 include/linux/file.h                      | 143 ++++--------------------------
 io_uring/mock_file.c                      |   5 +-
 kernel/bpf/bpf_iter.c                     |   6 +-
 kernel/bpf/token.c                        |   6 +-
 mm/userfaultfd.c                          |   6 +-
 net/handshake/netlink.c                   |  20 +++--
 net/kcm/kcmsock.c                         |   5 +-
 18 files changed, 89 insertions(+), 198 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 2b54afb31529..b3e9204e7031 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -266,10 +266,10 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
 static int spufs_context_open(const struct path *path)
 {
 	FD_PREPARE(fdf, 0, dentry_open(path, O_RDONLY, current_cred()));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	fd_prepare_file(fdf)->f_op = &spufs_context_fops;
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 static struct spu_context *
@@ -499,10 +499,10 @@ static int spufs_gang_open(const struct path *path)
 	 * in error path of *_open().
 	 */
 	FD_PREPARE(fdf, 0, dentry_open(path, O_RDONLY, current_cred()));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	fd_prepare_file(fdf)->f_op = &spufs_gang_fops;
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 static int spufs_create_gang(struct inode *inode,
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 9f3b628d5793..4d138db25472 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -377,16 +377,14 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
 	FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
 		   anon_inode_getfile("gpio-linehandle", &linehandle_fileops,
 				      lh, O_RDONLY | O_CLOEXEC));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	retain_and_null_ptr(lh);
 
 	handlereq.fd = fd_prepare_fd(fdf);
 	if (copy_to_user(ip, &handlereq, sizeof(handlereq)))
 		return -EFAULT;
 
-	fd_publish(fdf);
-
 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
 		handlereq.lines);
 
@@ -1715,16 +1713,14 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
 	FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
 		   anon_inode_getfile("gpio-line", &line_fileops, lr,
 				      O_RDONLY | O_CLOEXEC));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	retain_and_null_ptr(lr);
 
 	ulr.fd = fd_prepare_fd(fdf);
 	if (copy_to_user(ip, &ulr, sizeof(ulr)))
 		return -EFAULT;
 
-	fd_publish(fdf);
-
 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
 		ulr.num_lines);
 
@@ -2115,16 +2111,14 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 	FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
 		   anon_inode_getfile("gpio-event", &lineevent_fileops, le,
 				      O_RDONLY | O_CLOEXEC));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	retain_and_null_ptr(le);
 
 	eventreq.fd = fd_prepare_fd(fdf);
 	if (copy_to_user(ip, &eventreq, sizeof(eventreq)))
 		return -EFAULT;
 
-	fd_publish(fdf);
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/msm_perfcntr.c b/drivers/gpu/drm/msm/msm_perfcntr.c
index ce65b1160955..65c067d39ca0 100644
--- a/drivers/gpu/drm/msm/msm_perfcntr.c
+++ b/drivers/gpu/drm/msm/msm_perfcntr.c
@@ -543,8 +543,8 @@ msm_ioctl_perfcntr_config(struct drm_device *dev, void *data, struct drm_file *f
 
 		FD_PREPARE(fdf, O_CLOEXEC,
 			   anon_inode_getfile("[msm_perfcntrs]", &stream_fops, stream, 0));
-		if (fdf.err)
-			return fdf.err;
+		if (IS_ERR(fdf))
+			return PTR_ERR(fdf);
 
 		INIT_WORK(&stream->sel_work, sel_worker);
 		kthread_init_work(&stream->sample_work, sample_worker);
@@ -564,7 +564,7 @@ msm_ioctl_perfcntr_config(struct drm_device *dev, void *data, struct drm_file *f
 
 		msm_perfcntr_resume_locked(perfcntrs->stream);
 
-		stream_fd = fd_publish(fdf);
+		stream_fd = fd_prepare_fd(fdf);
 	} else {
 		kfree(ctx->perfctx);
 		ctx->perfctx = no_free_ptr(perfctx);
diff --git a/drivers/media/mc/mc-request.c b/drivers/media/mc/mc-request.c
index 13e77648807c..c9296bdbee27 100644
--- a/drivers/media/mc/mc-request.c
+++ b/drivers/media/mc/mc-request.c
@@ -316,8 +316,8 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
 	FD_PREPARE(fdf, O_CLOEXEC,
 		   anon_inode_getfile("request", &request_fops, NULL,
 				      O_CLOEXEC));
-	if (fdf.err) {
-		ret = fdf.err;
+	if (IS_ERR(fdf)) {
+		ret = PTR_ERR(fdf);
 		goto err_free_req;
 	}
 
@@ -328,7 +328,7 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
 	atomic_inc(&mdev->num_requests);
 	dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);
 
-	*alloc_fd = fd_publish(fdf);
+	*alloc_fd = fd_prepare_fd(fdf);
 
 	return 0;
 
diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c
index 4a805919bb0c..721b0d9f0e1f 100644
--- a/drivers/misc/ntsync.c
+++ b/drivers/misc/ntsync.c
@@ -724,10 +724,10 @@ static int ntsync_obj_get_fd(struct ntsync_obj *obj)
 {
 	FD_PREPARE(fdf, O_CLOEXEC,
 		   anon_inode_getfile("ntsync", &ntsync_obj_fops, obj, O_RDWR));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 	obj->file = fd_prepare_file(fdf);
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp)
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 9d33a02757d5..a00fea879f9a 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -403,12 +403,12 @@ static int do_eventfd(unsigned int count, int flags)
 	FD_PREPARE(fdf, flags,
 		   anon_inode_getfile_fmode("[eventfd]", &eventfd_fops, ctx,
 					    flags, FMODE_NOWAIT));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	ctx->id = ida_alloc(&eventfd_ida, GFP_KERNEL);
 	retain_and_null_ptr(ctx);
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index e0c4bf88a838..81857725f810 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -2514,12 +2514,12 @@ static int do_epoll_create(int flags)
 	FD_PREPARE(fdf, O_RDWR | (flags & O_CLOEXEC),
 		   anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep,
 				      O_RDWR | (flags & O_CLOEXEC)));
-	if (fdf.err) {
+	if (IS_ERR(fdf)) {
 		ep_clear_and_put(ep);
-		return fdf.err;
+		return PTR_ERR(fdf);
 	}
 	ep->file = fd_prepare_file(fdf);
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 SYSCALL_DEFINE1(epoll_create1, int, flags)
diff --git a/fs/file.c b/fs/file.c
index 1f06d0c846c2..7c05246a5129 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -761,26 +761,26 @@ int fd_stage(const struct fd_slot *slot, struct file *file)
 EXPORT_SYMBOL(fd_stage);
 
 /**
- * __fd_slot_fd - the descriptor number of a prepared slot
+ * fd_prepare_fd - the descriptor number of a prepared slot
  * @slot: slot from fd_prepare()
  */
-int __fd_slot_fd(const struct fd_slot *slot)
+int fd_prepare_fd(const struct fd_slot *slot)
 {
 	return ACCESS_PRIVATE(slot, fd);
 }
-EXPORT_SYMBOL(__fd_slot_fd);
+EXPORT_SYMBOL(fd_prepare_fd);
 
 /**
- * __fd_slot_file - the file staged into a slot, to configure before install
+ * fd_prepare_file - the file staged into a slot, to configure before install
  * @slot: slot from fd_prepare()
  *
  * Returns the file handed to fd_stage(), or NULL before one is staged.
  */
-struct file *__fd_slot_file(const struct fd_slot *slot)
+struct file *fd_prepare_file(const struct fd_slot *slot)
 {
 	return ACCESS_PRIVATE(slot, file);
 }
-EXPORT_SYMBOL(__fd_slot_file);
+EXPORT_SYMBOL(fd_prepare_file);
 
 /* Install every staged file, release the slots that never got one. */
 static void fd_slots_install(struct fd_slots *slots)
diff --git a/fs/namespace.c b/fs/namespace.c
index 1ecd96c918b3..fba29bcc0164 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -4544,9 +4544,9 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
 
 	FD_PREPARE(fdf, (flags & FSMOUNT_CLOEXEC) ? O_CLOEXEC : 0,
 		   dentry_open(&new_path, O_PATH, fc->cred));
-	if (fdf.err) {
+	if (IS_ERR(fdf)) {
 		dissolve_on_fput(new_path.mnt);
-		return fdf.err;
+		return PTR_ERR(fdf);
 	}
 
 	/*
@@ -4554,7 +4554,7 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
 	 * need to unmount it, not just simply put it.
 	 */
 	fd_prepare_file(fdf)->f_mode |= FMODE_NEED_UNMOUNT;
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 static inline int vfs_move_mount(const struct path *from_path,
@@ -5198,8 +5198,8 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename,
 		return -EINVAL;
 
 	FD_PREPARE(fdf, flags, vfs_open_tree(dfd, filename, flags));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	if (uattr) {
 		struct mount_kattr kattr = {};
@@ -5220,7 +5220,7 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename,
 			return ret;
 	}
 
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 int show_path(struct seq_file *m, struct dentry *root)
diff --git a/fs/nsfs.c b/fs/nsfs.c
index c3b6ae76594a..da021c8b49b2 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -348,8 +348,8 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
 			return ret;
 
 		FD_PREPARE(fdf, O_CLOEXEC, dentry_open(&path, O_RDONLY, current_cred()));
-		if (fdf.err)
-			return fdf.err;
+		if (IS_ERR(fdf))
+			return PTR_ERR(fdf);
 		/*
 		 * If @uinfo is passed return all information about the
 		 * mount namespace as well.
@@ -357,7 +357,7 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
 		ret = copy_ns_info_to_user(to_mnt_ns(ns), uinfo, usize, &kinfo);
 		if (ret)
 			return ret;
-		ret = fd_publish(fdf);
+		ret = fd_prepare_fd(fdf);
 		break;
 	}
 	default:
diff --git a/fs/xfs/xfs_handle.c b/fs/xfs/xfs_handle.c
index 0689cade8f74..174aa3c8260f 100644
--- a/fs/xfs/xfs_handle.c
+++ b/fs/xfs/xfs_handle.c
@@ -272,8 +272,8 @@ xfs_open_by_handle(
 	path.mnt = mntget(parfilp->f_path.mnt);
 
 	FD_PREPARE(fdf, 0, dentry_open(&path, hreq->oflags, cred));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	if (S_ISREG(inode->i_mode)) {
 		struct file *filp = fd_prepare_file(fdf);
@@ -282,7 +282,7 @@ xfs_open_by_handle(
 		filp->f_mode |= FMODE_NOCMTIME;
 	}
 
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 int
diff --git a/include/linux/file.h b/include/linux/file.h
index 1ee7f058a882..45d68e097c05 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -125,8 +125,8 @@ extern void fd_install(unsigned int fd, struct file *file);
 struct fd_slot;
 const struct fd_slot *fd_prepare(unsigned flags);
 int fd_stage(const struct fd_slot *slot, struct file *file);
-int __fd_slot_fd(const struct fd_slot *slot);
-struct file *__fd_slot_file(const struct fd_slot *slot);
+int fd_prepare_fd(const struct fd_slot *slot);
+struct file *fd_prepare_file(const struct fd_slot *slot);
 
 int receive_fd(struct file *file, int __user *ufd, unsigned int o_flags);
 
@@ -137,128 +137,6 @@ extern void __fput_sync(struct file *);
 
 extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max;
 
-/*
- * fd_prepare: Combined fd + file allocation cleanup class.
- * @err: Error code to indicate if allocation succeeded.
- * @__fd: Allocated fd (may not be accessed directly)
- * @__file: Allocated struct file pointer (may not be accessed directly)
- *
- * Allocates an fd and a file together. On error paths, automatically cleans
- * up whichever resource was successfully allocated. Allows flexible file
- * allocation with different functions per usage.
- *
- * Do not use directly.
- */
-struct fd_prepare {
-	s32 err;
-	s32 __fd; /* do not access directly */
-	struct file *__file; /* do not access directly */
-};
-
-/* Typedef for fd_prepare cleanup guards. */
-typedef struct fd_prepare class_fd_prepare_t;
-
-/* Do not use directly. */
-static inline int __fd_prepare_fd_old(struct fd_prepare fdf)
-{
-	return fdf.__fd;
-}
-
-/* Do not use directly. */
-static inline struct file *__fd_prepare_file_old(struct fd_prepare fdf)
-{
-	return fdf.__file;
-}
-
-/*
- * Accessors for a prepared descriptor. _Generic() bridges struct fd_prepare
- * (the cleanup class below) and struct fd_slot (fd_prepare()) while callers are
- * converted; the struct fd_prepare arm goes away with FD_PREPARE().
- */
-#define fd_prepare_fd(_x) _Generic((_x),				\
-	struct fd_prepare:	__fd_prepare_fd_old,			\
-	struct fd_slot *:	__fd_slot_fd,				\
-	const struct fd_slot *:	__fd_slot_fd)(_x)
-
-#define fd_prepare_file(_x) _Generic((_x),				\
-	struct fd_prepare:	__fd_prepare_file_old,			\
-	struct fd_slot *:	__fd_slot_file,				\
-	const struct fd_slot *:	__fd_slot_file)(_x)
-
-/* Do not use directly. */
-static inline void class_fd_prepare_destructor(const struct fd_prepare *fdf)
-{
-	if (unlikely(fdf->__fd >= 0))
-		put_unused_fd(fdf->__fd);
-	if (unlikely(!IS_ERR_OR_NULL(fdf->__file)))
-		fput(fdf->__file);
-}
-
-/* Do not use directly. */
-static inline int class_fd_prepare_lock_err(const struct fd_prepare *fdf)
-{
-	if (unlikely(fdf->err))
-		return fdf->err;
-	if (unlikely(fdf->__fd < 0))
-		return fdf->__fd;
-	if (unlikely(IS_ERR(fdf->__file)))
-		return PTR_ERR(fdf->__file);
-	if (unlikely(!fdf->__file))
-		return -ENOMEM;
-	return 0;
-}
-
-/*
- * __FD_PREPARE_INIT - Helper to initialize fd_prepare class.
- * @_fd_flags: flags for get_unused_fd_flags()
- * @_file_owned: expression that returns struct file *
- *
- * Returns a struct fd_prepare with fd, file, and err set.
- * If fd allocation fails, fd will be negative and err will be set. If
- * fd succeeds but file_init_expr fails, file will be ERR_PTR and err
- * will be set. The err field is the single source of truth for error
- * checking.
- */
-#define __FD_PREPARE_INIT(_fd_flags, _file_owned)                 \
-	({                                                        \
-		struct fd_prepare fdf = {                         \
-			.__fd = get_unused_fd_flags((_fd_flags)), \
-		};                                                \
-		if (likely(fdf.__fd >= 0))                        \
-			fdf.__file = (_file_owned);               \
-		fdf.err = ACQUIRE_ERR(fd_prepare, &fdf);          \
-		fdf;                                              \
-	})
-
-/*
- * FD_PREPARE - Macro to declare and initialize an fd_prepare variable.
- *
- * Declares and initializes an fd_prepare variable with automatic
- * cleanup. No separate scope required - cleanup happens when variable
- * goes out of scope.
- *
- * @_fdf: name of struct fd_prepare variable to define
- * @_fd_flags: flags for get_unused_fd_flags()
- * @_file_owned: struct file to take ownership of (can be expression)
- */
-#define FD_PREPARE(_fdf, _fd_flags, _file_owned) \
-	CLASS_INIT(fd_prepare, _fdf, __FD_PREPARE_INIT(_fd_flags, _file_owned))
-
-/*
- * fd_publish - Publish prepared fd and file to the fd table.
- * @_fdf: struct fd_prepare variable
- */
-#define fd_publish(_fdf)                                       \
-	({                                                     \
-		struct fd_prepare *fdp = &(_fdf);              \
-		VFS_WARN_ON_ONCE(fdp->err);                    \
-		VFS_WARN_ON_ONCE(fdp->__fd < 0);               \
-		VFS_WARN_ON_ONCE(IS_ERR_OR_NULL(fdp->__file)); \
-		fd_install(fdp->__fd, fdp->__file);            \
-		retain_and_null_ptr(fdp->__file);              \
-		take_fd(fdp->__fd);                            \
-	})
-
 /*
  * FD_ADD - allocate a descriptor, build the file and install it in one step.
  * @_fd_flags: flags for get_unused_fd_flags()
@@ -285,4 +163,21 @@ static inline int class_fd_prepare_lock_err(const struct fd_prepare *fdf)
 	__fd;								\
 })
 
+/*
+ * FD_PREPARE - reserve a descriptor and stage @_file_owned on it for the
+ * install at syscall exit; declares @_fdf, an fd_prepare() slot.
+ * @_fdf: name of the const struct fd_slot * to declare
+ * @_fd_flags: flags for get_unused_fd_flags()
+ * @_file_owned: struct file to take ownership of (can be an expression)
+ */
+#define FD_PREPARE(_fdf, _fd_flags, _file_owned)			\
+	const struct fd_slot *_fdf = fd_prepare(_fd_flags);		\
+	if (!IS_ERR(_fdf)) {						\
+		struct file *__file = (_file_owned);			\
+		if (unlikely(IS_ERR_OR_NULL(__file)))			\
+			_fdf = __file ? ERR_CAST(__file) : ERR_PTR(-ENOMEM); \
+		else							\
+			fd_stage(_fdf, __file);				\
+	}
+
 #endif /* __LINUX_FILE_H */
diff --git a/io_uring/mock_file.c b/io_uring/mock_file.c
index b318ed697998..67164c28ed65 100644
--- a/io_uring/mock_file.c
+++ b/io_uring/mock_file.c
@@ -257,8 +257,8 @@ static int io_create_mock_file(struct io_uring_cmd *cmd, unsigned int issue_flag
 	FD_PREPARE(fdf, O_RDWR | O_CLOEXEC,
 		   anon_inode_create_getfile("[io_uring_mock]", fops, mf,
 					     O_RDWR | O_CLOEXEC, NULL));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	retain_and_null_ptr(mf);
 	file = fd_prepare_file(fdf);
@@ -271,7 +271,6 @@ static int io_create_mock_file(struct io_uring_cmd *cmd, unsigned int issue_flag
 	if (copy_to_user(uarg, &mc, uarg_size))
 		return -EFAULT;
 
-	fd_publish(fdf);
 	return 0;
 }
 
diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c
index 14a5fdfa0421..00edc394101b 100644
--- a/kernel/bpf/bpf_iter.c
+++ b/kernel/bpf/bpf_iter.c
@@ -643,15 +643,15 @@ int bpf_iter_new_fd(struct bpf_link *link)
 	flags = O_RDONLY | O_CLOEXEC;
 
 	FD_PREPARE(fdf, flags, anon_inode_getfile("bpf_iter", &bpf_iter_fops, NULL, flags));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	iter_link = container_of(link, struct bpf_iter_link, link);
 	err = prepare_seq_file(fd_prepare_file(fdf), iter_link);
 	if (err)
 		return err; /* Automatic cleanup handles fput */
 
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 struct bpf_prog *bpf_iter_get_info(struct bpf_iter_meta *meta, bool in_stop)
diff --git a/kernel/bpf/token.c b/kernel/bpf/token.c
index e85a179523f0..5cac7fc5694b 100644
--- a/kernel/bpf/token.c
+++ b/kernel/bpf/token.c
@@ -169,8 +169,8 @@ int bpf_token_create(union bpf_attr *attr)
 	FD_PREPARE(fdf, O_CLOEXEC,
 		   alloc_file_pseudo(inode, path.mnt, BPF_TOKEN_INODE_NAME,
 				     O_RDWR, &bpf_token_fops));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	token = kzalloc_obj(*token, GFP_USER);
 	if (!token)
@@ -191,7 +191,7 @@ int bpf_token_create(union bpf_attr *attr)
 
 	get_user_ns(token->userns);
 	fd_prepare_file(fdf)->private_data = no_free_ptr(token);
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 int bpf_token_get_info_by_fd(struct bpf_token *token,
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 23fb68fce000..b5131fc597e6 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -4809,14 +4809,14 @@ static int new_userfaultfd(int flags)
 		   anon_inode_create_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
 					     O_RDONLY | (flags & UFFD_SHARED_FCNTL_FLAGS),
 					     NULL));
-	if (fdf.err)
-		return fdf.err;
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	/* prevent the mm struct to be freed */
 	mmgrab(ctx->mm);
 	fd_prepare_file(fdf)->f_mode |= FMODE_NOWAIT;
 	retain_and_null_ptr(ctx);
-	return fd_publish(fdf);
+	return fd_prepare_fd(fdf);
 }
 
 static inline bool userfaultfd_syscall_allowed(int flags)
diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
index 3fd4fef9bab1..98d4266e700e 100644
--- a/net/handshake/netlink.c
+++ b/net/handshake/netlink.c
@@ -106,19 +106,23 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
 	err = -EAGAIN;
 	req = handshake_req_next(hn, class);
 	if (req) {
-		FD_PREPARE(fdf, O_CLOEXEC, req->hr_file);
-		if (fdf.err) {
+		/* The ack carries the error, sendmsg() succeeds: stage last. */
+		const struct fd_slot *fd = fd_prepare(O_CLOEXEC);
+
+		if (IS_ERR(fd)) {
 			fput(req->hr_file); /* drop ref from handshake_req_next() */
-			err = fdf.err;
+			err = PTR_ERR(fd);
 			goto out_complete;
 		}
 
-		err = req->hr_proto->hp_accept(req, info, fd_prepare_fd(fdf));
-		if (err)
-			goto out_complete; /* Automatic cleanup handles fput */
+		err = req->hr_proto->hp_accept(req, info, fd_prepare_fd(fd));
+		if (err) {
+			fput(req->hr_file); /* not staged, drop it by hand */
+			goto out_complete;
+		}
 
-		trace_handshake_cmd_accept(net, req, req->hr_sk, fd_prepare_fd(fdf));
-		fd_publish(fdf);
+		fd_stage(fd, req->hr_file);
+		trace_handshake_cmd_accept(net, req, req->hr_sk, fd_prepare_fd(fd));
 		return 0;
 	}
 
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 71af69d442f2..2d744ee3d340 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1580,14 +1580,13 @@ static int kcm_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		struct kcm_clone info;
 
 		FD_PREPARE(fdf, 0, kcm_clone(sock));
-		if (fdf.err)
-			return fdf.err;
+		if (IS_ERR(fdf))
+			return PTR_ERR(fdf);
 
 		info.fd = fd_prepare_fd(fdf);
 		if (copy_to_user((void __user *)arg, &info, sizeof(info)))
 			return -EFAULT;
 
-		fd_publish(fdf);
 		err = 0;
 		break;
 	}

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (24 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:05   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install Christian Brauner
                   ` (25 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/dma-buf/dma-buf.c   | 33 ++++++++++------------------
 drivers/dma-buf/sw_sync.c   | 40 +++++++++++-----------------------
 drivers/dma-buf/sync_file.c | 52 +++++++++++++--------------------------------
 3 files changed, 38 insertions(+), 87 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d504c636dc29..f0d581fad7ae 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -440,7 +440,8 @@ static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
 	enum dma_resv_usage usage;
 	struct dma_fence *fence = NULL;
 	struct sync_file *sync_file;
-	int fd, ret;
+	int ret;
+	const struct fd_slot *fd;
 
 	if (copy_from_user(&arg, user_data, sizeof(arg)))
 		return -EFAULT;
@@ -451,14 +452,14 @@ static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
 	if ((arg.flags & DMA_BUF_SYNC_RW) == 0)
 		return -EINVAL;
 
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
+	fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	usage = dma_resv_usage_rw(arg.flags & DMA_BUF_SYNC_WRITE);
 	ret = dma_resv_get_singleton(dmabuf->resv, usage, &fence);
 	if (ret)
-		goto err_put_fd;
+		return ret;
 
 	if (!fence)
 		fence = dma_fence_get_stub();
@@ -467,26 +468,14 @@ static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
 
 	dma_fence_put(fence);
 
-	if (!sync_file) {
-		ret = -ENOMEM;
-		goto err_put_fd;
-	}
-
-	arg.fd = fd;
-	if (copy_to_user(user_data, &arg, sizeof(arg))) {
-		ret = -EFAULT;
-		goto err_put_file;
-	}
+	if (!sync_file)
+		return -ENOMEM;
 
-	fd_install(fd, sync_file->file);
+	arg.fd = fd_stage(fd, sync_file->file);
+	if (copy_to_user(user_data, &arg, sizeof(arg)))
+		return -EFAULT;
 
 	return 0;
-
-err_put_file:
-	fput(sync_file->file);
-err_put_fd:
-	put_unused_fd(fd);
-	return ret;
 }
 
 static long dma_buf_import_sync_file(struct dma_buf *dmabuf,
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 8df20b0218a9..90852950e4e3 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -344,8 +344,7 @@ static int sw_sync_debugfs_release(struct inode *inode, struct file *file)
 static long sw_sync_ioctl_create_fence(struct sync_timeline *obj,
 				       unsigned long arg)
 {
-	int fd = get_unused_fd_flags(O_CLOEXEC);
-	int err;
+	const struct fd_slot *fd = fd_prepare(O_CLOEXEC);
 	struct sync_pt *pt;
 	struct sync_file *sync_file;
 	struct sw_sync_create_fence_data data;
@@ -353,41 +352,26 @@ static long sw_sync_ioctl_create_fence(struct sync_timeline *obj,
 	/* SW sync fence are inherently unsafe and can deadlock the kernel */
 	add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
 
-	if (fd < 0)
-		return fd;
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
-	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
-		err = -EFAULT;
-		goto err;
-	}
+	if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
+		return -EFAULT;
 
 	pt = sync_pt_create(obj, data.value);
-	if (!pt) {
-		err = -ENOMEM;
-		goto err;
-	}
+	if (!pt)
+		return -ENOMEM;
 
 	sync_file = sync_file_create(&pt->base);
 	dma_fence_put(&pt->base);
-	if (!sync_file) {
-		err = -ENOMEM;
-		goto err;
-	}
-
-	data.fence = fd;
-	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
-		fput(sync_file->file);
-		err = -EFAULT;
-		goto err;
-	}
+	if (!sync_file)
+		return -ENOMEM;
 
-	fd_install(fd, sync_file->file);
+	data.fence = fd_stage(fd, sync_file->file);
+	if (copy_to_user((void __user *)arg, &data, sizeof(data)))
+		return -EFAULT;
 
 	return 0;
-
-err:
-	put_unused_fd(fd);
-	return err;
 }
 
 static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg)
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 2166bbdf7e4a..316fffc4067e 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -213,56 +213,34 @@ static __poll_t sync_file_poll(struct file *file, poll_table *wait)
 static long sync_file_ioctl_merge(struct sync_file *sync_file,
 				  unsigned long arg)
 {
-	int fd = get_unused_fd_flags(O_CLOEXEC);
-	int err;
+	const struct fd_slot *fd = fd_prepare(O_CLOEXEC);
 	struct sync_file *fence2, *fence3;
 	struct sync_merge_data data;
 
-	if (fd < 0)
-		return fd;
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
-	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
-		err = -EFAULT;
-		goto err_put_fd;
-	}
+	if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
+		return -EFAULT;
 
-	if (data.flags || data.pad) {
-		err = -EINVAL;
-		goto err_put_fd;
-	}
+	if (data.flags || data.pad)
+		return -EINVAL;
 
 	fence2 = sync_file_fdget(data.fd2);
-	if (!fence2) {
-		err = -ENOENT;
-		goto err_put_fd;
-	}
+	if (!fence2)
+		return -ENOENT;
 
 	data.name[sizeof(data.name) - 1] = '\0';
 	fence3 = sync_file_merge(data.name, sync_file, fence2);
-	if (!fence3) {
-		err = -ENOMEM;
-		goto err_put_fence2;
-	}
-
-	data.fence = fd;
-	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
-		err = -EFAULT;
-		goto err_put_fence3;
-	}
-
-	fd_install(fd, fence3->file);
 	fput(fence2->file);
-	return 0;
-
-err_put_fence3:
-	fput(fence3->file);
+	if (!fence3)
+		return -ENOMEM;
 
-err_put_fence2:
-	fput(fence2->file);
+	data.fence = fd_stage(fd, fence3->file);
+	if (copy_to_user((void __user *)arg, &data, sizeof(data)))
+		return -EFAULT;
 
-err_put_fd:
-	put_unused_fd(fd);
-	return err;
+	return 0;
 }
 
 static int sync_fill_fence_info(struct dma_fence *fence,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (25 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:04   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns Christian Brauner
                   ` (24 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 67 +++++++-------------------------
 1 file changed, 13 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 7fcfc150a7fc..158abe7e3da6 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1988,11 +1988,10 @@ static uint32_t get_process_num_bos(struct kfd_process *p)
 	return num_of_bos;
 }
 
-static int criu_get_prime_handle(struct kgd_mem *mem,
-				 int flags, u32 *shared_fd,
-				 struct file **file)
+static int criu_get_prime_handle(struct kgd_mem *mem, int flags, u32 *shared_fd)
 {
 	struct dma_buf *dmabuf;
+	const struct fd_slot *fd;
 	int ret;
 
 	ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, &dmabuf);
@@ -2001,38 +2000,17 @@ static int criu_get_prime_handle(struct kgd_mem *mem,
 		return ret;
 	}
 
-	ret = get_unused_fd_flags(flags);
-	if (ret < 0) {
+	fd = fd_prepare(flags);
+	if (IS_ERR(fd)) {
+		ret = PTR_ERR(fd);
 		pr_err("dmabuf create fd failed, ret:%d\n", ret);
-		goto out_free_dmabuf;
+		dma_buf_put(dmabuf);
+		return ret;
 	}
 
-	*shared_fd = ret;
-	*file = dmabuf->file;
+	/* Installed or dropped with the ioctl's result, nothing to put back. */
+	*shared_fd = fd_stage(fd, dmabuf->file);
 	return 0;
-
-out_free_dmabuf:
-	dma_buf_put(dmabuf);
-	return ret;
-}
-
-static void commit_files(struct file **files,
-			 struct kfd_criu_bo_bucket *bo_buckets,
-			 unsigned int count,
-			 int err)
-{
-	while (count--) {
-		struct file *file = files[count];
-
-		if (!file)
-			continue;
-		if (err) {
-			fput(file);
-			put_unused_fd(bo_buckets[count].dmabuf_fd);
-		} else {
-			fd_install(bo_buckets[count].dmabuf_fd, file);
-		}
-	}
 }
 
 static int criu_checkpoint_bos(struct kfd_process *p,
@@ -2043,7 +2021,6 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 {
 	struct kfd_criu_bo_bucket *bo_buckets;
 	struct kfd_criu_bo_priv_data *bo_privs;
-	struct file **files = NULL;
 	int ret = 0, pdd_index, bo_index = 0, id;
 	void *mem;
 
@@ -2057,12 +2034,6 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 		goto exit;
 	}
 
-	files = kvcalloc(num_bos, sizeof(struct file *), GFP_KERNEL);
-	if (!files) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
 	for (pdd_index = 0; pdd_index < p->n_pdds; pdd_index++) {
 		struct kfd_process_device *pdd = p->pdds[pdd_index];
 		struct amdgpu_bo *dumper_bo;
@@ -2105,7 +2076,7 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 				ret = criu_get_prime_handle(kgd_mem,
 						bo_bucket->alloc_flags &
 						KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0,
-						&bo_bucket->dmabuf_fd, &files[bo_index]);
+						&bo_bucket->dmabuf_fd);
 				if (ret)
 					goto exit;
 			} else {
@@ -2156,8 +2127,6 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 	*priv_offset += num_bos * sizeof(*bo_privs);
 
 exit:
-	commit_files(files, bo_buckets, bo_index, ret);
-	kvfree(files);
 	kvfree(bo_buckets);
 	kvfree(bo_privs);
 	return ret;
@@ -2504,8 +2473,7 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,
 
 static int criu_restore_bo(struct kfd_process *p,
 			   struct kfd_criu_bo_bucket *bo_bucket,
-			   struct kfd_criu_bo_priv_data *bo_priv,
-			   struct file **file)
+			   struct kfd_criu_bo_priv_data *bo_priv)
 {
 	struct kfd_process_device *pdd;
 	struct kgd_mem *kgd_mem;
@@ -2557,7 +2525,7 @@ static int criu_restore_bo(struct kfd_process *p,
 	if (bo_bucket->alloc_flags
 	    & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) {
 		ret = criu_get_prime_handle(kgd_mem, DRM_RDWR,
-					    &bo_bucket->dmabuf_fd, file);
+					    &bo_bucket->dmabuf_fd);
 		if (ret)
 			return ret;
 	} else {
@@ -2574,7 +2542,6 @@ static int criu_restore_bos(struct kfd_process *p,
 {
 	struct kfd_criu_bo_bucket *bo_buckets = NULL;
 	struct kfd_criu_bo_priv_data *bo_privs = NULL;
-	struct file **files = NULL;
 	int ret = 0;
 	uint32_t i = 0;
 
@@ -2588,12 +2555,6 @@ static int criu_restore_bos(struct kfd_process *p,
 	if (!bo_buckets)
 		return -ENOMEM;
 
-	files = kvcalloc(args->num_bos, sizeof(struct file *), GFP_KERNEL);
-	if (!files) {
-		ret = -ENOMEM;
-		goto exit;
-	}
-
 	ret = copy_from_user(bo_buckets, (void __user *)args->bos,
 			     args->num_bos * sizeof(*bo_buckets));
 	if (ret) {
@@ -2619,7 +2580,7 @@ static int criu_restore_bos(struct kfd_process *p,
 
 	/* Create and map new BOs */
 	for (; i < args->num_bos; i++) {
-		ret = criu_restore_bo(p, &bo_buckets[i], &bo_privs[i], &files[i]);
+		ret = criu_restore_bo(p, &bo_buckets[i], &bo_privs[i]);
 		if (ret) {
 			pr_debug("Failed to restore BO[%d] ret%d\n", i, ret);
 			goto exit;
@@ -2634,8 +2595,6 @@ static int criu_restore_bos(struct kfd_process *p,
 		ret = -EFAULT;
 
 exit:
-	commit_files(files, bo_buckets, i, ret);
-	kvfree(files);
 	kvfree(bo_buckets);
 	kvfree(bo_privs);
 	return ret;

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (26 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:04   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 29/50] drm/virtio: " Christian Brauner
                   ` (23 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/msm/msm_gem_submit.c | 22 +++++++++-------------
 drivers/gpu/drm/msm/msm_gem_vma.c    | 22 +++++++++-------------
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 5862db05297a..4ddfd07c1480 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -558,7 +558,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 	struct drm_syncobj **syncobjs_to_reset = NULL;
 	struct sync_file *sync_file = NULL;
 	unsigned cmds_to_parse;
-	int out_fence_fd = -1;
+	const struct fd_slot *out_fence_fd = NULL;
 	unsigned i;
 	int ret;
 
@@ -601,9 +601,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 	ring = gpu->rb[queue->ring_nr];
 
 	if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
-		out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
-		if (out_fence_fd < 0) {
-			ret = out_fence_fd;
+		out_fence_fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(out_fence_fd)) {
+			ret = PTR_ERR(out_fence_fd);
 			goto out_post_unlock;
 		}
 	}
@@ -777,6 +777,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 		sync_file = sync_file_create(submit->user_fence);
 		if (!sync_file)
 			ret = -ENOMEM;
+		else
+			fd_stage(out_fence_fd, sync_file->file);
 	}
 
 	if (ret)
@@ -814,15 +816,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 out_unlock:
 	mutex_unlock(&queue->lock);
 out_post_unlock:
-	if (ret) {
-		if (out_fence_fd >= 0)
-			put_unused_fd(out_fence_fd);
-		if (sync_file)
-			fput(sync_file->file);
-	} else if (sync_file) {
-		fd_install(out_fence_fd, sync_file->file);
-		args->fence_fd = out_fence_fd;
-	}
+	/* A staged sync file and its descriptor are dropped on return. */
+	if (!ret && sync_file)
+		args->fence_fd = fd_prepare_fd(out_fence_fd);
 
 	if (!IS_ERR_OR_NULL(submit)) {
 		msm_gem_submit_put(submit);
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index c11d021581e0..77d365566732 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -1441,7 +1441,7 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
 	struct drm_syncobj **syncobjs_to_reset = NULL;
 	struct sync_file *sync_file = NULL;
 	struct dma_fence *fence;
-	int out_fence_fd = -1;
+	const struct fd_slot *out_fence_fd = NULL;
 	int ret, nr_bos = 0;
 	unsigned i;
 
@@ -1479,9 +1479,9 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
 	}
 
 	if (args->flags & MSM_VM_BIND_FENCE_FD_OUT) {
-		out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
-		if (out_fence_fd < 0) {
-			ret = out_fence_fd;
+		out_fence_fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(out_fence_fd)) {
+			ret = PTR_ERR(out_fence_fd);
 			goto out_post_unlock;
 		}
 	}
@@ -1565,6 +1565,8 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
 		sync_file = sync_file_create(job->fence);
 		if (!sync_file)
 			ret = -ENOMEM;
+		else
+			fd_stage(out_fence_fd, sync_file->file);
 	}
 
 	if (ret)
@@ -1593,15 +1595,9 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file)
 out_unlock:
 	mutex_unlock(&queue->lock);
 out_post_unlock:
-	if (ret) {
-		if (out_fence_fd >= 0)
-			put_unused_fd(out_fence_fd);
-		if (sync_file)
-			fput(sync_file->file);
-	} else if (sync_file) {
-		fd_install(out_fence_fd, sync_file->file);
-		args->fence_fd = out_fence_fd;
-	}
+	/* A staged sync file and its descriptor are dropped on return. */
+	if (!ret && sync_file)
+		args->fence_fd = fd_prepare_fd(out_fence_fd);
 
 	if (!IS_ERR_OR_NULL(job)) {
 		if (ret)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 29/50] drm/virtio: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (27 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:11   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 30/50] drm/vmwgfx: " Christian Brauner
                   ` (22 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/virtio/virtgpu_submit.c | 32 ++++++++++++--------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c b/drivers/gpu/drm/virtio/virtgpu_submit.c
index 32cb1e4aa425..51b224acb72b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_submit.c
+++ b/drivers/gpu/drm/virtio/virtgpu_submit.c
@@ -39,7 +39,7 @@ struct virtio_gpu_submit {
 	struct virtio_gpu_device *vgdev;
 	struct sync_file *sync_file;
 	struct drm_file *file;
-	int out_fence_fd;
+	const struct fd_slot *out_fence_fd;
 	u64 fence_ctx;
 	u32 ring_idx;
 	void *buf;
@@ -340,14 +340,8 @@ static void virtio_gpu_cleanup_submit(struct virtio_gpu_submit *submit)
 	if (submit->buflist)
 		virtio_gpu_array_put_free(submit->buflist);
 
-	if (submit->out_fence_fd >= 0)
-		put_unused_fd(submit->out_fence_fd);
-
 	if (submit->out_fence)
 		dma_fence_put(&submit->out_fence->f);
-
-	if (submit->sync_file)
-		fput(submit->sync_file->file);
 }
 
 static void virtio_gpu_submit(struct virtio_gpu_submit *submit)
@@ -363,7 +357,7 @@ static void virtio_gpu_complete_submit(struct virtio_gpu_submit *submit)
 	submit->buf = NULL;
 	submit->buflist = NULL;
 	submit->sync_file = NULL;
-	submit->out_fence_fd = -1;
+	submit->out_fence_fd = NULL;
 }
 
 static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit,
@@ -405,7 +399,7 @@ static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit,
 	submit->out_fence = out_fence;
 	submit->fence_ctx = fence_ctx;
 	submit->ring_idx = ring_idx;
-	submit->out_fence_fd = -1;
+	submit->out_fence_fd = NULL;
 	submit->vfpriv = vfpriv;
 	submit->vgdev = vgdev;
 	submit->exbuf = exbuf;
@@ -420,15 +414,15 @@ static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit,
 		return PTR_ERR(submit->buf);
 
 	if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
-		err = get_unused_fd_flags(O_CLOEXEC);
-		if (err < 0)
-			return err;
-
-		submit->out_fence_fd = err;
+		submit->out_fence_fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(submit->out_fence_fd))
+			return PTR_ERR(submit->out_fence_fd);
 
 		submit->sync_file = sync_file_create(&out_fence->f);
 		if (!submit->sync_file)
 			return -ENOMEM;
+
+		fd_stage(submit->out_fence_fd, submit->sync_file->file);
 	}
 
 	return 0;
@@ -456,12 +450,10 @@ static int virtio_gpu_wait_in_fence(struct virtio_gpu_submit *submit)
 	return ret;
 }
 
-static void virtio_gpu_install_out_fence_fd(struct virtio_gpu_submit *submit)
+static void virtio_gpu_report_out_fence_fd(struct virtio_gpu_submit *submit)
 {
-	if (submit->sync_file) {
-		submit->exbuf->fence_fd = submit->out_fence_fd;
-		fd_install(submit->out_fence_fd, submit->sync_file->file);
-	}
+	if (submit->sync_file)
+		submit->exbuf->fence_fd = fd_prepare_fd(submit->out_fence_fd);
 }
 
 static int virtio_gpu_lock_buflist(struct virtio_gpu_submit *submit)
@@ -534,7 +526,7 @@ int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
 	 * Set up user-out data after submitting the job to optimize
 	 * the job submission path.
 	 */
-	virtio_gpu_install_out_fence_fd(&submit);
+	virtio_gpu_report_out_fence_fd(&submit);
 	virtio_gpu_process_post_deps(&submit);
 	virtio_gpu_complete_submit(&submit);
 cleanup:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 30/50] drm/vmwgfx: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (28 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 29/50] drm/virtio: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:09   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 31/50] vfio: install the migration data " Christian Brauner
                   ` (21 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 29 +++++++++++------------------
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index a9136a6523cb..9daa74a13485 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -4109,15 +4109,17 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 	uint32_t handle = 0;
 	int ret;
 	int32_t out_fence_fd = -1;
+	const struct fd_slot *out_fd = NULL;
 	struct sync_file *sync_file = NULL;
 	DECLARE_VAL_CONTEXT(val_ctx, sw_context, 1);
 
 	if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
-		out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
-		if (out_fence_fd < 0) {
+		out_fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(out_fd)) {
 			VMW_DEBUG_USER("Failed to get a fence fd.\n");
-			return out_fence_fd;
+			return PTR_ERR(out_fd);
 		}
+		out_fence_fd = fd_prepare_fd(out_fd);
 	}
 
 	if (throttle_us) {
@@ -4256,28 +4258,21 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 		sync_file = sync_file_create(&fence->base);
 		if (!sync_file) {
 			VMW_DEBUG_USER("Sync file create failed for fence\n");
-			put_unused_fd(out_fence_fd);
+			/* The reserved descriptor is released on return. */
 			out_fence_fd = -1;
 
 			(void) vmw_fence_obj_wait(fence, false, false,
 						  VMW_FENCE_WAIT_TIMEOUT);
+		} else {
+			/* Link the fence with the FD created earlier */
+			fd_stage(out_fd, sync_file->file);
 		}
 	}
 
+	/* A staged sync file is dropped with the ioctl on error. */
 	ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
 				    user_fence_rep, fence, handle, out_fence_fd);
 
-	if (sync_file) {
-		if (ret) {
-			/* usercopy of fence failed, put the file object */
-			fput(sync_file->file);
-			put_unused_fd(out_fence_fd);
-		} else {
-			/* Link the fence with the FD created earlier */
-			fd_install(out_fence_fd, sync_file->file);
-		}
-	}
-
 	/* Don't unreference when handing fence out */
 	if (unlikely(out_fence != NULL)) {
 		*out_fence = fence;
@@ -4323,9 +4318,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 	if (header)
 		vmw_cmdbuf_header_free(header);
 out_free_fence_fd:
-	if (out_fence_fd >= 0)
-		put_unused_fd(out_fence_fd);
-
+	/* A reserved descriptor is released on return. */
 	return ret;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 31/50] vfio: install the migration data descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (29 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 30/50] drm/vmwgfx: " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:07   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 32/50] liveupdate: install the session descriptors " Christian Brauner
                   ` (20 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/vfio/vfio_main.c | 25 +++++++------------------
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 423ead48aafe..93d9d21f4074 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -903,28 +903,17 @@ EXPORT_SYMBOL_GPL(vfio_mig_get_next_state);
 static int vfio_ioct_mig_return_fd(struct file *filp, void __user *arg,
 				   struct vfio_device_feature_mig_state *mig)
 {
-	int ret;
-	int fd;
+	FD_PREPARE(fdf, O_CLOEXEC, filp);
 
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0) {
-		ret = fd;
-		goto out_fput;
+	if (IS_ERR(fdf)) {
+		fput(filp);
+		return PTR_ERR(fdf);
 	}
 
-	mig->data_fd = fd;
-	if (copy_to_user(arg, mig, sizeof(*mig))) {
-		ret = -EFAULT;
-		goto out_put_unused;
-	}
-	fd_install(fd, filp);
+	mig->data_fd = fd_prepare_fd(fdf);
+	if (copy_to_user(arg, mig, sizeof(*mig)))
+		return -EFAULT;
 	return 0;
-
-out_put_unused:
-	put_unused_fd(fd);
-out_fput:
-	fput(filp);
-	return ret;
 }
 
 static int

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 32/50] liveupdate: install the session descriptors when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (30 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 31/50] vfio: install the migration data " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:09   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns Christian Brauner
                   ` (19 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 kernel/liveupdate/luo_core.c    | 48 ++++++++++++-----------------------------
 kernel/liveupdate/luo_session.c | 24 ++++++---------------
 2 files changed, 21 insertions(+), 51 deletions(-)

diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
index 1b2bda22902d..3899bbf30b53 100644
--- a/kernel/liveupdate/luo_core.c
+++ b/kernel/liveupdate/luo_core.c
@@ -270,61 +270,41 @@ struct luo_device_state {
 static int luo_ioctl_create_session(struct luo_ucmd *ucmd)
 {
 	struct liveupdate_ioctl_create_session *argp = ucmd->cmd;
+	const struct fd_slot *fd;
 	struct file *file;
 	int err;
 
-	argp->fd = get_unused_fd_flags(O_CLOEXEC);
-	if (argp->fd < 0)
-		return argp->fd;
+	fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	err = luo_session_create(argp->name, &file);
 	if (err)
-		goto err_put_fd;
-
-	err = luo_ucmd_respond(ucmd, sizeof(*argp));
-	if (err)
-		goto err_put_file;
-
-	fd_install(argp->fd, file);
-
-	return 0;
+		return err;
 
-err_put_file:
-	fput(file);
-err_put_fd:
-	put_unused_fd(argp->fd);
+	argp->fd = fd_stage(fd, file);
 
-	return err;
+	return luo_ucmd_respond(ucmd, sizeof(*argp));
 }
 
 static int luo_ioctl_retrieve_session(struct luo_ucmd *ucmd)
 {
 	struct liveupdate_ioctl_retrieve_session *argp = ucmd->cmd;
+	const struct fd_slot *fd;
 	struct file *file;
 	int err;
 
-	argp->fd = get_unused_fd_flags(O_CLOEXEC);
-	if (argp->fd < 0)
-		return argp->fd;
+	fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	err = luo_session_retrieve(argp->name, &file);
 	if (err < 0)
-		goto err_put_fd;
-
-	err = luo_ucmd_respond(ucmd, sizeof(*argp));
-	if (err)
-		goto err_put_file;
-
-	fd_install(argp->fd, file);
-
-	return 0;
+		return err;
 
-err_put_file:
-	fput(file);
-err_put_fd:
-	put_unused_fd(argp->fd);
+	argp->fd = fd_stage(fd, file);
 
-	return err;
+	return luo_ucmd_respond(ucmd, sizeof(*argp));
 }
 
 static int luo_open(struct inode *inodep, struct file *filep)
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index f48e9a4185f9..7de35bad1ede 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -282,33 +282,23 @@ static int luo_session_retrieve_fd(struct luo_session *session,
 				   struct luo_ucmd *ucmd)
 {
 	struct liveupdate_session_retrieve_fd *argp = ucmd->cmd;
+	const struct fd_slot *fd;
 	struct file *file;
 	int err;
 
-	argp->fd = get_unused_fd_flags(O_CLOEXEC);
-	if (argp->fd < 0)
-		return argp->fd;
+	fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	mutex_lock(&session->mutex);
 	err = luo_retrieve_file(&session->file_set, argp->token, &file);
 	mutex_unlock(&session->mutex);
 	if (err < 0)
-		goto err_put_fd;
-
-	err = luo_ucmd_respond(ucmd, sizeof(*argp));
-	if (err)
-		goto err_put_file;
-
-	fd_install(argp->fd, file);
-
-	return 0;
+		return err;
 
-err_put_file:
-	fput(file);
-err_put_fd:
-	put_unused_fd(argp->fd);
+	argp->fd = fd_stage(fd, file);
 
-	return err;
+	return luo_ucmd_respond(ucmd, sizeof(*argp));
 }
 
 static int luo_session_finish(struct luo_session *session,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (31 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 32/50] liveupdate: install the session descriptors " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:09   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns Christian Brauner
                   ` (18 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 io_uring/zcrx.c | 25 +++++++------------------
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 1b3b11405dac..d458c614c765 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -795,8 +795,6 @@ static int zcrx_export(struct io_ring_ctx *ctx, struct io_zcrx_ifq *ifq,
 		       struct zcrx_ctrl *ctrl, void __user *arg)
 {
 	struct zcrx_ctrl_export *ce = &ctrl->zc_export;
-	struct file *file;
-	int fd;
 
 	if (!mem_is_zero(ce, sizeof(*ce)))
 		return -EINVAL;
@@ -804,27 +802,18 @@ static int zcrx_export(struct io_ring_ctx *ctx, struct io_zcrx_ifq *ifq,
 	refcount_inc(&ifq->refs);
 	refcount_inc(&ifq->user_refs);
 
-	file = anon_inode_create_getfile("[zcrx]", &zcrx_box_fops,
-					 ifq, O_CLOEXEC, NULL);
-	if (IS_ERR(file)) {
+	FD_PREPARE(fdf, O_CLOEXEC,
+		   anon_inode_create_getfile("[zcrx]", &zcrx_box_fops, ifq,
+					     O_CLOEXEC, NULL));
+	if (IS_ERR(fdf)) {
 		zcrx_unregister(ifq, NULL);
-		return PTR_ERR(file);
-	}
-
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0) {
-		fput(file);
-		return fd;
+		return PTR_ERR(fdf);
 	}
 
-	ce->zcrx_fd = fd;
-	if (copy_to_user(arg, ctrl, sizeof(*ctrl))) {
-		fput(file);
-		put_unused_fd(fd);
+	ce->zcrx_fd = fd_prepare_fd(fdf);
+	if (copy_to_user(arg, ctrl, sizeof(*ctrl)))
 		return -EFAULT;
-	}
 
-	fd_install(fd, file);
 	return 0;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (32 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:14   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns Christian Brauner
                   ` (17 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 net/sctp/socket.c | 78 +++++++++++++++++++++----------------------------------
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..b75c50af8c16 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5744,46 +5744,41 @@ static int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id,
 }
 
 static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *peeloff,
-					  struct file **newfile, unsigned flags)
+					  unsigned flags)
 {
 	struct socket *newsock;
+	struct file *newfile;
+	const struct fd_slot *fd;
 	int retval;
 
 	retval = sctp_do_peeloff(sk, peeloff->associd, &newsock);
 	if (retval < 0)
-		goto out;
+		return retval;
 
-	/* Map the socket to an unused fd that can be returned to the user.  */
-	retval = get_unused_fd_flags(flags & SOCK_CLOEXEC);
-	if (retval < 0) {
+	/* Map the socket to a reserved fd that can be returned to the user. */
+	fd = fd_prepare(flags & SOCK_CLOEXEC);
+	if (IS_ERR(fd)) {
 		sock_release(newsock);
-		goto out;
-	}
-
-	*newfile = sock_alloc_file(newsock, 0, NULL);
-	if (IS_ERR(*newfile)) {
-		put_unused_fd(retval);
-		retval = PTR_ERR(*newfile);
-		*newfile = NULL;
-		return retval;
+		return PTR_ERR(fd);
 	}
 
-	pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk,
-		 retval);
-
-	peeloff->sd = retval;
+	newfile = sock_alloc_file(newsock, 0, NULL);
+	if (IS_ERR(newfile))
+		return PTR_ERR(newfile);
 
 	if (flags & SOCK_NONBLOCK)
-		(*newfile)->f_flags |= O_NONBLOCK;
-out:
-	return retval;
+		newfile->f_flags |= O_NONBLOCK;
+
+	peeloff->sd = fd_stage(fd, newfile);
+	pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk,
+		 peeloff->sd);
+	return peeloff->sd;
 }
 
 static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, int __user *optlen)
 {
 	sctp_peeloff_arg_t peeloff;
-	struct file *newfile = NULL;
-	int retval = 0;
+	int retval;
 
 	if (len < sizeof(sctp_peeloff_arg_t))
 		return -EINVAL;
@@ -5791,24 +5786,17 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
 	if (copy_from_user(&peeloff, optval, len))
 		return -EFAULT;
 
-	retval = sctp_getsockopt_peeloff_common(sk, &peeloff, &newfile, 0);
+	retval = sctp_getsockopt_peeloff_common(sk, &peeloff, 0);
 	if (retval < 0)
-		goto out;
+		return retval;
 
 	/* Return the fd mapped to the new socket.  */
-	if (put_user(len, optlen)) {
-		fput(newfile);
-		put_unused_fd(retval);
+	if (put_user(len, optlen))
 		return -EFAULT;
-	}
 
-	if (copy_to_user(optval, &peeloff, len)) {
-		fput(newfile);
-		put_unused_fd(retval);
+	if (copy_to_user(optval, &peeloff, len))
 		return -EFAULT;
-	}
-	fd_install(retval, newfile);
-out:
+
 	return retval;
 }
 
@@ -5816,8 +5804,7 @@ static int sctp_getsockopt_peeloff_flags(struct sock *sk, int len,
 					 char __user *optval, int __user *optlen)
 {
 	sctp_peeloff_flags_arg_t peeloff;
-	struct file *newfile = NULL;
-	int retval = 0;
+	int retval;
 
 	if (len < sizeof(sctp_peeloff_flags_arg_t))
 		return -EINVAL;
@@ -5826,24 +5813,17 @@ static int sctp_getsockopt_peeloff_flags(struct sock *sk, int len,
 		return -EFAULT;
 
 	retval = sctp_getsockopt_peeloff_common(sk, &peeloff.p_arg,
-						&newfile, peeloff.flags);
+						peeloff.flags);
 	if (retval < 0)
-		goto out;
+		return retval;
 
 	/* Return the fd mapped to the new socket.  */
-	if (put_user(len, optlen)) {
-		fput(newfile);
-		put_unused_fd(retval);
+	if (put_user(len, optlen))
 		return -EFAULT;
-	}
 
-	if (copy_to_user(optval, &peeloff, len)) {
-		fput(newfile);
-		put_unused_fd(retval);
+	if (copy_to_user(optval, &peeloff, len))
 		return -EFAULT;
-	}
-	fd_install(retval, newfile);
-out:
+
 	return retval;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (33 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:13   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor " Christian Brauner
                   ` (16 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 sound/core/compress_offload.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 23d62fede06e..94bc226f8db9 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1065,7 +1065,8 @@ static u64 snd_compr_seqno_next(struct snd_compr_stream *stream)
 static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_task *utask)
 {
 	struct snd_compr_task_runtime *task;
-	int retval, fd_i, fd_o;
+	int retval;
+	const struct fd_slot *fd_i, *fd_o;
 
 	if (stream->runtime->total_tasks >= stream->runtime->fragments)
 		return -EBUSY;
@@ -1080,29 +1081,26 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
 	if (retval < 0)
 		goto cleanup;
 	/* similar functionality as in dma_buf_fd(), but ensure that both
-	   file descriptors are allocated before fd_install() */
+	   file descriptors are reserved before either is staged */
 	if (!task->input || !task->input->file || !task->output || !task->output->file) {
 		retval = -EINVAL;
 		goto free_driver_task;
 	}
-	fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC);
-	if (fd_i < 0) {
-		retval = fd_i;
+	fd_i = fd_prepare(O_WRONLY|O_CLOEXEC);
+	if (IS_ERR(fd_i)) {
+		retval = PTR_ERR(fd_i);
 		goto free_driver_task;
 	}
-	fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC);
-	if (fd_o < 0) {
-		retval = fd_o;
-		put_unused_fd(fd_i);
+	fd_o = fd_prepare(O_RDONLY|O_CLOEXEC);
+	if (IS_ERR(fd_o)) {
+		retval = PTR_ERR(fd_o);
 		goto free_driver_task;
 	}
 	/* keep dmabuf reference until freed with task free ioctl */
 	get_dma_buf(task->input);
 	get_dma_buf(task->output);
-	fd_install(fd_i, task->input->file);
-	fd_install(fd_o, task->output->file);
-	utask->input_fd = fd_i;
-	utask->output_fd = fd_o;
+	utask->input_fd = fd_stage(fd_i, task->input->file);
+	utask->output_fd = fd_stage(fd_o, task->output->file);
 	list_add_tail(&task->list, &stream->runtime->tasks);
 	stream->runtime->total_tasks++;
 	return 0;

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (34 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:13   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server " Christian Brauner
                   ` (15 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/virt/nitro_enclaves/ne_misc_dev.c | 33 ++++++++++++-------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c
index c91300a73f50..93c3f00f5443 100644
--- a/drivers/virt/nitro_enclaves/ne_misc_dev.c
+++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c
@@ -1589,7 +1589,7 @@ static const struct file_operations ne_enclave_fops = {
 static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 __user *slot_uid)
 {
 	struct ne_pci_dev_cmd_reply cmd_reply = {};
-	int enclave_fd = -1;
+	const struct fd_slot *enclave_fd = NULL;
 	struct file *enclave_file = NULL;
 	unsigned int i = 0;
 	struct ne_enclave *ne_enclave = NULL;
@@ -1647,9 +1647,9 @@ static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 __user *slot_ui
 		goto free_cpumask;
 	}
 
-	enclave_fd = get_unused_fd_flags(O_CLOEXEC);
-	if (enclave_fd < 0) {
-		rc = enclave_fd;
+	enclave_fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(enclave_fd)) {
+		rc = PTR_ERR(enclave_fd);
 
 		dev_err_ratelimited(ne_misc_dev.this_device,
 				    "Error in getting unused fd [rc=%d]\n", rc);
@@ -1664,7 +1664,7 @@ static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 __user *slot_ui
 		dev_err_ratelimited(ne_misc_dev.this_device,
 				    "Error in anon inode get file [rc=%d]\n", rc);
 
-		goto put_fd;
+		goto free_cpumask;
 	}
 
 	rc = ne_do_request(pdev, SLOT_ALLOC,
@@ -1688,27 +1688,20 @@ static int ne_create_vm_ioctl(struct ne_pci_dev *ne_pci_dev, u64 __user *slot_ui
 
 	list_add(&ne_enclave->enclave_list_entry, &ne_pci_dev->enclaves_list);
 
-	if (copy_to_user(slot_uid, &ne_enclave->slot_uid, sizeof(ne_enclave->slot_uid))) {
-		/*
-		 * As we're holding the only reference to 'enclave_file', fput()
-		 * will call ne_enclave_release() which will do a proper cleanup
-		 * of all so far allocated resources, leaving only the unused fd
-		 * for us to free.
-		 */
-		fput(enclave_file);
-		put_unused_fd(enclave_fd);
+	fd_stage(enclave_fd, enclave_file);
 
+	/*
+	 * The failed ioctl drops the descriptor and with it the only reference
+	 * to 'enclave_file', so ne_enclave_release() does a proper cleanup of
+	 * all so far allocated resources.
+	 */
+	if (copy_to_user(slot_uid, &ne_enclave->slot_uid, sizeof(ne_enclave->slot_uid)))
 		return -EFAULT;
-	}
-
-	fd_install(enclave_fd, enclave_file);
 
-	return enclave_fd;
+	return fd_prepare_fd(enclave_fd);
 
 put_file:
 	fput(enclave_file);
-put_fd:
-	put_unused_fd(enclave_fd);
 free_cpumask:
 	free_cpumask_var(ne_enclave->vcpu_ids);
 	for (i = 0; i < ne_enclave->nr_parent_vm_cores; i++)

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (35 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:14   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure Christian Brauner
                   ` (14 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/char/tpm/tpm_vtpm_proxy.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
index b81fd2a537df..8eb87044596a 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -531,8 +531,8 @@ static struct file *vtpm_proxy_create_device(
 				 struct vtpm_proxy_new_dev *vtpm_new_dev)
 {
 	struct proxy_dev *proxy_dev;
-	int rc, fd;
 	struct file *file;
+	int rc;
 
 	if (vtpm_new_dev->flags & ~VTPM_PROXY_FLAGS_ALL)
 		return ERR_PTR(-EOPNOTSUPP);
@@ -544,20 +544,15 @@ static struct file *vtpm_proxy_create_device(
 	proxy_dev->flags = vtpm_new_dev->flags;
 
 	/* setup an anonymous file for the server-side */
-	fd = get_unused_fd_flags(O_RDWR);
-	if (fd < 0) {
-		rc = fd;
+	FD_PREPARE(fdf, O_RDWR,
+		   anon_inode_getfile("[vtpms]", &vtpm_proxy_fops, proxy_dev,
+				      O_RDWR));
+	if (IS_ERR(fdf)) {
+		rc = PTR_ERR(fdf);
 		goto err_delete_proxy_dev;
 	}
+	file = fd_prepare_file(fdf);
 
-	file = anon_inode_getfile("[vtpms]", &vtpm_proxy_fops, proxy_dev,
-				  O_RDWR);
-	if (IS_ERR(file)) {
-		rc = PTR_ERR(file);
-		goto err_put_unused_fd;
-	}
-
-	/* from now on we can unwind with put_unused_fd() + fput() */
 	/* simulate an open() on the server side */
 	vtpm_proxy_fops_open(file);
 
@@ -566,16 +561,13 @@ static struct file *vtpm_proxy_create_device(
 
 	vtpm_proxy_work_start(proxy_dev);
 
-	vtpm_new_dev->fd = fd;
+	vtpm_new_dev->fd = fd_prepare_fd(fdf);
 	vtpm_new_dev->major = MAJOR(proxy_dev->chip->dev.devt);
 	vtpm_new_dev->minor = MINOR(proxy_dev->chip->dev.devt);
 	vtpm_new_dev->tpm_num = proxy_dev->chip->dev_num;
 
 	return file;
 
-err_put_unused_fd:
-	put_unused_fd(fd);
-
 err_delete_proxy_dev:
 	vtpm_proxy_delete_proxy_dev(proxy_dev);
 
@@ -640,13 +632,9 @@ static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl,
 		return PTR_ERR(vtpm_file);
 
 	if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev,
-			 sizeof(vtpm_new_dev))) {
-		put_unused_fd(vtpm_new_dev.fd);
-		fput(vtpm_file);
+			 sizeof(vtpm_new_dev)))
 		return -EFAULT;
-	}
 
-	fd_install(vtpm_new_dev.fd, vtpm_file);
 	return 0;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (36 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:12   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 39/50] seccomp: stop putting the listener " Christian Brauner
                   ` (13 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 kernel/events/core.c | 31 +++++++++++--------------------
 1 file changed, 11 insertions(+), 20 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index a6c8e38a3110..54834a7aca53 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -13924,7 +13924,7 @@ SYSCALL_DEFINE5(perf_event_open,
 	struct file *event_file = NULL;
 	struct task_struct *task = NULL;
 	struct pmu *pmu;
-	int event_fd;
+	const struct fd_slot *event_fd;
 	int move_group = 0;
 	int err;
 	int f_flags = O_RDWR;
@@ -13990,9 +13990,9 @@ SYSCALL_DEFINE5(perf_event_open,
 	if (flags & PERF_FLAG_FD_CLOEXEC)
 		f_flags |= O_CLOEXEC;
 
-	event_fd = get_unused_fd_flags(f_flags);
-	if (event_fd < 0)
-		return event_fd;
+	event_fd = fd_prepare(f_flags);
+	if (IS_ERR(event_fd))
+		return PTR_ERR(event_fd);
 
 	/*
 	 * Event creation should be under SRCU, see perf_pmu_unregister().
@@ -14001,15 +14001,11 @@ SYSCALL_DEFINE5(perf_event_open,
 
 	CLASS(fd, group)(group_fd);     // group_fd == -1 => empty
 	if (group_fd != -1) {
-		if (!is_perf_file(group)) {
-			err = -EBADF;
-			goto err_fd;
-		}
+		if (!is_perf_file(group))
+			return -EBADF;
 		group_leader = fd_file(group)->private_data;
-		if (group_leader->state <= PERF_EVENT_STATE_EXIT) {
-			err = -ENODEV;
-			goto err_fd;
-		}
+		if (group_leader->state <= PERF_EVENT_STATE_EXIT)
+			return -ENODEV;
 		if (flags & PERF_FLAG_FD_OUTPUT)
 			output_event = group_leader;
 		if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -14018,10 +14014,8 @@ SYSCALL_DEFINE5(perf_event_open,
 
 	if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) {
 		task = find_lively_task_by_vpid(pid);
-		if (IS_ERR(task)) {
-			err = PTR_ERR(task);
-			goto err_fd;
-		}
+		if (IS_ERR(task))
+			return PTR_ERR(task);
 	}
 
 	if (task && group_leader &&
@@ -14298,8 +14292,7 @@ SYSCALL_DEFINE5(perf_event_open,
 	 * This ensures destruction of the group leader will find
 	 * the pointer to itself in perf_group_detach().
 	 */
-	fd_install(event_fd, event_file);
-	return event_fd;
+	return fd_stage(event_fd, event_file);
 
 err_context:
 	put_pmu_ctx(event->pmu_ctx);
@@ -14316,8 +14309,6 @@ SYSCALL_DEFINE5(perf_event_open,
 err_task:
 	if (task)
 		put_task_struct(task);
-err_fd:
-	put_unused_fd(event_fd);
 	return err;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 39/50] seccomp: stop putting the listener descriptor back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (37 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:14   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 40/50] KVM: stop putting descriptors " Christian Brauner
                   ` (12 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 kernel/seccomp.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 86cf4460d69e..dc275ab1e031 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1957,7 +1957,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
 	const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
 	struct seccomp_filter *prepared = NULL;
 	long ret = -EINVAL;
-	int listener = -1;
+	const struct fd_slot *listener = NULL;
 	struct file *listener_f = NULL;
 
 	/* Validate flags. */
@@ -1990,15 +1990,14 @@ static long seccomp_set_mode_filter(unsigned int flags,
 		return PTR_ERR(prepared);
 
 	if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
-		listener = get_unused_fd_flags(O_CLOEXEC);
-		if (listener < 0) {
-			ret = listener;
+		listener = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(listener)) {
+			ret = PTR_ERR(listener);
 			goto out_free;
 		}
 
 		listener_f = init_listener(prepared);
 		if (IS_ERR(listener_f)) {
-			put_unused_fd(listener);
 			ret = PTR_ERR(listener_f);
 			goto out_free;
 		}
@@ -2038,11 +2037,9 @@ static long seccomp_set_mode_filter(unsigned int flags,
 		if (ret) {
 			listener_f->private_data = NULL;
 			fput(listener_f);
-			put_unused_fd(listener);
 			seccomp_notify_detach(prepared);
 		} else {
-			fd_install(listener, listener_f);
-			ret = listener;
+			ret = fd_stage(listener, listener_f);
 		}
 	}
 out_free:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 40/50] KVM: stop putting descriptors back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (38 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 39/50] seccomp: stop putting the listener " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:15   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor " Christian Brauner
                   ` (11 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 virt/kvm/kvm_main.c | 65 +++++++++++++++++------------------------------------
 1 file changed, 21 insertions(+), 44 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d..8d3d47a6c98a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4326,27 +4326,18 @@ static const struct file_operations kvm_vcpu_stats_fops = {
 
 static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu)
 {
-	int fd;
-	struct file *file;
 	char name[15 + ITOA_MAX_LEN + 1];
 
 	snprintf(name, sizeof(name), "kvm-vcpu-stats:%d", vcpu->vcpu_id);
 
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
-
-	file = anon_inode_getfile_fmode(name, &kvm_vcpu_stats_fops, vcpu,
-					O_RDONLY, FMODE_PREAD);
-	if (IS_ERR(file)) {
-		put_unused_fd(fd);
-		return PTR_ERR(file);
-	}
+	FD_PREPARE(fdf, O_CLOEXEC,
+		   anon_inode_getfile_fmode(name, &kvm_vcpu_stats_fops, vcpu,
+					    O_RDONLY, FMODE_PREAD));
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	kvm_get_kvm(vcpu->kvm);
-	fd_install(fd, file);
-
-	return fd;
+	return fd_prepare_fd(fdf);
 }
 
 #ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
@@ -5136,24 +5127,14 @@ static const struct file_operations kvm_vm_stats_fops = {
 
 static int kvm_vm_ioctl_get_stats_fd(struct kvm *kvm)
 {
-	int fd;
-	struct file *file;
-
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
-
-	file = anon_inode_getfile_fmode("kvm-vm-stats",
-			&kvm_vm_stats_fops, kvm, O_RDONLY, FMODE_PREAD);
-	if (IS_ERR(file)) {
-		put_unused_fd(fd);
-		return PTR_ERR(file);
-	}
+	FD_PREPARE(fdf, O_CLOEXEC,
+		   anon_inode_getfile_fmode("kvm-vm-stats", &kvm_vm_stats_fops,
+					    kvm, O_RDONLY, FMODE_PREAD));
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	kvm_get_kvm(kvm);
-	fd_install(fd, file);
-
-	return fd;
+	return fd_prepare_fd(fdf);
 }
 
 #define SANITY_CHECK_MEM_REGION_FIELD(field)					\
@@ -5499,21 +5480,20 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(file_is_kvm);
 static int kvm_dev_ioctl_create_vm(unsigned long type)
 {
 	char fdname[ITOA_MAX_LEN + 1];
-	int r, fd;
 	struct kvm *kvm;
 	struct file *file;
+	const struct fd_slot *fd;
+	int r;
 
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
+	fd = fd_prepare(O_CLOEXEC);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
-	snprintf(fdname, sizeof(fdname), "%d", fd);
+	snprintf(fdname, sizeof(fdname), "%d", fd_prepare_fd(fd));
 
 	kvm = kvm_create_vm(type, fdname);
-	if (IS_ERR(kvm)) {
-		r = PTR_ERR(kvm);
-		goto put_fd;
-	}
+	if (IS_ERR(kvm))
+		return PTR_ERR(kvm);
 
 	file = anon_inode_getfile("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
 	if (IS_ERR(file)) {
@@ -5529,13 +5509,10 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
 	 */
 	kvm_uevent_notify_change(KVM_EVENT_CREATE_VM, kvm);
 
-	fd_install(fd, file);
-	return fd;
+	return fd_stage(fd, file);
 
 put_kvm:
 	kvm_put_kvm(kvm);
-put_fd:
-	put_unused_fd(fd);
 	return r;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (39 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 40/50] KVM: stop putting descriptors " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:16   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand Christian Brauner
                   ` (10 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 virt/kvm/guest_memfd.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 625e62e1a031..e0d1cb869342 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -526,17 +526,16 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
 	struct gmem_file *f;
 	struct inode *inode;
 	struct file *file;
-	int fd, err;
+	const struct fd_slot *fd;
+	int err;
 
-	fd = get_unused_fd_flags(0);
-	if (fd < 0)
-		return fd;
+	fd = fd_prepare(0);
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	f = kzalloc_obj(*f);
-	if (!f) {
-		err = -ENOMEM;
-		goto err_fd;
-	}
+	if (!f)
+		return -ENOMEM;
 
 	/* __fput() will take care of fops_put(). */
 	if (!fops_get(&kvm_gmem_fops)) {
@@ -575,8 +574,7 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
 	xa_init(&f->bindings);
 	list_add(&f->entry, &GMEM_I(inode)->gmem_file_list);
 
-	fd_install(fd, file);
-	return fd;
+	return fd_stage(fd, file);
 
 err_inode:
 	iput(inode);
@@ -584,8 +582,6 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
 	fops_put(&kvm_gmem_fops);
 err_gmem:
 	kfree(f);
-err_fd:
-	put_unused_fd(fd);
 	return err;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (40 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:17   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor " Christian Brauner
                   ` (9 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/drm_lease.c   | 20 +++++++++-----------
 drivers/gpu/drm/drm_prime.c   | 13 +++++--------
 drivers/gpu/drm/drm_syncobj.c | 44 +++++++++++++------------------------------
 3 files changed, 27 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 5d2cf724cbd7..b95747cf79a7 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -484,7 +484,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 	struct file *lessee_file = NULL;
 	struct file *lessor_file = lessor_priv->filp;
 	struct drm_file *lessee_priv;
-	int fd = -1;
+	const struct fd_slot *fd;
 	uint32_t *object_ids;
 
 	/* Can't lease without MODESET */
@@ -529,10 +529,10 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 	}
 
 	/* Allocate a file descriptor for the lease */
-	fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
-	if (fd < 0) {
+	fd = fd_prepare(cl->flags & (O_CLOEXEC | O_NONBLOCK));
+	if (IS_ERR(fd)) {
 		idr_destroy(&leases);
-		ret = fd;
+		ret = PTR_ERR(fd);
 		goto out_lessor;
 	}
 
@@ -543,7 +543,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 	if (IS_ERR(lessee)) {
 		ret = PTR_ERR(lessee);
 		idr_destroy(&leases);
-		goto out_leases;
+		goto out_lessor;
 	}
 
 	/* Clone the lessor file to create a new file for us */
@@ -562,12 +562,13 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 	lessee_priv->authenticated = 1;
 
 	/* Pass fd back to userspace */
-	drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
-	cl->fd = fd;
+	drm_dbg_lease(dev, "Returning fd %d id %d\n", fd_prepare_fd(fd),
+		      lessee->lessee_id);
+	cl->fd = fd_prepare_fd(fd);
 	cl->lessee_id = lessee->lessee_id;
 
 	/* Hook up the fd */
-	fd_install(fd, lessee_file);
+	fd_stage(fd, lessee_file);
 
 	drm_master_put(&lessor);
 	drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
@@ -576,9 +577,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 out_lessee:
 	drm_master_put(&lessee);
 
-out_leases:
-	put_unused_fd(fd);
-
 out_lessor:
 	drm_master_put(&lessor);
 	drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 9b44c78cd77f..e33d84ac7256 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -513,19 +513,16 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
 			       int *prime_fd)
 {
 	struct dma_buf *dmabuf;
-	int fd = get_unused_fd_flags(flags);
+	const struct fd_slot *fd = fd_prepare(flags);
 
-	if (fd < 0)
-		return fd;
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	dmabuf = drm_gem_prime_handle_to_dmabuf(dev, file_priv, handle, flags);
-	if (IS_ERR(dmabuf)) {
-		put_unused_fd(fd);
+	if (IS_ERR(dmabuf))
 		return PTR_ERR(dmabuf);
-	}
 
-	fd_install(fd, dmabuf->file);
-	*prime_fd = fd;
+	*prime_fd = fd_stage(fd, dmabuf->file);
 	return 0;
 }
 EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 2fa170a29a62..621858b6ac43 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -663,25 +663,14 @@ static const struct file_operations drm_syncobj_file_fops = {
  */
 int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd)
 {
-	struct file *file;
-	int fd;
-
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
-
-	file = anon_inode_getfile("syncobj_file",
-				  &drm_syncobj_file_fops,
-				  syncobj, 0);
-	if (IS_ERR(file)) {
-		put_unused_fd(fd);
-		return PTR_ERR(file);
-	}
+	FD_PREPARE(fdf, O_CLOEXEC,
+		   anon_inode_getfile("syncobj_file", &drm_syncobj_file_fops,
+				      syncobj, 0));
+	if (IS_ERR(fdf))
+		return PTR_ERR(fdf);
 
 	drm_syncobj_get(syncobj);
-	fd_install(fd, file);
-
-	*p_fd = fd;
+	*p_fd = fd_prepare_fd(fdf);
 	return 0;
 }
 EXPORT_SYMBOL(drm_syncobj_get_fd);
@@ -762,31 +751,24 @@ static int drm_syncobj_export_sync_file(struct drm_file *file_private,
 	int ret;
 	struct dma_fence *fence;
 	struct sync_file *sync_file;
-	int fd = get_unused_fd_flags(O_CLOEXEC);
+	const struct fd_slot *fd = fd_prepare(O_CLOEXEC);
 
-	if (fd < 0)
-		return fd;
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	ret = drm_syncobj_find_fence(file_private, handle, point, 0, &fence);
 	if (ret)
-		goto err_put_fd;
+		return ret;
 
 	sync_file = sync_file_create(fence);
 
 	dma_fence_put(fence);
 
-	if (!sync_file) {
-		ret = -EINVAL;
-		goto err_put_fd;
-	}
-
-	fd_install(fd, sync_file->file);
+	if (!sync_file)
+		return -EINVAL;
 
-	*p_fd = fd;
+	*p_fd = fd_stage(fd, sync_file->file);
 	return 0;
-err_put_fd:
-	put_unused_fd(fd);
-	return ret;
 }
 /**
  * drm_syncobj_open - initializes syncobj file-private structures at devnode open time

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor by hand
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (41 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:14   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns Christian Brauner
                   ` (8 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 03b41f803520..e5c0f7201cea 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1581,7 +1581,8 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
 	struct dma_fence *fence;
 	struct drm_syncobj *syncobj;
 	struct sync_file *sync_file;
-	int fd, r;
+	const struct fd_slot *fd;
+	int r;
 
 	fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence);
 	if (IS_ERR(fence))
@@ -1610,21 +1611,18 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data,
 		return r;
 
 	case AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD:
-		fd = get_unused_fd_flags(O_CLOEXEC);
-		if (fd < 0) {
+		fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(fd)) {
 			dma_fence_put(fence);
-			return fd;
+			return PTR_ERR(fd);
 		}
 
 		sync_file = sync_file_create(fence);
 		dma_fence_put(fence);
-		if (!sync_file) {
-			put_unused_fd(fd);
+		if (!sync_file)
 			return -ENOMEM;
-		}
 
-		fd_install(fd, sync_file->file);
-		info->out.handle = fd;
+		info->out.handle = fd_stage(fd, sync_file->file);
 		return 0;
 
 	default:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (42 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:15   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure Christian Brauner
                   ` (7 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 1a77a09b3377..174f1d66d9ad 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -420,7 +420,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 	struct etnaviv_gpu *gpu;
 	struct sync_file *sync_file = NULL;
 	struct ww_acquire_ctx ticket;
-	int out_fence_fd = -1;
+	const struct fd_slot *out_fence_fd = NULL;
 	struct pid *pid = get_pid(task_pid(current));
 	void *stream;
 	int ret;
@@ -504,9 +504,9 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 	}
 
 	if (args->flags & ETNA_SUBMIT_FENCE_FD_OUT) {
-		out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
-		if (out_fence_fd < 0) {
-			ret = out_fence_fd;
+		out_fence_fd = fd_prepare(O_CLOEXEC);
+		if (IS_ERR(out_fence_fd)) {
+			ret = PTR_ERR(out_fence_fd);
 			goto err_submit_cmds;
 		}
 	}
@@ -607,10 +607,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 			 */
 			goto err_submit_put;
 		}
-		fd_install(out_fence_fd, sync_file->file);
+		fd_stage(out_fence_fd, sync_file->file);
 	}
 
-	args->fence_fd = out_fence_fd;
+	args->fence_fd = out_fence_fd ? fd_prepare_fd(out_fence_fd) : -1;
 	args->fence = submit->out_fence_id;
 
 err_submit_job:
@@ -623,8 +623,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 	ww_acquire_fini(&ticket);
 
 err_submit_cmds:
-	if (ret && (out_fence_fd >= 0))
-		put_unused_fd(out_fence_fd);
 	kvfree(stream);
 	kvfree(bos);
 	kvfree(relocs);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (43 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:18   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the " Christian Brauner
                   ` (6 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/accel/habanalabs/common/memory.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index 361cff577381..1559442cd56f 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -1861,11 +1861,13 @@ static int export_dmabuf(struct hl_ctx *ctx,
 {
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct hl_device *hdev = ctx->hdev;
-	CLASS(get_unused_fd, fd)(flags);
+	const struct fd_slot *fd = fd_prepare(flags);
 
-	if (fd < 0) {
-		dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd);
-		return fd;
+	if (IS_ERR(fd)) {
+		int rc = PTR_ERR(fd);
+
+		dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", rc);
+		return rc;
 	}
 
 	exp_info.ops = &habanalabs_dmabuf_ops;
@@ -1889,8 +1891,7 @@ static int export_dmabuf(struct hl_ctx *ctx,
 	 */
 	get_file(ctx->hpriv->file_priv->filp);
 
-	*dmabuf_fd = fd;
-	fd_install(take_fd(fd), hl_dmabuf->dmabuf->file);
+	*dmabuf_fd = fd_stage(fd, hl_dmabuf->dmabuf->file);
 
 	return 0;
 }

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the descriptor back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (44 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:21   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns Christian Brauner
                   ` (5 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/xen/gntdev-dmabuf.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index 83b0df460894..a3ecc7c83974 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -357,10 +357,10 @@ static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args)
 {
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct gntdev_dmabuf *gntdev_dmabuf __free(kfree) = NULL;
-	CLASS(get_unused_fd, ret)(O_CLOEXEC);
+	const struct fd_slot *fd = fd_prepare(O_CLOEXEC);
 
-	if (ret < 0)
-		return ret;
+	if (IS_ERR(fd))
+		return PTR_ERR(fd);
 
 	gntdev_dmabuf = kzalloc_obj(*gntdev_dmabuf);
 	if (!gntdev_dmabuf)
@@ -388,17 +388,17 @@ static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args)
 	if (IS_ERR(gntdev_dmabuf->dmabuf))
 		return PTR_ERR(gntdev_dmabuf->dmabuf);
 
-	gntdev_dmabuf->fd = ret;
-	args->fd = ret;
+	gntdev_dmabuf->fd = fd_prepare_fd(fd);
+	args->fd = fd_prepare_fd(fd);
 
-	pr_debug("Exporting DMA buffer with fd %d\n", ret);
+	pr_debug("Exporting DMA buffer with fd %d\n", fd_prepare_fd(fd));
 
 	get_file(gntdev_dmabuf->priv->filp);
 	mutex_lock(&args->dmabuf_priv->lock);
 	list_add(&gntdev_dmabuf->next, &args->dmabuf_priv->exp_list);
 	mutex_unlock(&args->dmabuf_priv->lock);
 
-	fd_install(take_fd(ret), no_free_ptr(gntdev_dmabuf)->dmabuf->file);
+	fd_stage(fd, no_free_ptr(gntdev_dmabuf)->dmabuf->file);
 	return 0;
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (45 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:18   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf " Christian Brauner
                   ` (4 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/iio/industrialio-buffer.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 2c9ec93dff47..9fb15bf82d0a 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -2041,7 +2041,7 @@ static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg
 	int __user *ival = (int __user *)arg;
 	struct iio_dev_buffer_pair *ib;
 	struct iio_buffer *buffer;
-	int fd, idx, ret;
+	int idx, ret, fdno;
 
 	if (copy_from_user(&idx, ival, sizeof(idx)))
 		return -EFAULT;
@@ -2067,26 +2067,18 @@ static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg
 	ib->indio_dev = indio_dev;
 	ib->buffer = buffer;
 
-	fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
-			      ib, O_RDWR | O_CLOEXEC);
-	if (fd < 0) {
-		ret = fd;
+	FD_PREPARE(fdf, O_RDWR | O_CLOEXEC,
+		   anon_inode_getfile("iio:buffer", &iio_buffer_chrdev_fileops,
+				      ib, O_RDWR | O_CLOEXEC));
+	if (IS_ERR(fdf)) {
+		ret = PTR_ERR(fdf);
 		goto error_free_ib;
 	}
 
-	if (copy_to_user(ival, &fd, sizeof(fd))) {
-		/*
-		 * "Leak" the fd, as there's not much we can do about this
-		 * anyway. 'fd' might have been closed already, as
-		 * anon_inode_getfd() called fd_install() on it, which made
-		 * it reachable by userland.
-		 *
-		 * Instead of allowing a malicious user to play tricks with
-		 * us, rely on the process exit path to do any necessary
-		 * cleanup, as in releasing the file, if still needed.
-		 */
+	fdno = fd_prepare_fd(fdf);
+	/* The staged file is dropped with its descriptor if this faults. */
+	if (copy_to_user(ival, &fdno, sizeof(fdno)))
 		return -EFAULT;
-	}
 
 	return 0;
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf descriptor when the ioctl returns
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (46 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:20   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure Christian Brauner
                   ` (3 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/misc/fastrpc.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 90fd669636ec..24b84019bbd7 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -7,6 +7,7 @@
 #include <linux/dma-buf.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-resv.h>
+#include <linux/file.h>
 #include <linux/idr.h>
 #include <linux/list.h>
 #include <linux/miscdevice.h>
@@ -1804,6 +1805,7 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct fastrpc_buf *buf = NULL;
 	int err;
+	const struct fd_slot *fd;
 
 	if (copy_from_user(&bp, argp, sizeof(bp)))
 		return -EFAULT;
@@ -1822,23 +1824,16 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
 		return err;
 	}
 
-	bp.fd = dma_buf_fd(buf->dmabuf, O_ACCMODE);
-	if (bp.fd < 0) {
+	fd = fd_prepare(O_ACCMODE);
+	if (IS_ERR(fd)) {
 		dma_buf_put(buf->dmabuf);
 		return -EINVAL;
 	}
+	bp.fd = fd_stage(fd, buf->dmabuf->file);
 
-	if (copy_to_user(argp, &bp, sizeof(bp))) {
-		/*
-		 * The usercopy failed, but we can't do much about it, as
-		 * dma_buf_fd() already called fd_install() and made the
-		 * file descriptor accessible for the current process. It
-		 * might already be closed and dmabuf no longer valid when
-		 * we reach this point. Therefore "leak" the fd and rely on
-		 * the process exit path to do any required cleanup.
-		 */
+	/* The staged file is dropped with its descriptor if this faults. */
+	if (copy_to_user(argp, &bp, sizeof(bp)))
 		return -EFAULT;
-	}
 
 	return 0;
 }

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (47 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf " Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:21   ` sashiko-bot
  2026-09-15 11:31 ` [PATCH RFC POC 50/50] Drivers: hv: mshv: " Christian Brauner
                   ` (2 subsequent siblings)
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/iommu/iommufd/eventq.c | 39 +++++++++++++++++----------------------
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c
index 747dd5155121..f5fdc6cdf0a1 100644
--- a/drivers/iommu/iommufd/eventq.c
+++ b/drivers/iommu/iommufd/eventq.c
@@ -412,9 +412,9 @@ static int iommufd_eventq_fops_release(struct inode *inode, struct file *filep)
 		.release = iommufd_eventq_fops_release,                        \
 	})
 
-static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
-			       struct iommufd_ctx *ictx,
-			       const struct file_operations *fops)
+static const struct fd_slot *iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
+				struct iommufd_ctx *ictx,
+				const struct file_operations *fops)
 {
 	struct file *filep;
 
@@ -425,14 +425,14 @@ static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
 	/* The filep is fput() by the core code during failure */
 	filep = anon_inode_getfile(name, fops, eventq, O_RDWR);
 	if (IS_ERR(filep))
-		return PTR_ERR(filep);
+		return ERR_CAST(filep);
 
 	eventq->ictx = ictx;
 	iommufd_ctx_get(eventq->ictx);
 	eventq->filep = filep;
 	refcount_inc(&eventq->obj.users);
 
-	return get_unused_fd_flags(O_CLOEXEC);
+	return fd_prepare(O_CLOEXEC);
 }
 
 static const struct file_operations iommufd_fault_fops =
@@ -442,7 +442,7 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 {
 	struct iommu_fault_alloc *cmd = ucmd->cmd;
 	struct iommufd_fault *fault;
-	int fdno;
+	const struct fd_slot *fdno;
 	int rc;
 
 	if (cmd->flags)
@@ -458,22 +458,19 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
 
 	fdno = iommufd_eventq_init(&fault->common, "[iommufd-pgfault]",
 				   ucmd->ictx, &iommufd_fault_fops);
-	if (fdno < 0)
-		return fdno;
+	if (IS_ERR(fdno))
+		return PTR_ERR(fdno);
 
 	cmd->out_fault_id = fault->common.obj.id;
-	cmd->out_fault_fd = fdno;
+	cmd->out_fault_fd = fd_prepare_fd(fdno);
 
 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
 	if (rc)
-		goto out_put_fdno;
+		return rc;
 
-	fd_install(fdno, fault->common.filep);
+	fd_stage(fdno, fault->common.filep);
 
 	return 0;
-out_put_fdno:
-	put_unused_fd(fdno);
-	return rc;
 }
 
 int iommufd_fault_iopf_handler(struct iopf_group *group)
@@ -506,7 +503,7 @@ int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd)
 	struct iommu_veventq_alloc *cmd = ucmd->cmd;
 	struct iommufd_veventq *veventq;
 	struct iommufd_viommu *viommu;
-	int fdno;
+	const struct fd_slot *fdno;
 	int rc;
 
 	if (cmd->flags || cmd->__reserved ||
@@ -543,24 +540,22 @@ int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd)
 
 	fdno = iommufd_eventq_init(&veventq->common, "[iommufd-viommu-event]",
 				   ucmd->ictx, &iommufd_veventq_fops);
-	if (fdno < 0) {
-		rc = fdno;
+	if (IS_ERR(fdno)) {
+		rc = PTR_ERR(fdno);
 		goto out_abort;
 	}
 
 	cmd->out_veventq_id = veventq->common.obj.id;
-	cmd->out_veventq_fd = fdno;
+	cmd->out_veventq_fd = fd_prepare_fd(fdno);
 
 	rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
 	if (rc)
-		goto out_put_fdno;
+		goto out_abort;
 
 	iommufd_object_finalize(ucmd->ictx, &veventq->common.obj);
-	fd_install(fdno, veventq->common.filep);
+	fd_stage(fdno, veventq->common.filep);
 	goto out_unlock_veventqs;
 
-out_put_fdno:
-	put_unused_fd(fdno);
 out_abort:
 	iommufd_object_abort_and_destroy(ucmd->ictx, &veventq->common.obj);
 out_unlock_veventqs:

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* [PATCH RFC POC 50/50] Drivers: hv: mshv: stop putting descriptors back on failure
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (48 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure Christian Brauner
@ 2026-09-15 11:31 ` Christian Brauner
  2026-09-15 12:19   ` sashiko-bot
  2026-09-15 16:02 ` [PATCH RFC POC 00/50] file: handle files on syscall exit Linus Torvalds
  2026-09-15 17:51 ` Jann Horn
  51 siblings, 1 reply; 108+ messages in thread
From: Christian Brauner @ 2026-09-15 11:31 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv,
	Christian Brauner (Amutable)

Rely on the fd exit path machinery.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 drivers/hv/mshv_root_main.c | 27 +++++++--------------------
 drivers/hv/mshv_vtl_main.c  | 20 +++++---------------
 2 files changed, 12 insertions(+), 35 deletions(-)

diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index cc2cfce2aefd..c95cee0bae85 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1072,8 +1072,6 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	struct mshv_vp *vp;
 	struct page *intercept_msg_page, *register_page, *ghcb_page;
 	struct hv_stats_page *stats_pages[2];
-	struct file *file;
-	int fd;
 	long ret;
 
 	if (copy_from_user(&args, arg, sizeof(args)))
@@ -1148,19 +1146,14 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	if (ret)
 		goto put_partition;
 
-	fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
-	if (fd < 0) {
-		ret = fd;
+	FD_PREPARE(fdf, O_RDWR | O_CLOEXEC,
+		   anon_inode_getfile("mshv_vp", &mshv_vp_fops, vp,
+				      O_RDWR | O_CLOEXEC));
+	if (IS_ERR(fdf)) {
+		ret = PTR_ERR(fdf);
 		goto remove_debugfs_vp;
 	}
 
-	file = anon_inode_getfile("mshv_vp", &mshv_vp_fops, vp,
-				  O_RDWR | O_CLOEXEC);
-	if (IS_ERR(file)) {
-		ret = PTR_ERR(file);
-		goto put_unused_vp_fd;
-	}
-
 	/* already exclusive with the partition mutex for all ioctls */
 	partition->pt_vp_count++;
 	/*
@@ -1171,17 +1164,11 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	 */
 	smp_store_release(&partition->pt_vp_array[args.vp_index], vp);
 
-	/*
-	 * fd_install() is the userspace-visibility commit point.  Must be the
-	 * last operation that can fail or be observed.
-	 */
-	fd_install(fd, file);
-	ret = fd;
+	/* The syscall exit installs the file; nothing after this can fail. */
+	ret = fd_prepare_fd(fdf);
 
 	goto out;
 
-put_unused_vp_fd:
-	put_unused_fd(fd);
 remove_debugfs_vp:
 	mshv_debugfs_vp_remove(vp);
 put_partition:
diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c
index 6e3c11c68171..f14203d76da1 100644
--- a/drivers/hv/mshv_vtl_main.c
+++ b/drivers/hv/mshv_vtl_main.c
@@ -114,29 +114,19 @@ static long
 mshv_ioctl_create_vtl(void __user *user_arg, struct device *module_dev)
 {
 	struct mshv_vtl *vtl;
-	struct file *file;
-	int fd;
 
 	vtl = kzalloc_obj(*vtl);
 	if (!vtl)
 		return -ENOMEM;
 
-	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0) {
-		kfree(vtl);
-		return fd;
-	}
-	file = anon_inode_getfile("mshv_vtl", &mshv_vtl_fops,
-				  vtl, O_RDWR);
-	if (IS_ERR(file)) {
-		put_unused_fd(fd);
+	FD_PREPARE(fdf, O_CLOEXEC,
+		   anon_inode_getfile("mshv_vtl", &mshv_vtl_fops, vtl, O_RDWR));
+	if (IS_ERR(fdf)) {
 		kfree(vtl);
-		return PTR_ERR(file);
+		return PTR_ERR(fdf);
 	}
 	vtl->module_dev = module_dev;
-	fd_install(fd, file);
-
-	return fd;
+	return fd_prepare_fd(fdf);
 }
 
 static long

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 11/50] MIPS: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 11/50] MIPS: " Christian Brauner
@ 2026-09-15 11:45   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:45 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: io-uring, linux-gpio, Jens Axboe, linuxppc-dev, linux-arm-msm,
	David Airlie, linux-snps-arc, Michael S. Tsirkin, linux-csky,
	Jan Kara, linux-kernel, linux-um, Ingo Molnar, virtualization,
	Peter Zijlstra, linux-mips, linux-hyperv, Alexander Viro, bpf,
	dri-devel, linux-fsdevel, linux-openrisc, sparclinux,
	linux-hexagon, linux-sh, linux-parisc, Eugenio Perez, linux-mm,
	Jann Horn, linux-alpha, linux-m68k, Oleg Nesterov, kvm,
	Christian Brauner (Amutable), kexec, linux-arm-kernel

> Add TIF_FD_SLOTS to the syscall exit work. The return path rereads
> the flags after the system call and calls syscall_trace_leave() for
> any of the exit work bits which commits the reservations before audit
> and the ptrace exit stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=11


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 07/50] csky: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 07/50] csky: " Christian Brauner
@ 2026-09-15 11:47   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:47 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-mm, Ingo Molnar, virtualization, Michael S. Tsirkin,
	Jens Axboe, Peter Zijlstra, David Airlie, linux-sh, linux-arm-msm,
	linux-snps-arc, bpf, linux-fsdevel, linux-arm-kernel, linux-csky,
	sparclinux, Christian Brauner (Amutable), linux-parisc, linux-um,
	Eugenio Perez, linux-openrisc, linux-kernel, kexec, dri-devel,
	linux-hyperv, Jann Horn, Jan Kara, linux-hexagon, kvm,
	Oleg Nesterov, linux-m68k, linux-mips, linux-gpio, Alexander Viro,
	linux-alpha, linuxppc-dev, io-uring

> Add TIF_FD_SLOTS and test it after the untraced system call has
> stored its return value. A task that reserved descriptors joins the
> traced path, where syscall_trace_exit() commits them before audit and
> the ptrace exit stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=7


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 10/50] microblaze: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 10/50] microblaze: " Christian Brauner
@ 2026-09-15 11:48   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:48 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-arm-msm, kexec, sparclinux, linux-sh, bpf, linux-mm,
	linux-snps-arc, Michael S. Tsirkin, linux-openrisc, kvm,
	linux-fsdevel, Peter Zijlstra, linux-kernel, linux-m68k,
	Eugenio Perez, linux-arm-kernel, Jens Axboe, Jann Horn,
	Ingo Molnar, Jan Kara, dri-devel, linux-um, virtualization,
	Christian Brauner (Amutable), Alexander Viro, io-uring,
	linux-gpio, David Airlie, linux-hyperv, Oleg Nesterov,
	linux-alpha, linux-csky, linux-hexagon, linuxppc-dev,
	linux-parisc, linux-mips

> Add TIF_FD_SLOTS to the syscall work mask. The return path rereads
> the flags after the system call and calls do_syscall_trace_leave()
> for any of them which commits the reservations before audit and the
> ptrace exit stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=10


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 06/50] arm64: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 06/50] arm64: " Christian Brauner
@ 2026-09-15 11:48   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:48 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: David Airlie, linux-parisc, virtualization, linux-mips,
	Oleg Nesterov, dri-devel, Jens Axboe, linux-um,
	Christian Brauner (Amutable), Eugenio Perez, linux-kernel,
	linux-hyperv, Alexander Viro, linux-fsdevel, linux-arm-kernel,
	sparclinux, linux-csky, linux-sh, Peter Zijlstra, linux-snps-arc,
	kexec, Ingo Molnar, io-uring, kvm, linux-hexagon, bpf,
	Michael S. Tsirkin, linuxppc-dev, linux-m68k, linux-alpha,
	linux-mm, linux-gpio, linux-arm-msm, linux-openrisc, Jann Horn,
	Jan Kara

> Add TIF_FD_SLOTS to the syscall work bits. el0_svc_common() rereads
> the flags after the system call and takes the trace exit for any of
> them. So a task that reserved descriptors ends up in
> syscall_trace_exit() which commits them before audit and the ptrace exit
> stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=6


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 04/50] ARC: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 04/50] ARC: " Christian Brauner
@ 2026-09-15 11:48   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:48 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-hexagon, linux-snps-arc, linux-arm-msm, Michael S. Tsirkin,
	Jann Horn, Oleg Nesterov, sparclinux, linux-fsdevel, linux-mm,
	linux-sh, virtualization, Peter Zijlstra, linux-m68k, linux-mips,
	linux-parisc, linux-openrisc, kvm, linux-csky, Jens Axboe,
	linux-gpio, bpf, linux-arm-kernel, linux-kernel, linux-hyperv,
	linux-um, Jan Kara, linux-alpha, Eugenio Perez,
	Christian Brauner (Amutable), dri-devel, David Airlie,
	linuxppc-dev, kexec, io-uring, Alexander Viro, Ingo Molnar

> Add TIF_FD_SLOTS and test it on the untraced return from a system
> call. A task that reserved descriptors takes the tracesys_exit path,
> where syscall_trace_exit() commits them before the ptrace exit stop.
> The traced path already ends up there.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=4


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 08/50] hexagon: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 08/50] hexagon: " Christian Brauner
@ 2026-09-15 11:49   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:49 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Michael S. Tsirkin, Jann Horn, Oleg Nesterov, linux-m68k, kexec,
	linux-parisc, sparclinux, linux-csky, David Airlie, linux-hexagon,
	linux-snps-arc, linux-fsdevel, Peter Zijlstra, linux-alpha,
	linux-sh, linux-hyperv, linux-mips, bpf, linux-openrisc,
	linux-arm-kernel, kvm, Jens Axboe, linux-arm-msm, Ingo Molnar,
	linux-gpio, linux-um, Jan Kara, linuxppc-dev, dri-devel,
	Christian Brauner (Amutable), Alexander Viro, virtualization,
	Eugenio Perez, linux-kernel, linux-mm, io-uring

> Add TIF_FD_SLOTS and test it in do_trap0() once the system call has
> returned, before the ptrace exit stop gets to see the result.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=8


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 09/50] m68k: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 09/50] m68k: " Christian Brauner
@ 2026-09-15 11:50   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:50 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: kexec, linux-openrisc, io-uring, linux-arm-msm, linux-mips,
	Eugenio Perez, linux-mm, linux-sh, Jann Horn, virtualization,
	linux-kernel, David Airlie, bpf, linux-hyperv, kvm, sparclinux,
	linux-arm-kernel, linuxppc-dev, linux-hexagon, linux-gpio,
	linux-m68k, linux-alpha, Ingo Molnar, linux-um,
	Michael S. Tsirkin, linux-parisc, Peter Zijlstra, Jan Kara,
	dri-devel, Christian Brauner (Amutable), linux-snps-arc,
	linux-csky, Jens Axboe, Oleg Nesterov, linux-fsdevel,
	Alexander Viro

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] m68k: single-step SIGTRAP lost on fd-allocating syscalls
--

commit 731b1387fc76d92d165ee1f28de694e3d228627b
Author: Christian Brauner <brauner@kernel.org>

m68k: commit fds on syscall exit

Add TIF_FD_SLOTS and test it on the untraced return from a system
call in all three entry paths. A task that reserved descriptors calls
syscall_trace_leave(), which commits them before the ptrace exit stop.

[ ... ]

> diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
> index 338b474910f74..9e4471f681652 100644
> --- a/arch/m68k/kernel/entry.S
> +++ b/arch/m68k/kernel/entry.S
> @@ -229,6 +229,8 @@ ret_from_syscall:
>  syscall_exit_work:
>  	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
>  	bnes	1b			| if so, skip resched, signals
> +	btst	#4,%a1@(TINFO_FLAGS+2)	| TIF_FD_SLOTS: commit descriptors
> +	jne	do_trace_exit

[Severity: High]
Does this new branch cause delayed trace (single-step) SIGTRAPs to be lost? 

If a process is being single-stepped (TIF_DELAYED_TRACE is set) and executes a 
syscall that allocates file descriptors (TIF_FD_SLOTS is set), this 
unconditionally branches to do_trace_exit. 

Looking at do_trace_exit, it executes syscall_trace_leave() and then directly
jumps to the exception return path, bypassing the jmi do_delayed_trace logic 
completely. 

This means single-stepping over a system call like open() could fail to 
deliver the expected SIGTRAP, which might break debugger functionality.

>  	lslw	#1,%d0
>  	jcs	do_trace_exit
>  	jmi	do_delayed_trace

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=9

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 03/50] alpha: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 03/50] alpha: " Christian Brauner
@ 2026-09-15 11:50   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:50 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-arm-msm, linux-kernel, Jens Axboe, linux-mips,
	linux-openrisc, kvm, sparclinux, linux-hyperv, David Airlie,
	linux-mm, bpf, Ingo Molnar, Michael S. Tsirkin, linux-hexagon,
	linux-parisc, Jan Kara, linux-csky, Oleg Nesterov, linux-snps-arc,
	linux-m68k, dri-devel, Eugenio Perez, linux-sh,
	Christian Brauner (Amutable), io-uring, Peter Zijlstra,
	Alexander Viro, linux-arm-kernel, linux-um, linux-fsdevel,
	linux-gpio, linuxppc-dev, Jann Horn, virtualization, linux-alpha,
	kexec

> Add TIF_FD_SLOTS and test it once the untraced system call has stored
> its result. A task that reserved descriptors calls syscall_trace_leave()
> and joins ret_from_sys_call with the flag gone.
> 
> We mirror the traced error path where the switch stack is set up and the
> return address and the syscall restart state are placed in callee-saved
> registers.
> 
> Btw, let's remove alpha... It's a pain.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=3


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 02/50] entry: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 02/50] entry: commit fds " Christian Brauner
@ 2026-09-15 11:52   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:52 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-um, linux-arm-kernel, linux-arm-msm, linux-hexagon,
	linux-csky, linuxppc-dev, virtualization,
	Christian Brauner (Amutable), Peter Zijlstra, Alexander Viro,
	Michael S. Tsirkin, linux-hyperv, Oleg Nesterov, Eugenio Perez,
	linux-mm, linux-gpio, linux-openrisc, linux-sh, linux-m68k, kexec,
	Jan Kara, io-uring, sparclinux, David Airlie, kvm, linux-alpha,
	linux-fsdevel, linux-snps-arc, Jens Axboe, Ingo Molnar,
	linux-kernel, bpf, Jann Horn, linux-mips, linux-parisc, dri-devel

> Reserving a descriptor with fd_prepare() marks the task with
> SYSCALL_WORK_FD_SLOTS. The syscall exit path already tests the
> syscall work bits so a syscall that deferred nothing pays nothing new
> and one that did takes the slow path. syscall_exit_work() commits the
> reservations before audit and ptrace.
> 
> Architectures without the generic entry code grow TIF_FD_SLOTS bit in
> their syscall exit work in the following patches.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=2


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 12/50] nios2: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 12/50] nios2: " Christian Brauner
@ 2026-09-15 11:54   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:54 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-arm-msm, linux-um, linux-hexagon, linux-mips, linux-parisc,
	virtualization, Jens Axboe, linux-hyperv, io-uring,
	Michael S. Tsirkin, linux-arm-kernel, Alexander Viro, linux-csky,
	sparclinux, Christian Brauner (Amutable), linux-gpio, Ingo Molnar,
	linux-kernel, linux-mm, linux-m68k, David Airlie, dri-devel,
	Eugenio Perez, bpf, linux-snps-arc, linuxppc-dev, linux-sh,
	linux-alpha, linux-fsdevel, Jan Kara, Peter Zijlstra, kexec,
	Jann Horn, linux-openrisc, Oleg Nesterov, kvm

> Add TIF_FD_SLOTS and test it once the untraced system call has had
> its return code translated into the r2 and r7 pair userspace sees.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=12


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture
  2026-09-15 11:31 ` [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture Christian Brauner
@ 2026-09-15 11:54   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:54 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-gpio, Michael S. Tsirkin, Oleg Nesterov, linux-sh,
	dri-devel, linux-alpha, linux-fsdevel, sparclinux, linux-kernel,
	kvm, Alexander Viro, virtualization, linux-um, linux-mm,
	linux-snps-arc, David Airlie, linux-arm-kernel, Peter Zijlstra,
	linux-csky, linux-hyperv, Ingo Molnar, Jan Kara, linux-m68k,
	linux-parisc, linux-hexagon, Jens Axboe, linux-arm-msm,
	Christian Brauner (Amutable), kexec, linux-openrisc, bpf,
	Jann Horn, linux-mips, linuxppc-dev, Eugenio Perez, io-uring

> Every architecture now either uses the generic entry code or provides
> TIF_FD_SLOTS. The fallback that deferred without ever committing
> can go. Make it a build error instead. A new architecture can't grow
> fd_prepare() callers without the syscall exit hook.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=19


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 15/50] sh: commit fds on syscall exit
  2026-09-15 11:31 ` [PATCH RFC POC 15/50] sh: " Christian Brauner
@ 2026-09-15 11:55   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:55 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-gpio, Eugenio Perez, Jan Kara, Ingo Molnar, linux-hexagon,
	David Airlie, linux-kernel, linux-arm-kernel, Jann Horn,
	Alexander Viro, bpf, linux-mips, kvm, dri-devel, linux-csky,
	linux-openrisc, linux-sh, linuxppc-dev, io-uring, Peter Zijlstra,
	virtualization, kexec, linux-alpha, linux-parisc, linux-m68k,
	Michael S. Tsirkin, sparclinux, linux-um, linux-arm-msm,
	Christian Brauner (Amutable), linux-mm, linux-fsdevel,
	Oleg Nesterov, linux-snps-arc, Jens Axboe, linux-hyperv

> Add TIF_FD_SLOTS to the syscall work mask. syscall_exit rereads the
> flags after the system call and goes to syscall_exit_work for any bit
> in the all-work mask, but hands over a copy shifted right by eight
> when the bit was in the upper byte. Reload the flags there and test
> the full mask, so that the bit reaches do_syscall_trace_leave().
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=15


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 01/50] file: install files on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 01/50] file: install " Christian Brauner
@ 2026-09-15 11:55   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:55 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-fsdevel, linux-m68k, linux-kernel, linux-snps-arc, kvm, bpf,
	io-uring, linux-alpha, kexec, Jens Axboe, Michael S. Tsirkin,
	dri-devel, sparclinux, linux-parisc, linux-mm, linux-openrisc,
	linux-gpio, linux-arm-msm, linux-hexagon, Jann Horn, Ingo Molnar,
	Oleg Nesterov, David Airlie, Eugenio Perez, linux-csky,
	Alexander Viro, linux-mips, linux-um, linuxppc-dev,
	Peter Zijlstra, virtualization, Jan Kara, linux-hyperv, linux-sh,
	linux-arm-kernel, Christian Brauner (Amutable)

> So we've spoken about this idea quite a few times over the years that
> we could reserve fds and files on a task and then install or a clean
> them up on syscall success or error and get rid of most of the
> complicated cleanup dance that we have.
> 
> My original approach to this had been to implement FD_PREPARE() based on
> cleanup guards and use scopes to make this happen. The other idea was
> what I'm illustrating here. It is overall equally robust and makes the
> install fd and file pattern work even if it there's a ton of cleanup or
> setup work happening in the middle. This is particular evident in the
> conversions of various dma/drm code later in the series.
> 
> So this lets the syscall path do the install. fd_prepare() allocates a
> descriptor like get_unused_fd_flags() does and records it in a slot on
> the task. fd_stage() attaches the file to that slot and returns the
> [ ... ]
> fdtagble with outstanding reservations. Kernel threads never return to
> userspace so nothing would commit. Anything left at exit is a bug and
> gets warned about and dropped.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=1


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 17/50] um: commit fds on syscall exit
  2026-09-15 11:31 ` [PATCH RFC POC 17/50] um: " Christian Brauner
@ 2026-09-15 11:55   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:55 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: io-uring, linux-mm, Ingo Molnar, linux-hexagon, virtualization,
	Alexander Viro, linux-arm-kernel, linux-gpio, Jann Horn,
	linux-fsdevel, dri-devel, linux-snps-arc, linux-m68k, Jens Axboe,
	linux-parisc, linux-mips, linux-openrisc, linux-um, linux-hyperv,
	kexec, linuxppc-dev, Michael S. Tsirkin, linux-kernel,
	Eugenio Perez, Christian Brauner (Amutable), Oleg Nesterov,
	linux-csky, linux-arm-msm, linux-alpha, linux-sh, Jan Kara, kvm,
	bpf, sparclinux, Peter Zijlstra, David Airlie

> Add TIF_FD_SLOTS. handle_syscall() calls syscall_trace_leave() after
> every system call, so test the flag there and commit the reservations
> before audit and the ptrace exit stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=17


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 16/50] sparc: commit fds on syscall exit
  2026-09-15 11:31 ` [PATCH RFC POC 16/50] sparc: " Christian Brauner
@ 2026-09-15 11:57   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:57 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-csky, linux-snps-arc, Alexander Viro, Jens Axboe, io-uring,
	Jan Kara, Ingo Molnar, virtualization, linux-parisc, linux-um,
	David Airlie, linux-alpha, linux-gpio, linux-mips,
	Christian Brauner (Amutable), Oleg Nesterov, linuxppc-dev,
	linux-hexagon, linux-arm-kernel, Michael S. Tsirkin, dri-devel,
	kvm, linux-sh, linux-kernel, Jann Horn, bpf, linux-arm-msm,
	Eugenio Perez, linux-openrisc, linux-m68k, linux-fsdevel,
	linux-mm, Peter Zijlstra, kexec, sparclinux, linux-hyperv

> Add TIF_FD_SLOTS and test it together with the other syscall exit
> work on the way out of a system call. A task that reserved
> descriptors calls syscall_trace() on sparc32 and syscall_trace_leave()
> on sparc64.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=16


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 14/50] parisc: commit fds on syscall exit
  2026-09-15 11:31 ` [PATCH RFC POC 14/50] parisc: " Christian Brauner
@ 2026-09-15 11:59   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:59 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Peter Zijlstra, linux-sh, virtualization, Eugenio Perez,
	Alexander Viro, Oleg Nesterov, linux-csky, linux-m68k, dri-devel,
	io-uring, kexec, David Airlie, linux-um,
	Christian Brauner (Amutable), linux-fsdevel, kvm, linux-kernel,
	linux-hyperv, linux-alpha, Michael S. Tsirkin, Jan Kara,
	Jens Axboe, linux-arm-msm, linux-parisc, linux-arm-kernel,
	linuxppc-dev, bpf, Ingo Molnar, linux-gpio, linux-mips,
	linux-hexagon, linux-snps-arc, linux-openrisc, linux-mm,
	sparclinux, Jann Horn

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] parisc: syscall fast path exposes uninitialized pt_regs to ptrace
--

commit 38a139df8c7c61e11fc9314b5f43e371c71a8356
Author: Christian Brauner <brauner@kernel.org>

parisc: commit fds on syscall exit

This commit adds TIF_FD_SLOTS and tests it in syscall_exit once the return
value has been saved. A task that reserved descriptors calls
do_syscall_trace_exit() to commit descriptors and then continues with the
usual checks.

> diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
> index e04c5d806c105..c5807cf6fbd8d 100644
> --- a/arch/parisc/kernel/entry.S
> +++ b/arch/parisc/kernel/entry.S

[ ... ]

> @@ -1765,6 +1767,16 @@ syscall_do_signal:
>  
>  	b,n     syscall_check_sig
>  
> +syscall_do_fd_slots:
> +	mfctl	%cr30,%r1
> +#ifdef CONFIG_64BIT
> +	ldo	-16(%r30),%r29			/* Reference param save area */
> +#endif
> +	ldo	TASK_REGS(%r1),%r26		/* struct pt_regs *regs */
> +	BL	do_syscall_trace_exit,%r2

[Severity: High]
Does this expose uninitialized kernel stack memory to a tracer?

When a process executes a system call that reserves a file descriptor slot,
it enters via the fast path which only saves a minimal set of registers to
TASK_REGS. If TIF_FD_SLOTS is set, the fast path directly invokes
do_syscall_trace_exit() here before all registers (like %r3-%r18) are saved.

> +	nop
> +	b,n	syscall_check_resched
> +
>  syscall_restore:
>  	mfctl	%cr30,%r1
>  

[ ... ]

> diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
> index 1d9e210702e1f..f142766792afa 100644
> --- a/arch/parisc/kernel/ptrace.c
> +++ b/arch/parisc/kernel/ptrace.c

[ ... ]

> @@ -381,6 +382,9 @@ void do_syscall_trace_exit(struct pt_regs *regs)
>  	int stepping = test_thread_flag(TIF_SINGLESTEP) ||
>  		test_thread_flag(TIF_BLOCKSTEP);
>  
> +	if (test_thread_flag(TIF_FD_SLOTS))
> +		fd_slots_commit(regs);
> +
>  	audit_syscall_exit(regs);
>  
>  #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS

[ ... ]

>  	if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
>  		ptrace_report_syscall_exit(regs, stepping);
>  }

[Severity: High]
If a tracer attaches concurrently while the process is blocked in a file
descriptor allocation syscall, setting TIF_SYSCALL_TRACE, won't this call pass
the incompletely initialized pt_regs from the fast path to the tracing
subsystem?

This could allow an unprivileged user attaching a tracer to their own process
to read uninitialized kernel memory via PTRACE_GETREGS. Also, tracer
modifications via PTRACE_SETREGS to these uninitialized registers would be
ignored because the fast path does not properly restore them before returning
to userspace.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=14

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 05/50] ARM: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 05/50] ARM: " Christian Brauner
@ 2026-09-15 11:59   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 11:59 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-um, linux-openrisc, Michael S. Tsirkin, Peter Zijlstra, bpf,
	linux-csky, linux-m68k, linux-gpio, Eugenio Perez, virtualization,
	Jan Kara, Oleg Nesterov, linux-hyperv, linux-fsdevel, linux-alpha,
	dri-devel, linux-kernel, linux-mm, linux-snps-arc, linux-parisc,
	io-uring, Ingo Molnar, kvm, Jens Axboe, David Airlie,
	linuxppc-dev, Alexander Viro, Jann Horn, linux-sh, linux-arm-msm,
	linux-hexagon, linux-arm-kernel, sparclinux, linux-mips,
	Christian Brauner (Amutable), kexec

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] arm: redundant TIF_FD_SLOTS check due to bit-shift overlap
--

commit bdf52635177f575c1b58cdb7e902386551a36647
Author: Christian Brauner <brauner@kernel.org>

ARM: commit fds on syscall exit

Add TIF_FD_SLOTS and test it where the syscall return path decides
between the syscall work and the plain work pending slow path. A task
that reserved descriptors goes through __sys_trace_return_nosave
where syscall_trace_exit() commits them before audit and the ptrace
exit stop.

> diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
> index 88336a1292bb7..59a70d90b0b61 100644
> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S

[ ... ]

> @@ -83,6 +83,8 @@ ENDPROC(ret_fast_syscall)
>  
>  	tst	r1, #_TIF_SYSCALL_WORK
>  	bne	__sys_trace_return_nosave
> +	tst	r1, #(_TIF_FD_SLOTS << 16)	@ r1 holds TI_FLAGS << 16
> +	bne	__sys_trace_return_nosave

[Severity: Low]
Is this newly added check reachable?

The preceding tst r1, #_TIF_SYSCALL_WORK instruction appears to intercept
the branch because it inadvertently catches this condition.

In ret_fast_syscall, r1 is loaded with TI_FLAGS << 16. TIF_FD_SLOTS is
bit 5, so shifting it by 16 places it at bit 21 in r1.

_TIF_SYSCALL_WORK naturally includes bit 21 (_TIF_SYSCALL_AUDIT). Because of
this bit-shift overlap, the first test against _TIF_SYSCALL_WORK will
evaluate to non-zero whenever TIF_FD_SLOTS is set. This means the branch to
__sys_trace_return_nosave is taken early, making the new tst instruction
unreachable dead code.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=5

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 18/50] xtensa: commit fds on syscall exit
  2026-09-15 11:31 ` [PATCH RFC POC 18/50] xtensa: " Christian Brauner
@ 2026-09-15 12:00   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:00 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-arm-msm, linux-hexagon, linux-kernel, kvm, linux-mm,
	linux-arm-kernel, linux-openrisc, Peter Zijlstra, linux-hyperv,
	linux-fsdevel, Jens Axboe, linuxppc-dev, linux-gpio, David Airlie,
	virtualization, Oleg Nesterov, linux-alpha, kexec, Ingo Molnar,
	dri-devel, linux-csky, linux-m68k, Jan Kara, linux-um,
	Eugenio Perez, Jann Horn, bpf, linux-parisc, linux-sh,
	Christian Brauner (Amutable), linux-snps-arc, Alexander Viro,
	io-uring, sparclinux, linux-mips, Michael S. Tsirkin

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] xtensa: inconsistent mid-syscall ptrace exit tracing due to stale flags
--

commit f64c69fbd6ff1a2ee8dd26645f9d56d2d371647e
Author: Christian Brauner <brauner@kernel.org>

xtensa: commit fds on syscall exit

Add TIF_FD_SLOTS and test it once the system call has stored its
return value. A task that reserved descriptors uses the traced path.

[ ... ]

> diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
> index 272fff587907f..4b95f48736e6b 100644
> --- a/arch/xtensa/kernel/entry.S
> +++ b/arch/xtensa/kernel/entry.S
> @@ -1976,6 +1976,11 @@ ENTRY(system_call)
>  1:	/* regs->areg[2] = return_value */
>  
>  	s32i	abi_rv, abi_saved0, PT_AREG2
> +
> +	/* descriptors reserved by the syscall are committed in do_syscall_trace_leave */
> +	GET_THREAD_INFO(a4, a1)
> +	l32i	a4, a4, TI_FLAGS
> +	bbsi.l	a4, TIF_FD_SLOTS, 1f
>  	bnez	abi_saved1, 1f

[Severity: Medium]
Does this introduce a regression leading to inconsistent ptrace
observability?

The exit path in system_call() dynamically checks TIF_FD_SLOTS from fresh
thread flags (loaded into a4), but falls back to abi_saved1 for trace work.

Earlier in system_call(), abi_saved1 is cached before executing the syscall:

    GET_THREAD_INFO(a4, a1)
    l32i    abi_saved1, a4, TI_FLAGS
    movi    a4, _TIF_WORK_MASK
    and     abi_saved1, abi_saved1, a4

If a tracer attaches mid-syscall (e.g. using PTRACE_ATTACH on an Xtensa
process currently blocked inside a system call), wouldn't the exit trace
events be missed for most syscalls because abi_saved1 lacks the new flags,
yet mysteriously be caught if the syscall happens to allocate a file
descriptor (because TIF_FD_SLOTS is checked against the fresh TI_FLAGS)?

Could we reload the fresh _TIF_WORK_MASK from thread_info here instead of
relying on the stale abi_saved1 cache?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=18

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install
  2026-09-15 11:31 ` [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install Christian Brauner
@ 2026-09-15 12:00   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:00 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: Michael S. Tsirkin, linux-sh, Peter Zijlstra, linux-openrisc,
	Ingo Molnar, linux-mips, linux-parisc, linux-hyperv,
	Alexander Viro, Jens Axboe, linuxppc-dev, linux-hexagon,
	sparclinux, kexec, linux-gpio, kvm, Jan Kara, linux-fsdevel,
	linux-csky, Christian Brauner (Amutable), Eugenio Perez,
	virtualization, Jann Horn, linux-mm, Oleg Nesterov, linux-um,
	linux-m68k, io-uring, linux-arm-msm, linux-snps-arc,
	linux-arm-kernel, linux-alpha, bpf, David Airlie, dri-devel,
	linux-kernel

> receive_fd() cannot defer to syscall exit as SECCOMP_IOCTL_NOTIF_ADDFD
> installs into the target task and hands the number to the supervisor
> and IORING_OP_FIXED_FD_INSTALL runs from an io_uring op. Open-code the
> get_unused_fd_flags() + fd_install() it did through FD_PREPARE().
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=23


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 24/50] file: make FD_ADD() a standalone immediate install
  2026-09-15 11:31 ` [PATCH RFC POC 24/50] file: make FD_ADD() a standalone " Christian Brauner
@ 2026-09-15 12:01   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:01 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-m68k, linux-arm-msm, linux-um, Jens Axboe,
	Christian Brauner (Amutable), dri-devel, Michael S. Tsirkin,
	sparclinux, Jann Horn, Jan Kara, Ingo Molnar, linux-arm-kernel,
	linux-parisc, linuxppc-dev, linux-mips, Alexander Viro,
	linux-hyperv, linux-snps-arc, linux-fsdevel, linux-kernel,
	linux-mm, linux-csky, io-uring, Eugenio Perez, David Airlie,
	Peter Zijlstra, Oleg Nesterov, linux-openrisc, linux-gpio,
	linux-hexagon, linux-alpha, linux-sh, kvm, bpf, virtualization,
	kexec

> FD_ADD() was built on FD_PREPARE() + fd_publish(). Give it its own small
> macro that allocates the descriptor so it stays an immediate one-shot
> for the hot descriptor-is-the-result paths (open, socket, accept, memfd
> etc.).
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=24


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots
  2026-09-15 11:31 ` [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots Christian Brauner
@ 2026-09-15 12:02   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:02 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: bpf, linux-fsdevel, linux-gpio, linux-csky, Alexander Viro,
	dri-devel, Jan Kara, Jens Axboe, Michael S. Tsirkin, Jann Horn,
	kexec, Eugenio Perez, linux-mm, linux-hyperv, linux-mips,
	linux-hexagon, Peter Zijlstra, virtualization, linux-snps-arc,
	sparclinux, linux-alpha, linuxppc-dev, io-uring, Oleg Nesterov,
	linux-parisc, kvm, linux-sh, linux-arm-msm, linux-arm-kernel,
	linux-kernel, linux-m68k, Christian Brauner (Amutable),
	Ingo Molnar, linux-openrisc, linux-um, David Airlie

> If the fdtable is unshared or the task exits we can't install
> reservations. The reserved fd isn't reserved anymore. execve() would
> leak the reservation into the child.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=20


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 13/50] openrisc: commit fds on syscall exit
  2026-09-15 11:30 ` [PATCH RFC POC 13/50] openrisc: " Christian Brauner
@ 2026-09-15 12:02   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:02 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-csky, io-uring, Peter Zijlstra, linux-snps-arc,
	linux-parisc, linux-m68k, linux-sh, linux-openrisc, Jens Axboe,
	linux-mips, David Airlie, Alexander Viro, Ingo Molnar,
	linux-hyperv, Eugenio Perez, linux-mm, linux-fsdevel,
	linuxppc-dev, Jann Horn, linux-kernel, Michael S. Tsirkin,
	Christian Brauner (Amutable), linux-arm-msm, linux-alpha,
	linux-hexagon, kexec, dri-devel, bpf, Jan Kara, sparclinux,
	linux-gpio, linux-um, virtualization, kvm, linux-arm-kernel,
	Oleg Nesterov

> Add TIF_FD_SLOTS and test it together with TIF_SYSCALL_TRACE on the
> way out of a system call. The check used to rely on the flags r30 had
> been loaded with before the call. Reload them. The syscall may have set
> the new bit. A task that reserved descriptors calls
> do_syscall_trace_leave() which commits them before audit and the ptrace
> exit stop.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=13


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns
  2026-09-15 11:31 ` [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns Christian Brauner
@ 2026-09-15 12:03   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:03 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: kvm, linux-m68k, linux-gpio, dri-devel, linux-hyperv,
	David Airlie, Jan Kara, linux-arm-msm, Jann Horn, linux-alpha,
	linux-hexagon, linux-parisc, Jens Axboe, linux-openrisc,
	linuxppc-dev, bpf, linux-um, io-uring, Alexander Viro, linux-mm,
	Peter Zijlstra, Ingo Molnar, linux-fsdevel, virtualization,
	Oleg Nesterov, linux-csky, linux-mips, kexec, Michael S. Tsirkin,
	linux-sh, sparclinux, Christian Brauner (Amutable),
	linux-snps-arc, Eugenio Perez, linux-kernel, linux-arm-kernel

> scm_recv_one_fd() allocates a descriptor, writes the number into the
> control message and installs the file right there, one descriptor at a
> time. Everything that recvmsg() does after scm_detach_fds() can still
> fail though. When it does the syscall returns -EFAULT while the received
> descriptors are already in the table and the caller has no way to tell.
> 
> Reserve the descriptor with fd_prepare() and stage the file with
> fd_stage(). The number is written to userspace as before, but the file
> is only installed when recvmsg() returns success and dropped together
> with the descriptor when it returns an error.
> 
> A control message that doesn't fit still gets only the descriptors it
> can report and MSG_CTRUNC.
> 
> IORING_OP_RECVMSG reaches the same code from io-wq workers and the
> SQPOLL thread. io_uring requests commit their reservations before the
> completion is posted.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=22


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 12:04   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:04 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: kexec, io-uring, Peter Zijlstra, Jan Kara, linux-hexagon,
	Michael S. Tsirkin, virtualization, linux-mm, linux-csky,
	linux-um, Ingo Molnar, linux-gpio, Oleg Nesterov, linux-arm-msm,
	Jann Horn, dri-devel, linuxppc-dev, bpf, linux-hyperv,
	Alexander Viro, linux-alpha, linux-mips, linux-arm-kernel,
	linux-parisc, kvm, David Airlie, linux-m68k, linux-sh, sparclinux,
	linux-fsdevel, Eugenio Perez, Jens Axboe, linux-snps-arc,
	linux-openrisc, linux-kernel, Christian Brauner (Amutable)

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=28


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install
  2026-09-15 11:31 ` [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install Christian Brauner
@ 2026-09-15 12:04   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:04 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Christian Brauner (Amutable), linux-parisc, Jann Horn,
	linux-arm-kernel, linux-alpha, bpf, linux-csky, dri-devel,
	linux-sh, linux-hexagon, kvm, linux-mm, linux-snps-arc, io-uring,
	linux-gpio, sparclinux, linux-mips, Eugenio Perez,
	Michael S. Tsirkin, Oleg Nesterov, linuxppc-dev, linux-fsdevel,
	linux-um, Peter Zijlstra, Jan Kara, kexec, linux-arm-msm,
	linux-openrisc, David Airlie, Ingo Molnar, linux-kernel,
	linux-m68k, virtualization, linux-hyperv, Alexander Viro,
	Jens Axboe

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=27


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path
  2026-09-15 11:31 ` [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path Christian Brauner
@ 2026-09-15 12:05   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:05 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Jens Axboe, Peter Zijlstra, linux-alpha, linux-kernel, sparclinux,
	Michael S. Tsirkin, linux-mm, linux-hyperv, linux-mips,
	linux-openrisc, linux-m68k, linuxppc-dev, linux-parisc,
	linux-gpio, virtualization, Ingo Molnar, linux-um, dri-devel,
	linux-csky, Alexander Viro, bpf, linux-snps-arc, io-uring,
	Christian Brauner (Amutable), Oleg Nesterov, Eugenio Perez, kexec,
	kvm, linux-arm-kernel, linux-hexagon, linux-arm-msm, Jann Horn,
	David Airlie, linux-sh, Jan Kara, linux-fsdevel

> The FD_PREPARE() cleanup class allocated and installed immediately and
> required fd_publish() to be the last thing that could fail. Reimplement
> it on the deferred path. FD_PREPARE() reserves a slot with fd_prepare()
> and stages the file on it. The syscall exit installs on success and
> drops on error. fd_prepare_fd() and fd_prepare_file() now read the slot.
> fd_publish() is gone.
> 
> Convert every FD_PREPARE() user since fdf.err can now become a simple
> IS_ERR(fdf).
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=25


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand
  2026-09-15 11:31 ` [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand Christian Brauner
@ 2026-09-15 12:05   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:05 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: Oleg Nesterov, linux-hexagon, virtualization, bpf, linux-sh,
	linux-gpio, linuxppc-dev, linux-csky, kvm, linux-fsdevel,
	dri-devel, Jan Kara, Eugenio Perez, linux-kernel, linux-mm,
	linux-alpha, Jens Axboe, linux-um, David Airlie, linux-snps-arc,
	linux-mips, linux-parisc, Christian Brauner (Amutable),
	linux-openrisc, linux-hyperv, linux-m68k, sparclinux, Ingo Molnar,
	Michael S. Tsirkin, Jann Horn, linux-arm-msm, Peter Zijlstra,
	kexec, io-uring, Alexander Viro, linux-arm-kernel

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=26


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 31/50] vfio: install the migration data descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 31/50] vfio: install the migration data " Christian Brauner
@ 2026-09-15 12:07   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:07 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: kexec, linux-csky, Jens Axboe, dri-devel, bpf, linux-mm, linux-um,
	linuxppc-dev, linux-gpio, Peter Zijlstra,
	Christian Brauner (Amutable), Ingo Molnar, linux-sh,
	Alexander Viro, linux-openrisc, Eugenio Perez, linux-hexagon,
	Oleg Nesterov, linux-snps-arc, David Airlie, linux-arm-msm,
	linux-hyperv, Michael S. Tsirkin, linux-mips, linux-m68k,
	virtualization, linux-arm-kernel, linux-parisc, linux-kernel,
	io-uring, Jan Kara, Jann Horn, kvm, linux-fsdevel, sparclinux,
	linux-alpha

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=31


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 30/50] drm/vmwgfx: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 30/50] drm/vmwgfx: " Christian Brauner
@ 2026-09-15 12:09   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:09 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: Eugenio Perez, dri-devel, bpf, Jann Horn, linux-m68k, kvm,
	linux-fsdevel, linux-parisc, Jan Kara, sparclinux, linuxppc-dev,
	linux-hexagon, linux-arm-msm, Peter Zijlstra, linux-alpha,
	linux-gpio, Michael S. Tsirkin, Oleg Nesterov, linux-snps-arc,
	Alexander Viro, linux-mm, linux-arm-kernel, linux-kernel,
	linux-um, David Airlie, Jens Axboe, linux-hyperv, linux-mips,
	linux-openrisc, virtualization, linux-csky, io-uring,
	Christian Brauner (Amutable), Ingo Molnar, linux-sh, kexec

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=30


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns
  2026-09-15 11:31 ` [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns Christian Brauner
@ 2026-09-15 12:09   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:09 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: Christian Brauner (Amutable), Ingo Molnar, Peter Zijlstra,
	sparclinux, linux-sh, kvm, linux-m68k, linux-fsdevel, linux-mm,
	io-uring, dri-devel, linux-parisc, Oleg Nesterov, linux-hyperv,
	virtualization, linux-hexagon, linux-openrisc, Michael S. Tsirkin,
	linux-gpio, Eugenio Perez, linux-csky, Jann Horn, linux-um,
	Jens Axboe, linux-kernel, bpf, kexec, linux-arm-msm, Jan Kara,
	linux-mips, Alexander Viro, linux-arm-kernel, linuxppc-dev,
	David Airlie, linux-snps-arc, linux-alpha

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=33


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 32/50] liveupdate: install the session descriptors when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 32/50] liveupdate: install the session descriptors " Christian Brauner
@ 2026-09-15 12:09   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:09 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Michael S. Tsirkin, Jan Kara, linux-gpio, Oleg Nesterov, io-uring,
	bpf, linux-openrisc, kexec, Eugenio Perez, linux-arm-msm,
	linux-kernel, sparclinux, linux-arm-kernel, Ingo Molnar,
	Peter Zijlstra, Jann Horn, linux-hexagon, dri-devel, linux-hyperv,
	linux-mips, linux-um, kvm, Jens Axboe, virtualization,
	linux-snps-arc, linux-fsdevel, David Airlie,
	Christian Brauner (Amutable), linux-parisc, linux-m68k, linux-sh,
	linux-csky, linux-mm, linuxppc-dev, linux-alpha, Alexander Viro

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=32


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 21/50] io_uring: commit fds per request
  2026-09-15 11:31 ` [PATCH RFC POC 21/50] io_uring: commit fds per request Christian Brauner
@ 2026-09-15 12:11   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:11 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: bpf, Michael S. Tsirkin, Jens Axboe, linux-m68k, linux-gpio,
	linux-arm-msm, David Airlie, linux-arm-kernel, kvm, linuxppc-dev,
	Oleg Nesterov, Christian Brauner (Amutable), sparclinux,
	linux-parisc, io-uring, Peter Zijlstra, linux-mm, Alexander Viro,
	linux-sh, Jann Horn, linux-snps-arc, dri-devel, linux-fsdevel,
	linux-mips, linux-um, linux-kernel, linux-alpha, Jan Kara,
	linux-hyperv, linux-hexagon, Ingo Molnar, linux-openrisc,
	Eugenio Perez, kexec, linux-csky, virtualization

> io_uring requests don't complete on syscall exit of the task that
> submitted them. They complete:
> 
> - inline from io_uring_enter()
> - from task_work on any return to userspace
> - from io-wq workers and from the SQPOLL thread
> 
> The CQEs are visible to other threads before any syscall returns. So
> commit the reserved descriptors before the completion is posted. Commit
> them after ->issue() based on the request's result and before every CQE
> they post.
> 
> Nothing reachable from io_uring reserves yet. Once SCM_RIGHTS is
> converted this keeps IORING_OP_RECVMSG working from io-wq workers and
> the SQPOLL thread.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=21


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 29/50] drm/virtio: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 29/50] drm/virtio: " Christian Brauner
@ 2026-09-15 12:11   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:11 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: kvm, Jan Kara, linux-csky, Alexander Viro, dri-devel, Jann Horn,
	linux-parisc, linux-snps-arc, Ingo Molnar, linux-mips,
	linux-alpha, linux-um, linux-arm-msm, virtualization, io-uring,
	Michael S. Tsirkin, linux-kernel, Jens Axboe, linuxppc-dev,
	linux-hyperv, David Airlie, Peter Zijlstra, linux-hexagon,
	linux-sh, linux-openrisc, linux-fsdevel, sparclinux, bpf,
	linux-mm, linux-arm-kernel, Eugenio Perez, kexec, linux-gpio,
	linux-m68k, Oleg Nesterov, Christian Brauner (Amutable)

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=29


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure Christian Brauner
@ 2026-09-15 12:12   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:12 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Eugenio Perez, Michael S. Tsirkin, Peter Zijlstra, kexec,
	linux-um, linux-arm-msm, linux-snps-arc, io-uring, linux-openrisc,
	linux-parisc, Christian Brauner (Amutable), David Airlie,
	Ingo Molnar, linux-arm-kernel, linux-m68k, linux-hyperv,
	linuxppc-dev, linux-mips, linux-gpio, dri-devel, linux-alpha,
	Oleg Nesterov, kvm, bpf, Jens Axboe, linux-hexagon, linux-mm,
	virtualization, Jann Horn, linux-kernel, sparclinux, linux-sh,
	linux-fsdevel, linux-csky, Alexander Viro, Jan Kara

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=38


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor " Christian Brauner
@ 2026-09-15 12:13   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:13 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-hexagon, io-uring, linux-hyperv, dri-devel,
	Christian Brauner (Amutable), Oleg Nesterov, linux-fsdevel,
	linux-openrisc, Jens Axboe, linux-arm-kernel, linux-mips,
	David Airlie, Jann Horn, linux-gpio, sparclinux, Jan Kara,
	Eugenio Perez, linux-alpha, Peter Zijlstra, linux-sh,
	linux-parisc, kexec, linux-mm, Ingo Molnar, linux-um,
	Michael S. Tsirkin, Alexander Viro, linux-kernel, linux-csky,
	linuxppc-dev, kvm, bpf, linux-arm-msm, virtualization, linux-m68k,
	linux-snps-arc

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=36


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns Christian Brauner
@ 2026-09-15 12:13   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:13 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-parisc, Christian Brauner (Amutable), linux-arm-msm,
	linux-fsdevel, linux-mm, bpf, linux-mips, dri-devel, linux-hyperv,
	Michael S. Tsirkin, virtualization, kvm, io-uring, kexec,
	linux-m68k, linux-hexagon, linux-alpha, Ingo Molnar,
	linux-openrisc, Oleg Nesterov, Jens Axboe, linux-gpio, Jann Horn,
	linux-um, Alexander Viro, Jan Kara, linux-snps-arc, linux-csky,
	David Airlie, sparclinux, linux-sh, Peter Zijlstra, linux-kernel,
	Eugenio Perez, linux-arm-kernel, linuxppc-dev

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=35


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor by hand
  2026-09-15 11:31 ` [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor " Christian Brauner
@ 2026-09-15 12:14   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:14 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linuxppc-dev, linux-kernel, Jens Axboe, dri-devel, linux-fsdevel,
	linux-snps-arc, linux-um, David Airlie, linux-arm-msm, linux-csky,
	linux-gpio, Jann Horn, linux-alpha, Jan Kara, linux-openrisc,
	linux-parisc, io-uring, linux-mm, bpf, kexec, Ingo Molnar,
	Alexander Viro, sparclinux, Eugenio Perez, kvm, virtualization,
	Oleg Nesterov, linux-arm-kernel, linux-hexagon, linux-m68k,
	Michael S. Tsirkin, Peter Zijlstra, linux-mips, linux-sh,
	Christian Brauner (Amutable), linux-hyperv

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=43


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 39/50] seccomp: stop putting the listener descriptor back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 39/50] seccomp: stop putting the listener " Christian Brauner
@ 2026-09-15 12:14   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:14 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: Michael S. Tsirkin, dri-devel, virtualization, io-uring,
	linux-fsdevel, linux-hexagon, linux-arm-msm, kvm, kexec,
	linux-gpio, Alexander Viro, bpf, linux-sh,
	Christian Brauner (Amutable), linuxppc-dev, Oleg Nesterov,
	linux-alpha, linux-arm-kernel, Jan Kara, Peter Zijlstra,
	linux-m68k, linux-mips, sparclinux, linux-kernel, linux-snps-arc,
	Jens Axboe, Jann Horn, linux-openrisc, linux-um, Ingo Molnar,
	linux-parisc, David Airlie, linux-mm, Eugenio Perez, linux-hyperv,
	linux-csky

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=39


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns
  2026-09-15 11:31 ` [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns Christian Brauner
@ 2026-09-15 12:14   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:14 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Peter Zijlstra, linuxppc-dev, Eugenio Perez, io-uring, linux-mm,
	linux-snps-arc, linux-hexagon, Alexander Viro, bpf, linux-parisc,
	virtualization, linux-arm-kernel, Christian Brauner (Amutable),
	kexec, linux-arm-msm, Ingo Molnar, Jann Horn, dri-devel,
	linux-fsdevel, Jan Kara, linux-sh, linux-mips, linux-alpha,
	linux-openrisc, Oleg Nesterov, Jens Axboe, Michael S. Tsirkin,
	linux-kernel, linux-um, kvm, linux-hyperv, linux-m68k,
	David Airlie, sparclinux, linux-gpio, linux-csky

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=34


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server " Christian Brauner
@ 2026-09-15 12:14   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:14 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: linux-m68k, Alexander Viro, Peter Zijlstra, linux-arm-kernel,
	virtualization, bpf, Oleg Nesterov, Jens Axboe, Eugenio Perez,
	kexec, linux-openrisc, linux-fsdevel, kvm, linux-hyperv, Jan Kara,
	David Airlie, linux-kernel, io-uring, linux-snps-arc, linux-sh,
	linux-hexagon, linux-alpha, dri-devel, linux-csky, sparclinux,
	linux-um, linux-mips, Jann Horn, linux-mm, linuxppc-dev,
	Christian Brauner (Amutable), linux-gpio, Ingo Molnar,
	linux-arm-msm, linux-parisc, Michael S. Tsirkin

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=37


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 12:15   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:15 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: virtualization, linux-parisc, io-uring, Michael S. Tsirkin,
	Jann Horn, Oleg Nesterov, linux-alpha, linux-kernel, linux-hyperv,
	linuxppc-dev, linux-arm-msm, linux-fsdevel, bpf, linux-arm-kernel,
	Christian Brauner (Amutable), linux-mm, linux-snps-arc,
	Eugenio Perez, linux-m68k, linux-gpio, dri-devel, kvm, linux-mips,
	Jan Kara, linux-sh, linux-um, sparclinux, linux-hexagon,
	David Airlie, Ingo Molnar, Alexander Viro, kexec, Peter Zijlstra,
	linux-csky, linux-openrisc, Jens Axboe

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=44


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 40/50] KVM: stop putting descriptors back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 40/50] KVM: stop putting descriptors " Christian Brauner
@ 2026-09-15 12:15   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:15 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-alpha, bpf, kexec, dri-devel, David Airlie, Ingo Molnar,
	linux-snps-arc, linux-parisc, sparclinux, linux-um, linux-hyperv,
	Alexander Viro, linux-mm, Peter Zijlstra, linuxppc-dev,
	linux-gpio, linux-kernel, Michael S. Tsirkin, linux-m68k,
	Jann Horn, Oleg Nesterov, linux-openrisc, linux-arm-kernel,
	linux-csky, Jens Axboe, kvm, Jan Kara, io-uring, linux-arm-msm,
	Eugenio Perez, linux-fsdevel, Christian Brauner (Amutable),
	linux-hexagon, linux-sh, virtualization, linux-mips

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=40


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor " Christian Brauner
@ 2026-09-15 12:16   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:16 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-alpha, linux-kernel, linux-mips, sparclinux, Jan Kara,
	Jens Axboe, linux-arm-kernel, linuxppc-dev, linux-gpio,
	Christian Brauner (Amutable), Jann Horn, linux-sh, David Airlie,
	Michael S. Tsirkin, linux-csky, linux-parisc, bpf, linux-snps-arc,
	linux-arm-msm, linux-hexagon, Eugenio Perez, Ingo Molnar,
	Peter Zijlstra, dri-devel, kvm, linux-m68k, linux-um, linux-mm,
	virtualization, kexec, Alexander Viro, linux-hyperv,
	Oleg Nesterov, linux-openrisc, io-uring, linux-fsdevel

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=41


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand
  2026-09-15 11:31 ` [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand Christian Brauner
@ 2026-09-15 12:17   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:17 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: sparclinux, linux-openrisc, Ingo Molnar, linux-csky,
	Christian Brauner (Amutable), linux-hexagon, linux-arm-msm, bpf,
	Peter Zijlstra, linux-mips, linux-fsdevel, Jens Axboe,
	linux-alpha, kexec, kvm, Jan Kara, linux-sh, linux-um, Jann Horn,
	linux-m68k, Alexander Viro, linux-kernel, linux-snps-arc,
	David Airlie, linux-hyperv, linux-mm, linux-arm-kernel, io-uring,
	Michael S. Tsirkin, Eugenio Perez, Oleg Nesterov, linuxppc-dev,
	linux-gpio, virtualization, dri-devel, linux-parisc

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=42


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns Christian Brauner
@ 2026-09-15 12:18   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:18 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: David Airlie, virtualization, dri-devel, linux-openrisc,
	linux-arm-msm, sparclinux, linux-mips, Jann Horn, linux-hexagon,
	bpf, linux-gpio, linux-m68k, linux-hyperv, kexec, Eugenio Perez,
	Michael S. Tsirkin, linuxppc-dev, linux-alpha, linux-parisc,
	linux-sh, io-uring, Peter Zijlstra, Alexander Viro,
	Christian Brauner (Amutable), linux-arm-kernel, linux-snps-arc,
	linux-um, kvm, Ingo Molnar, linux-kernel, Jan Kara, linux-csky,
	linux-fsdevel, linux-mm, Oleg Nesterov, Jens Axboe

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=47


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure Christian Brauner
@ 2026-09-15 12:18   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:18 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Michael S. Tsirkin, linux-gpio, linux-hyperv, linux-kernel,
	sparclinux, dri-devel, linux-mm, linux-fsdevel, linux-snps-arc,
	Oleg Nesterov, Peter Zijlstra, Ingo Molnar, linux-alpha,
	Alexander Viro, virtualization, linux-mips, kexec, bpf,
	linux-arm-msm, linuxppc-dev, Jan Kara, linux-openrisc, linux-sh,
	David Airlie, linux-um, linux-csky, linux-parisc, Jens Axboe,
	Christian Brauner (Amutable), linux-arm-kernel, kvm,
	linux-hexagon, io-uring, linux-m68k, Eugenio Perez, Jann Horn

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=45


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 50/50] Drivers: hv: mshv: stop putting descriptors back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 50/50] Drivers: hv: mshv: " Christian Brauner
@ 2026-09-15 12:19   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:19 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Alexander Viro, linux-alpha, linux-arm-kernel, linux-parisc,
	Jann Horn, linux-hexagon, sparclinux, Jan Kara, virtualization,
	Peter Zijlstra, kexec, linux-hyperv, kvm, Eugenio Perez,
	linux-fsdevel, linux-snps-arc, linux-sh, linux-mips,
	linux-arm-msm, David Airlie, Oleg Nesterov, linux-csky, bpf,
	linuxppc-dev, io-uring, linux-kernel, Ingo Molnar,
	Michael S. Tsirkin, linux-m68k, Jens Axboe, dri-devel, linux-gpio,
	linux-openrisc, linux-um, Christian Brauner (Amutable), linux-mm

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=50


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf descriptor when the ioctl returns
  2026-09-15 11:31 ` [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf " Christian Brauner
@ 2026-09-15 12:20   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:20 UTC (permalink / raw)
  To: Linus Torvalds, Christian Brauner
  Cc: Christian Brauner (Amutable), sparclinux, linux-csky, linux-sh,
	linuxppc-dev, linux-kernel, linux-hyperv, Oleg Nesterov,
	linux-alpha, io-uring, bpf, Peter Zijlstra, linux-um,
	linux-snps-arc, kvm, dri-devel, Michael S. Tsirkin, Jan Kara,
	linux-hexagon, Jens Axboe, Eugenio Perez, Ingo Molnar, linux-mm,
	linux-gpio, linux-mips, linux-arm-msm, linux-openrisc, kexec,
	linux-arm-kernel, linux-parisc, linux-m68k, virtualization,
	Jann Horn, Alexander Viro, David Airlie, linux-fsdevel

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=48


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure Christian Brauner
@ 2026-09-15 12:21   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:21 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-openrisc, virtualization, kexec, linux-fsdevel,
	linuxppc-dev, linux-alpha, linux-arm-kernel, io-uring, linux-csky,
	kvm, linux-sh, David Airlie, Ingo Molnar, Jann Horn, linux-kernel,
	Peter Zijlstra, linux-mm, bpf, dri-devel, linux-mips, sparclinux,
	Eugenio Perez, linux-arm-msm, linux-gpio, linux-hexagon,
	linux-parisc, Jens Axboe, Christian Brauner (Amutable), Jan Kara,
	Alexander Viro, linux-m68k, linux-um, Oleg Nesterov,
	linux-snps-arc, linux-hyperv, Michael S. Tsirkin

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=49


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the descriptor back on failure
  2026-09-15 11:31 ` [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the " Christian Brauner
@ 2026-09-15 12:21   ` sashiko-bot
  0 siblings, 0 replies; 108+ messages in thread
From: sashiko-bot @ 2026-09-15 12:21 UTC (permalink / raw)
  To: Christian Brauner, Linus Torvalds
  Cc: linux-gpio, bpf, Oleg Nesterov, Jann Horn, linux-mm,
	linux-openrisc, linux-arm-msm, linux-hyperv, virtualization,
	sparclinux, kvm, linux-mips, linux-alpha, dri-devel,
	Peter Zijlstra, io-uring, David Airlie,
	Christian Brauner (Amutable), linux-m68k, linux-arm-kernel,
	Ingo Molnar, linux-um, linux-sh, Jan Kara, Alexander Viro,
	linux-kernel, Jens Axboe, linuxppc-dev, linux-snps-arc,
	Eugenio Perez, kexec, linux-parisc, linux-fsdevel, linux-hexagon,
	Michael S. Tsirkin, linux-csky

> Rely on the fd exit path machinery.
> 
> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260915-work-fd-reserve-unify-folded-v1-0-4d5217d6b246@kernel.org?part=46


^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (49 preceding siblings ...)
  2026-09-15 11:31 ` [PATCH RFC POC 50/50] Drivers: hv: mshv: " Christian Brauner
@ 2026-09-15 16:02 ` Linus Torvalds
  2026-09-15 22:21   ` Rob Clark
  2026-09-16  7:09   ` Christian Brauner
  2026-09-15 17:51 ` Jann Horn
  51 siblings, 2 replies; 108+ messages in thread
From: Linus Torvalds @ 2026-09-15 16:02 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv

On Tue, 15 Sept 2026 at 04:31, Christian Brauner <brauner@kernel.org> wrote:
>
> TL;DR, this lets arch code handle fd install and cleanup. fd_prepare()
> allocates a descriptor like get_unused_fd_flags() does and records it in
> a slot on the task. fd_stage() attaches the file to that slot and
> returns the number.

Honestly, I am *not* a fan. At all.

I think this adds complexity rather than removing it.

The diffstat tells a story:

>  106 files changed, 962 insertions(+), 861 deletions(-)

in how this adds a hundred lines more than it deletes.

But to make things worse, it adds them in bad places: low-level
architecture assembly code.

Those extra lines are *not* making complicated code simpler. Quite the
reverse. They are taking fairly straightforward "just deal with errors
with normal cleanup in the place where it makes sense" and makes the
*straightforward* case simpler, while making the big picture more
complicated and subtle, and adding new code to places that are not
simple and just blindly do somethign that makes no sense in that
context.

IOW: it's more code, and it's more abstraction, and it DOES NOT HELP.

And yes, most of the well-maintained modern platforms (read: x86 and
arm64) use the generic infrastructure and they don't show that
low-level asm effect. So for those cases, it's mainly just  that added
conceptual complexity and a new odd rule - and makes a *successful*
system call go through that "extra work" and indirection phase that it
didn't use to go through.

So it just spreads out the work, and moves it to a less obvious place.

All for the very questionable advantage that you can now randomly add
a file descriptor without the few lines of fairly straightforward
rollback.

IOW, I do not see a single real upside to this, and I see immediate
downsides to it, and a more abstract complicated machinery.

I do *not* see why we woudl want to make this be a "every system call
exit" kind of thing. If there are places that think it's complicated
to do, they could have *their* local little stack of fd's pending. Why
force it onto the low-level system call entry for every system call
when there are only a small handful of actual real cases (the vfs
itself, and random ioctl's by odd driver subsystems).

              Linus

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
                   ` (50 preceding siblings ...)
  2026-09-15 16:02 ` [PATCH RFC POC 00/50] file: handle files on syscall exit Linus Torvalds
@ 2026-09-15 17:51 ` Jann Horn
  2026-09-15 19:08   ` Linus Torvalds
  51 siblings, 1 reply; 108+ messages in thread
From: Jann Horn @ 2026-09-15 17:51 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Linus Torvalds, Alexander Viro, Jan Kara, Ingo Molnar,
	Peter Zijlstra, linux-fsdevel, linux-kernel, linux-mm,
	Oleg Nesterov, linux-alpha, linux-snps-arc, linux-arm-kernel,
	linux-csky, linux-hexagon, linux-m68k, linux-mips, linux-openrisc,
	linux-parisc, linux-sh, sparclinux, linux-um, Jens Axboe,
	io-uring, netdev, linuxppc-dev, linux-gpio, linux-arm-msm,
	dri-devel, bpf, David Airlie, virtualization, kvm, kexec,
	linux-hyperv

On Tue, Sep 15, 2026 at 1:31 PM Christian Brauner <brauner@kernel.org> wrote:
> TL;DR, this lets arch code handle fd install and cleanup. fd_prepare()
> allocates a descriptor like get_unused_fd_flags() does and records it in
> a slot on the task. fd_stage() attaches the file to that slot and
> returns the number.

I'm not really a fan but I feel like if you want to do this, you
should be using task_work so you don't have to touch the entry/exit
paths directly? (And if task_work is too inefficient somehow, you
could tinker with the task_work implementation.)

> When the syscall returns success the exit path installs every staged
> file. When it returns an error it drops the descriptors and the files.

Is this mainly about stuff like "we installed a file descriptor and
then the following put_user() failed"? Because if so, I think a nicer
fix would be to have a policy of "if userspace provides unwritable
memory to a syscall, just keep going and pretend the access worked",
and maybe have a sysctl that kills the process when this happens to
emphasize that userspace should not be doing this.

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 17:51 ` Jann Horn
@ 2026-09-15 19:08   ` Linus Torvalds
  2026-09-16  9:50     ` David Laight
  0 siblings, 1 reply; 108+ messages in thread
From: Linus Torvalds @ 2026-09-15 19:08 UTC (permalink / raw)
  To: Jann Horn
  Cc: Christian Brauner, Alexander Viro, Jan Kara, Ingo Molnar,
	Peter Zijlstra, linux-fsdevel, linux-kernel, linux-mm,
	Oleg Nesterov, linux-alpha, linux-snps-arc, linux-arm-kernel,
	linux-csky, linux-hexagon, linux-m68k, linux-mips, linux-openrisc,
	linux-parisc, linux-sh, sparclinux, linux-um, Jens Axboe,
	io-uring, netdev, linuxppc-dev, linux-gpio, linux-arm-msm,
	dri-devel, bpf, David Airlie, virtualization, kvm, kexec,
	linux-hyperv

On Tue, 15 Sept 2026 at 10:52, Jann Horn <jannh@google.com> wrote:
>
> Is this mainly about stuff like "we installed a file descriptor and
> then the following put_user() failed"? Because if so, I think a nicer
> fix would be to have a policy of "if userspace provides unwritable
> memory to a syscall, just keep going and pretend the access worked",
> and maybe have a sysctl that kills the process when this happens to
> emphasize that userspace should not be doing this.

We've done that before, where we just ignore put_user() errors and the
user gets whatever the user gets.

It is maybe not optimal, but it's fine. You can find quite a lot of
unchecked put_user() calls with a pattern like

        git grep '^[[:space:]]*put_user(.*);'

and some of them are in core code - see the two in kernel/fork.c, for example.

One of them says "if userspace has not set up a proper pointer then
tough luck". The other one doesn't even bother with a comment.

The scheduler has two cases too, although one of them is admittedly
for another error case.

So yes, saying "if you pass bogus arguments, you get what you get" is
a valid model. It's perhaps not the *preferred* model, but it's not
wrong.

It *would* be wrong to take code that already has error handling and
remove the error handling, though.

                  Linus

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 16:02 ` [PATCH RFC POC 00/50] file: handle files on syscall exit Linus Torvalds
@ 2026-09-15 22:21   ` Rob Clark
  2026-09-15 22:54     ` Linus Torvalds
  2026-09-16  7:09   ` Christian Brauner
  1 sibling, 1 reply; 108+ messages in thread
From: Rob Clark @ 2026-09-15 22:21 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Christian Brauner, Alexander Viro, Jann Horn, Jan Kara,
	Ingo Molnar, Peter Zijlstra, linux-fsdevel, linux-kernel,
	linux-mm, Oleg Nesterov, linux-alpha, linux-snps-arc,
	linux-arm-kernel, linux-csky, linux-hexagon, linux-m68k,
	linux-mips, linux-openrisc, linux-parisc, linux-sh, sparclinux,
	linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev, linux-gpio,
	linux-arm-msm, dri-devel, bpf, David Airlie, virtualization, kvm,
	kexec, linux-hyperv

On Tue, Sep 15, 2026 at 9:02 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> On Tue, 15 Sept 2026 at 04:31, Christian Brauner <brauner@kernel.org> wrote:
> >
> > TL;DR, this lets arch code handle fd install and cleanup. fd_prepare()
> > allocates a descriptor like get_unused_fd_flags() does and records it in
> > a slot on the task. fd_stage() attaches the file to that slot and
> > returns the number.
>
> Honestly, I am *not* a fan. At all.
>
> I think this adds complexity rather than removing it.
>
> The diffstat tells a story:
>
> >  106 files changed, 962 insertions(+), 861 deletions(-)
>
> in how this adds a hundred lines more than it deletes.
>
> But to make things worse, it adds them in bad places: low-level
> architecture assembly code.
>
> Those extra lines are *not* making complicated code simpler. Quite the
> reverse. They are taking fairly straightforward "just deal with errors
> with normal cleanup in the place where it makes sense" and makes the
> *straightforward* case simpler, while making the big picture more
> complicated and subtle, and adding new code to places that are not
> simple and just blindly do somethign that makes no sense in that
> context.

With fd's it is more than just about error rollback.. exposing an fd
to userspace mid-way thru an ioctl is an easy security bug to write..

OTOH, "just use FD_PREPARE() / fd_publish()"..

BR,
-R

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 22:21   ` Rob Clark
@ 2026-09-15 22:54     ` Linus Torvalds
  0 siblings, 0 replies; 108+ messages in thread
From: Linus Torvalds @ 2026-09-15 22:54 UTC (permalink / raw)
  To: rob.clark
  Cc: Christian Brauner, Alexander Viro, Jann Horn, Jan Kara,
	Ingo Molnar, Peter Zijlstra, linux-fsdevel, linux-kernel,
	linux-mm, Oleg Nesterov, linux-alpha, linux-snps-arc,
	linux-arm-kernel, linux-csky, linux-hexagon, linux-m68k,
	linux-mips, linux-openrisc, linux-parisc, linux-sh, sparclinux,
	linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev, linux-gpio,
	linux-arm-msm, dri-devel, bpf, David Airlie, virtualization, kvm,
	kexec, linux-hyperv

On Tue, 15 Sept 2026 at 15:21, Rob Clark <rob.clark@oss.qualcomm.com> wrote:
>
> With fd's it is more than just about error rollback.. exposing an fd
> to userspace mid-way thru an ioctl is an easy security bug to write..

That isn't very common code. It's something that is done by a few
strange cases, and yes, those cases should just do it right.

But "those few cases should do it right" does not mean "make a whole
new subsystem for this thing that makes a simple "open" actually be
slower and stranger".

             Linus

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 16:02 ` [PATCH RFC POC 00/50] file: handle files on syscall exit Linus Torvalds
  2026-09-15 22:21   ` Rob Clark
@ 2026-09-16  7:09   ` Christian Brauner
  1 sibling, 0 replies; 108+ messages in thread
From: Christian Brauner @ 2026-09-16  7:09 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Alexander Viro, Jann Horn, Jan Kara, Ingo Molnar, Peter Zijlstra,
	linux-fsdevel, linux-kernel, linux-mm, Oleg Nesterov, linux-alpha,
	linux-snps-arc, linux-arm-kernel, linux-csky, linux-hexagon,
	linux-m68k, linux-mips, linux-openrisc, linux-parisc, linux-sh,
	sparclinux, linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev,
	linux-gpio, linux-arm-msm, dri-devel, bpf, David Airlie,
	virtualization, kvm, kexec, linux-hyperv

On Tue, Sep 15, 2026 at 09:02:31AM -0700, Linus Torvalds wrote:
> On Tue, 15 Sept 2026 at 04:31, Christian Brauner <brauner@kernel.org> wrote:
> >
> > TL;DR, this lets arch code handle fd install and cleanup. fd_prepare()
> > allocates a descriptor like get_unused_fd_flags() does and records it in
> > a slot on the task. fd_stage() attaches the file to that slot and
> > returns the number.
> 
> Honestly, I am *not* a fan. At all.

I'm really glad that you don't like it! I hate it too.

To quote back from the cover letter:

> The idea in this series is old-ish and really never let go of me and so
> I wanted to at least dump it onto the list once even if it's just for
> illustrative purposes.

I think the cleanup-based solution we've added a couple of releases ago
is the better appraoch. Which is why I chose it over this.

But this install-on-the-way-out idea has been brought up quite a few
times as the "better approach". I never really believed it would work
nicely. Now we have an implementation on the list that we can point to
and we can move on from this.

^ permalink raw reply	[flat|nested] 108+ messages in thread

* Re: [PATCH RFC POC 00/50] file: handle files on syscall exit
  2026-09-15 19:08   ` Linus Torvalds
@ 2026-09-16  9:50     ` David Laight
  0 siblings, 0 replies; 108+ messages in thread
From: David Laight @ 2026-09-16  9:50 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Jann Horn, Christian Brauner, Alexander Viro, Jan Kara,
	Ingo Molnar, Peter Zijlstra, linux-fsdevel, linux-kernel,
	linux-mm, Oleg Nesterov, linux-alpha, linux-snps-arc,
	linux-arm-kernel, linux-csky, linux-hexagon, linux-m68k,
	linux-mips, linux-openrisc, linux-parisc, linux-sh, sparclinux,
	linux-um, Jens Axboe, io-uring, netdev, linuxppc-dev, linux-gpio,
	linux-arm-msm, dri-devel, bpf, David Airlie, virtualization, kvm,
	kexec, linux-hyperv

On Tue, 15 Sep 2026 12:08:57 -0700
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> On Tue, 15 Sept 2026 at 10:52, Jann Horn <jannh@google.com> wrote:
> >
> > Is this mainly about stuff like "we installed a file descriptor and
> > then the following put_user() failed"? Because if so, I think a nicer
> > fix would be to have a policy of "if userspace provides unwritable
> > memory to a syscall, just keep going and pretend the access worked",
> > and maybe have a sysctl that kills the process when this happens to
> > emphasize that userspace should not be doing this.  
> 
> We've done that before, where we just ignore put_user() errors and the
> user gets whatever the user gets.
> 
> It is maybe not optimal, but it's fine. You can find quite a lot of
> unchecked put_user() calls with a pattern like
> 
>         git grep '^[[:space:]]*put_user(.*);'
> 
> and some of them are in core code - see the two in kernel/fork.c, for example.
> 
> One of them says "if userspace has not set up a proper pointer then
> tough luck". The other one doesn't even bother with a comment.

I think the code should try to return EFAULT (IIRC that is too hard
in one of the exec cases).
Otherwise very unexpected things might happen if the memory is just
readonly.
If you ignore the error and the pointer is invalid the application will
get a SIGSEGV and (usually) die.
But winding back kernel data because a user copy failed is likely to
be problematic/difficult and at best have error path code that isn't
really tested.

As well as writing fd numbers to userspace, some sockopt code tries to
wind back if the write to optlen fails (which has been read earlier).

I've forgotten which Unix converted EFAULT to SIGSEGV in the system
call exit code - I'm sure one of the ones I've used did.

David

> 
> The scheduler has two cases too, although one of them is admittedly
> for another error case.
> 
> So yes, saying "if you pass bogus arguments, you get what you get" is
> a valid model. It's perhaps not the *preferred* model, but it's not
> wrong.
> 
> It *would* be wrong to take code that already has error handling and
> remove the error handling, though.
> 
>                   Linus
> 


^ permalink raw reply	[flat|nested] 108+ messages in thread

end of thread, other threads:[~2026-09-16  9:50 UTC | newest]

Thread overview: 108+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-15 11:30 [PATCH RFC POC 00/50] file: handle files on syscall exit Christian Brauner
2026-09-15 11:30 ` [PATCH RFC POC 01/50] file: install " Christian Brauner
2026-09-15 11:55   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 02/50] entry: commit fds " Christian Brauner
2026-09-15 11:52   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 03/50] alpha: " Christian Brauner
2026-09-15 11:50   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 04/50] ARC: " Christian Brauner
2026-09-15 11:48   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 05/50] ARM: " Christian Brauner
2026-09-15 11:59   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 06/50] arm64: " Christian Brauner
2026-09-15 11:48   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 07/50] csky: " Christian Brauner
2026-09-15 11:47   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 08/50] hexagon: " Christian Brauner
2026-09-15 11:49   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 09/50] m68k: " Christian Brauner
2026-09-15 11:50   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 10/50] microblaze: " Christian Brauner
2026-09-15 11:48   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 11/50] MIPS: " Christian Brauner
2026-09-15 11:45   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 12/50] nios2: " Christian Brauner
2026-09-15 11:54   ` sashiko-bot
2026-09-15 11:30 ` [PATCH RFC POC 13/50] openrisc: " Christian Brauner
2026-09-15 12:02   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 14/50] parisc: " Christian Brauner
2026-09-15 11:59   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 15/50] sh: " Christian Brauner
2026-09-15 11:55   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 16/50] sparc: " Christian Brauner
2026-09-15 11:57   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 17/50] um: " Christian Brauner
2026-09-15 11:55   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 18/50] xtensa: " Christian Brauner
2026-09-15 12:00   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 19/50] file: require the syscall exit hook from every architecture Christian Brauner
2026-09-15 11:54   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 20/50] file: warn when the descriptor table is unshared with slots Christian Brauner
2026-09-15 12:02   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 21/50] io_uring: commit fds per request Christian Brauner
2026-09-15 12:11   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 22/50] net: install SCM_RIGHTS descriptors when recvmsg() returns Christian Brauner
2026-09-15 12:03   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 23/50] file: open-code receive_fd()'s immediate install Christian Brauner
2026-09-15 12:00   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 24/50] file: make FD_ADD() a standalone " Christian Brauner
2026-09-15 12:01   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 25/50] file: reimplement FD_PREPARE() on the deferred fd_prepare() path Christian Brauner
2026-09-15 12:05   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 26/50] dma-buf: stop unwinding sync file descriptors by hand Christian Brauner
2026-09-15 12:05   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 27/50] drm/amdkfd: stop collecting CRIU dma-buf descriptors for a final install Christian Brauner
2026-09-15 12:04   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 28/50] drm/msm: install the out-fence descriptor when the ioctl returns Christian Brauner
2026-09-15 12:04   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 29/50] drm/virtio: " Christian Brauner
2026-09-15 12:11   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 30/50] drm/vmwgfx: " Christian Brauner
2026-09-15 12:09   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 31/50] vfio: install the migration data " Christian Brauner
2026-09-15 12:07   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 32/50] liveupdate: install the session descriptors " Christian Brauner
2026-09-15 12:09   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 33/50] io_uring/zcrx: install the exported descriptor when the request returns Christian Brauner
2026-09-15 12:09   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 34/50] sctp: install the peeloff descriptor when the syscall returns Christian Brauner
2026-09-15 12:14   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 35/50] ALSA: compress: install the task descriptors when the ioctl returns Christian Brauner
2026-09-15 12:13   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 36/50] nitro_enclaves: install the enclave descriptor " Christian Brauner
2026-09-15 12:13   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 37/50] tpm: vtpm_proxy: install the server " Christian Brauner
2026-09-15 12:14   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 38/50] perf: stop putting the event descriptor back on failure Christian Brauner
2026-09-15 12:12   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 39/50] seccomp: stop putting the listener " Christian Brauner
2026-09-15 12:14   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 40/50] KVM: stop putting descriptors " Christian Brauner
2026-09-15 12:15   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 41/50] KVM: guest_memfd: stop putting the descriptor " Christian Brauner
2026-09-15 12:16   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 42/50] drm: stop unwinding descriptors by hand Christian Brauner
2026-09-15 12:17   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 43/50] drm/amdgpu: stop unwinding the fence descriptor " Christian Brauner
2026-09-15 12:14   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 44/50] drm/etnaviv: install the out-fence descriptor when the ioctl returns Christian Brauner
2026-09-15 12:15   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 45/50] accel/habanalabs: stop putting the dma-buf descriptor back on failure Christian Brauner
2026-09-15 12:18   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 46/50] xen/gntdev-dmabuf: stop putting the " Christian Brauner
2026-09-15 12:21   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 47/50] iio: buffer: install the buffer descriptor when the ioctl returns Christian Brauner
2026-09-15 12:18   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 48/50] misc: fastrpc: install the dma-buf " Christian Brauner
2026-09-15 12:20   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 49/50] iommufd: stop putting descriptors back on failure Christian Brauner
2026-09-15 12:21   ` sashiko-bot
2026-09-15 11:31 ` [PATCH RFC POC 50/50] Drivers: hv: mshv: " Christian Brauner
2026-09-15 12:19   ` sashiko-bot
2026-09-15 16:02 ` [PATCH RFC POC 00/50] file: handle files on syscall exit Linus Torvalds
2026-09-15 22:21   ` Rob Clark
2026-09-15 22:54     ` Linus Torvalds
2026-09-16  7:09   ` Christian Brauner
2026-09-15 17:51 ` Jann Horn
2026-09-15 19:08   ` Linus Torvalds
2026-09-16  9:50     ` David Laight

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).