linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Christian Brauner <brauner@kernel.org>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [GIT PULL 08/17 for v6.19] cred guards
Date: Fri, 28 Nov 2025 17:48:19 +0100	[thread overview]
Message-ID: <20251128-kernel-cred-guards-v619-92c5a929779c@brauner> (raw)
In-Reply-To: <20251128-vfs-v619-77cd88166806@brauner>

Hey Linus,

/* Summary */
This contains substantial credential infrastructure improvements adding
euard-based credential management that simplifies code and eliminates
manual reference counting in many subsystems.

Features

- Kernel Credential Guards

  Add with_kernel_creds() and scoped_with_kernel_creds() guards that allow
  using the kernel credentials without allocating and copying them. This
  was requested by Linus after seeing repeated prepare_kernel_creds() calls
  that duplicate the kernel credentials only to drop them again later.

  The new guards completely avoid the allocation and never expose the
  temporary variable to hold the kernel credentials anywhere in callers.

- Generic Credential Guards

  Add scoped_with_creds() guards for the common
  override_creds()/revert_creds() pattern. This builds on earlier work
  that made override_creds()/revert_creds() completely reference count
  free.

- Prepare Credential Guards

  Add prepare credential guards for the more complex pattern of
  preparing a new set of credentials and overriding the current
  credentials with them:
  (1) prepare_creds()
  (2) modify new creds
  (3) override_creds()
  (4) revert_creds()
  (5) put_cred()

Cleanups

- Make init_cred static since it should not be directly accessed.

- Add kernel_cred() helper to properly access the kernel credentials.

- Fix scoped_class() macro that was introduced two cycles ago.

- coredump: split out do_coredump() from vfs_coredump() for cleaner
  credential handling.

- coredump: move revert_cred() before coredump_cleanup().

- coredump: mark struct mm_struct as const.

- coredump: pass struct linux_binfmt as const.

- sev-dev: use guard for path.

/* Testing */

gcc (Debian 14.2.0-19) 14.2.0
Debian clang version 19.1.7 (3+b1)

No build failures or warnings were observed.

/* Conflicts */

Merge conflicts with mainline
=============================

diff --cc fs/backing-file.c
index 2a86bb6fcd13,ea137be16331..000000000000
--- a/fs/backing-file.c
+++ b/fs/backing-file.c
@@@ -227,40 -267,14 +267,8 @@@ ssize_t backing_file_write_iter(struct 
  	    !(file->f_mode & FMODE_CAN_ODIRECT))
  		return -EINVAL;
  
- 	old_cred = override_creds(ctx->cred);
- 	if (is_sync_kiocb(iocb)) {
- 		rwf_t rwf = iocb_to_rw_flags(flags);
- 
- 		ret = vfs_iter_write(file, iter, &iocb->ki_pos, rwf);
- 		if (ctx->end_write)
- 			ctx->end_write(iocb, ret);
- 	} else {
- 		struct backing_aio *aio;
- 
- 		ret = backing_aio_init_wq(iocb);
- 		if (ret)
- 			goto out;
- 
- 		ret = -ENOMEM;
- 		aio = kmem_cache_zalloc(backing_aio_cachep, GFP_KERNEL);
- 		if (!aio)
- 			goto out;
- 
- 		aio->orig_iocb = iocb;
- 		aio->end_write = ctx->end_write;
- 		kiocb_clone(&aio->iocb, iocb, get_file(file));
- 		aio->iocb.ki_flags = flags;
- 		aio->iocb.ki_complete = backing_aio_queue_completion;
- 		refcount_set(&aio->ref, 2);
- 		ret = vfs_iocb_iter_write(file, &aio->iocb, iter);
- 		backing_aio_put(aio);
- 		if (ret != -EIOCBQUEUED)
- 			backing_aio_cleanup(aio, ret);
- 	}
- out:
- 	revert_creds(old_cred);
 -	/*
 -	 * Stacked filesystems don't support deferred completions, don't copy
 -	 * this property in case it is set by the issuer.
 -	 */
 -	flags &= ~IOCB_DIO_CALLER_COMP;
--
- 	return ret;
+ 	scoped_with_creds(ctx->cred)
+ 		return do_backing_file_write_iter(file, iter, iocb, flags, ctx->end_write);
  }
  EXPORT_SYMBOL_GPL(backing_file_write_iter);
  
diff --cc fs/nfs/localio.c
index 656976b4f42c,0c89a9d1e089..000000000000
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@@ -620,37 -595,30 +620,34 @@@ static void nfs_local_call_read(struct 
  	struct nfs_local_kiocb *iocb =
  		container_of(work, struct nfs_local_kiocb, work);
  	struct file *filp = iocb->kiocb.ki_filp;
- 	const struct cred *save_cred;
 +	bool force_done = false;
  	ssize_t status;
 +	int n_iters;
  
- 	save_cred = override_creds(filp->f_cred);
- 
- 	n_iters = atomic_read(&iocb->n_iters);
- 	for (int i = 0; i < n_iters ; i++) {
- 		if (iocb->iter_is_dio_aligned[i]) {
- 			iocb->kiocb.ki_flags |= IOCB_DIRECT;
- 			/* Only use AIO completion if DIO-aligned segment is last */
- 			if (i == iocb->end_iter_index) {
- 				iocb->kiocb.ki_complete = nfs_local_read_aio_complete;
- 				iocb->aio_complete_work = nfs_local_read_aio_complete_work;
- 			}
- 		} else
- 			iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
- 
- 		status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]);
- 		if (status != -EIOCBQUEUED) {
- 			if (unlikely(status >= 0 && status < iocb->iters[i].count))
- 				force_done = true; /* Partial read */
- 			if (nfs_local_pgio_done(iocb, status, force_done)) {
- 				nfs_local_read_iocb_done(iocb);
- 				break;
+ 	scoped_with_creds(filp->f_cred) {
 -		for (int i = 0; i < iocb->n_iters ; i++) {
++		n_iters = atomic_read(&iocb->n_iters);
++		for (int i = 0; i < n_iters ; i++) {
+ 			if (iocb->iter_is_dio_aligned[i]) {
+ 				iocb->kiocb.ki_flags |= IOCB_DIRECT;
 -				iocb->kiocb.ki_complete = nfs_local_read_aio_complete;
 -				iocb->aio_complete_work = nfs_local_read_aio_complete_work;
 -			}
++				/* Only use AIO completion if DIO-aligned segment is last */
++				if (i == iocb->end_iter_index) {
++					iocb->kiocb.ki_complete = nfs_local_read_aio_complete;
++					iocb->aio_complete_work = nfs_local_read_aio_complete_work;
++				}
++			} else
++				iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
+ 
 -			iocb->kiocb.ki_pos = iocb->offset[i];
+ 			status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]);
+ 			if (status != -EIOCBQUEUED) {
 -				nfs_local_pgio_done(iocb->hdr, status);
 -				if (iocb->hdr->task.tk_status)
++				if (unlikely(status >= 0 && status < iocb->iters[i].count))
++					force_done = true; /* Partial read */
++				if (nfs_local_pgio_done(iocb, status, force_done)) {
++					nfs_local_read_iocb_done(iocb);
+ 					break;
++				}
  			}
  		}
  	}
--
- 	revert_creds(save_cred);
 -	if (status != -EIOCBQUEUED) {
 -		nfs_local_read_done(iocb, status);
 -		nfs_local_pgio_release(iocb);
 -	}
  }
  
  static int
@@@ -826,41 -839,20 +823,40 @@@ static void nfs_local_call_write(struc
  		container_of(work, struct nfs_local_kiocb, work);
  	struct file *filp = iocb->kiocb.ki_filp;
  	unsigned long old_flags = current->flags;
- 	const struct cred *save_cred;
 +	bool force_done = false;
  	ssize_t status;
 +	int n_iters;
  
  	current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
- 	save_cred = override_creds(filp->f_cred);
  
 -	scoped_with_creds(filp->f_cred)
 -		status = do_nfs_local_call_write(iocb, filp);
 -
 -	current->flags = old_flags;
++	scoped_with_creds(filp->f_cred) {
 +	file_start_write(filp);
- 	n_iters = atomic_read(&iocb->n_iters);
- 	for (int i = 0; i < n_iters ; i++) {
- 		if (iocb->iter_is_dio_aligned[i]) {
- 			iocb->kiocb.ki_flags |= IOCB_DIRECT;
- 			/* Only use AIO completion if DIO-aligned segment is last */
- 			if (i == iocb->end_iter_index) {
- 				iocb->kiocb.ki_complete = nfs_local_write_aio_complete;
- 				iocb->aio_complete_work = nfs_local_write_aio_complete_work;
- 			}
- 		} else
- 			iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
- 
- 		status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]);
- 		if (status != -EIOCBQUEUED) {
- 			if (unlikely(status >= 0 && status < iocb->iters[i].count))
- 				force_done = true; /* Partial write */
- 			if (nfs_local_pgio_done(iocb, status, force_done)) {
- 				nfs_local_write_iocb_done(iocb);
- 				break;
++		n_iters = atomic_read(&iocb->n_iters);
++		for (int i = 0; i < n_iters ; i++) {
++			if (iocb->iter_is_dio_aligned[i]) {
++				iocb->kiocb.ki_flags |= IOCB_DIRECT;
++				/* Only use AIO completion if DIO-aligned segment is last */
++				if (i == iocb->end_iter_index) {
++					iocb->kiocb.ki_complete = nfs_local_write_aio_complete;
++					iocb->aio_complete_work = nfs_local_write_aio_complete_work;
++				}
++			} else
++				iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
+ 
 -	if (status != -EIOCBQUEUED) {
 -		nfs_local_write_done(iocb, status);
 -		nfs_local_vfs_getattr(iocb);
 -		nfs_local_pgio_release(iocb);
++			status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]);
++			if (status != -EIOCBQUEUED) {
++				if (unlikely(status >= 0 && status < iocb->iters[i].count))
++					force_done = true; /* Partial write */
++				if (nfs_local_pgio_done(iocb, status, force_done)) {
++					nfs_local_write_iocb_done(iocb);
++					break;
++				}
 +			}
 +		}
++		file_end_write(filp);
  	}
- 	file_end_write(filp);
 +
- 	revert_creds(save_cred);
 +	current->flags = old_flags;
  }
  
  static int

Merge conflicts with other trees
================================

The following changes since commit dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa:

  Linux 6.18-rc3 (2025-10-26 15:59:49 -0700)

are available in the Git repository at:

  git@gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs tags/kernel-6.19-rc1.cred

for you to fetch changes up to c8e00cdc7425d5c60fd1ce6e7f71e5fb1b236991:

  Merge patch series "credential guards: credential preparation" (2025-11-05 23:11:52 +0100)

Please consider pulling these changes from the signed kernel-6.19-rc1.cred tag.

Thanks!
Christian

----------------------------------------------------------------
kernel-6.19-rc1.cred

----------------------------------------------------------------
Christian Brauner (39):
      cleanup: fix scoped_class()
      cred: add kernel_cred() helper
      cred: make init_cred static
      cred: add scoped_with_kernel_creds()
      firmware: don't copy kernel creds
      nbd: don't copy kernel creds
      target: don't copy kernel creds
      unix: don't copy creds
      Merge patch series "creds: add {scoped_}with_kernel_creds()"
      cred: add scoped_with_creds() guards
      aio: use credential guards
      backing-file: use credential guards for reads
      backing-file: use credential guards for writes
      backing-file: use credential guards for splice read
      backing-file: use credential guards for splice write
      backing-file: use credential guards for mmap
      binfmt_misc: use credential guards
      erofs: use credential guards
      nfs: use credential guards in nfs_local_call_read()
      nfs: use credential guards in nfs_local_call_write()
      nfs: use credential guards in nfs_idmap_get_key()
      smb: use credential guards in cifs_get_spnego_key()
      act: use credential guards in acct_write_process()
      cgroup: use credential guards in cgroup_attach_permissions()
      net/dns_resolver: use credential guards in dns_query()
      Merge patch series "credentials guards: the easy cases"
      cred: add prepare credential guard
      sev-dev: use guard for path
      sev-dev: use prepare credential guard
      sev-dev: use override credential guards
      coredump: move revert_cred() before coredump_cleanup()
      coredump: pass struct linux_binfmt as const
      coredump: mark struct mm_struct as const
      coredump: split out do_coredump() from vfs_coredump()
      coredump: use prepare credential guard
      coredump: use override credential guard
      trace: use prepare credential guard
      trace: use override credential guard
      Merge patch series "credential guards: credential preparation"

 drivers/base/firmware_loader/main.c   |  59 ++++++--------
 drivers/block/nbd.c                   |  54 +++++--------
 drivers/crypto/ccp/sev-dev.c          |  17 ++--
 drivers/target/target_core_configfs.c |  14 +---
 fs/aio.c                              |   6 +-
 fs/backing-file.c                     | 147 +++++++++++++++++-----------------
 fs/binfmt_misc.c                      |   7 +-
 fs/coredump.c                         | 142 ++++++++++++++++----------------
 fs/erofs/fileio.c                     |   6 +-
 fs/nfs/localio.c                      |  59 +++++++-------
 fs/nfs/nfs4idmap.c                    |   7 +-
 fs/smb/client/cifs_spnego.c           |   6 +-
 include/linux/cleanup.h               |  15 ++--
 include/linux/cred.h                  |  22 +++++
 include/linux/init_task.h             |   1 -
 include/linux/sched/coredump.h        |   2 +-
 init/init_task.c                      |  27 +++++++
 kernel/acct.c                         |  29 +++----
 kernel/cgroup/cgroup.c                |  10 +--
 kernel/cred.c                         |  27 -------
 kernel/trace/trace_events_user.c      |  22 ++---
 net/dns_resolver/dns_query.c          |   6 +-
 net/unix/af_unix.c                    |  17 +---
 security/keys/process_keys.c          |   2 +-
 24 files changed, 330 insertions(+), 374 deletions(-)

  parent reply	other threads:[~2025-11-28 16:51 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-28 16:48 [GIT PULL 00/17 for v6.19] v6.19 Christian Brauner
2025-11-28 16:48 ` [GIT PULL 01/17 for v6.19] vfs iomap Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 02/17 for v6.19] vfs misc Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 03/17 for v6.19] vfs inode Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 04/17 for v6.19] vfs writeback Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 05/17 for v6.19] namespaces Christian Brauner
2025-12-01 19:06   ` Eric W. Biederman
2025-12-02 17:00     ` Linus Torvalds
2025-12-03 10:07       ` Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 06/17 for v6.19] vfs coredump Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 07/17 for v6.19] vfs folio Christian Brauner
2025-12-01 22:08   ` pr-tracker-bot
2025-11-28 16:48 ` Christian Brauner [this message]
2025-12-01 21:53   ` [GIT PULL 08/17 for v6.19] cred guards Linus Torvalds
2025-12-02  1:26     ` Sasha Levin
2025-12-02  1:36       ` [PATCH] nfs/localio: make do_nfs_local_call_write() return void Sasha Levin
2025-12-01 22:08   ` [GIT PULL 08/17 for v6.19] cred guards pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 09/17 for v6.19] vfs headers Christian Brauner
2025-12-01 23:22   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 10/17 for v6.19] vfs super guards Christian Brauner
2025-12-01 23:22   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 11/17 for v6.19] minix Christian Brauner
2025-12-01 23:22   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 12/17 for v6.19] vfs directory delegations Christian Brauner
2025-12-02  3:19   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 13/17 for v6.19] vfs directory locking Christian Brauner
2025-12-02  3:19   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 14/17 for v6.19] overlayfs cred guards Christian Brauner
2025-12-02  3:19   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 15/17 for v6.19] autofs Christian Brauner
2025-12-02  3:19   ` pr-tracker-bot
2025-11-28 16:48 ` [GIT PULL 16/17 for v6.19] vfs fd prepare Christian Brauner
2025-12-01 14:15   ` Al Viro
2025-12-01 18:41     ` Sean Christopherson
2025-11-28 16:48 ` [GIT PULL 17/17 for v6.19] vfs fd prepare minimal Christian Brauner
2025-12-02  1:35   ` Linus Torvalds
2025-12-02  9:42     ` Christian Brauner
2025-12-02  3:19   ` pr-tracker-bot

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20251128-kernel-cred-guards-v619-92c5a929779c@brauner \
    --to=brauner@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

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

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