Merge branch 'kernel-6.14.cred' into vfs.all

This commit is contained in:
Christian Brauner 2025-01-10 16:17:43 +01:00
commit b3ffcb5635
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
13 changed files with 29 additions and 129 deletions

View File

@ -527,11 +527,6 @@ There are some functions to help manage credentials:
This gets a reference on a live set of credentials, returning a pointer to This gets a reference on a live set of credentials, returning a pointer to
that set of credentials. that set of credentials.
- ``struct cred *get_new_cred(struct cred *cred);``
This gets a reference on a set of credentials that is under construction
and is thus still mutable, returning a pointer to that set of credentials.
Open File Credentials Open File Credentials
===================== =====================

View File

@ -249,7 +249,7 @@ static struct file *open_file_as_root(const char *filename, int flags, umode_t m
fp = file_open_root(&root, filename, flags, mode); fp = file_open_root(&root, filename, flags, mode);
path_put(&root); path_put(&root);
revert_creds(old_cred); put_cred(revert_creds(old_cred));
return fp; return fp;
} }

View File

@ -176,7 +176,7 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
!(file->f_mode & FMODE_CAN_ODIRECT)) !(file->f_mode & FMODE_CAN_ODIRECT))
return -EINVAL; return -EINVAL;
old_cred = override_creds_light(ctx->cred); old_cred = override_creds(ctx->cred);
if (is_sync_kiocb(iocb)) { if (is_sync_kiocb(iocb)) {
rwf_t rwf = iocb_to_rw_flags(flags); rwf_t rwf = iocb_to_rw_flags(flags);
@ -197,7 +197,7 @@ ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
backing_aio_cleanup(aio, ret); backing_aio_cleanup(aio, ret);
} }
out: out:
revert_creds_light(old_cred); revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(iocb->ki_filp); ctx->accessed(iocb->ki_filp);
@ -233,7 +233,7 @@ ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
*/ */
flags &= ~IOCB_DIO_CALLER_COMP; flags &= ~IOCB_DIO_CALLER_COMP;
old_cred = override_creds_light(ctx->cred); old_cred = override_creds(ctx->cred);
if (is_sync_kiocb(iocb)) { if (is_sync_kiocb(iocb)) {
rwf_t rwf = iocb_to_rw_flags(flags); rwf_t rwf = iocb_to_rw_flags(flags);
@ -264,7 +264,7 @@ ssize_t backing_file_write_iter(struct file *file, struct iov_iter *iter,
backing_aio_cleanup(aio, ret); backing_aio_cleanup(aio, ret);
} }
out: out:
revert_creds_light(old_cred); revert_creds(old_cred);
return ret; return ret;
} }
@ -281,9 +281,9 @@ ssize_t backing_file_splice_read(struct file *in, struct kiocb *iocb,
if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING))) if (WARN_ON_ONCE(!(in->f_mode & FMODE_BACKING)))
return -EIO; return -EIO;
old_cred = override_creds_light(ctx->cred); old_cred = override_creds(ctx->cred);
ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags); ret = vfs_splice_read(in, &iocb->ki_pos, pipe, len, flags);
revert_creds_light(old_cred); revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(iocb->ki_filp); ctx->accessed(iocb->ki_filp);
@ -310,11 +310,11 @@ ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
if (ret) if (ret)
return ret; return ret;
old_cred = override_creds_light(ctx->cred); old_cred = override_creds(ctx->cred);
file_start_write(out); file_start_write(out);
ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags); ret = out->f_op->splice_write(pipe, out, &iocb->ki_pos, len, flags);
file_end_write(out); file_end_write(out);
revert_creds_light(old_cred); revert_creds(old_cred);
if (ctx->end_write) if (ctx->end_write)
ctx->end_write(iocb, ret); ctx->end_write(iocb, ret);
@ -338,9 +338,9 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
vma_set_file(vma, file); vma_set_file(vma, file);
old_cred = override_creds_light(ctx->cred); old_cred = override_creds(ctx->cred);
ret = call_mmap(vma->vm_file, vma); ret = call_mmap(vma->vm_file, vma);
revert_creds_light(old_cred); revert_creds(old_cred);
if (ctx->accessed) if (ctx->accessed)
ctx->accessed(user_file); ctx->accessed(user_file);

View File

@ -27,7 +27,7 @@ int nfsd_setuser(struct svc_cred *cred, struct svc_export *exp)
int flags = nfsexp_flags(cred, exp); int flags = nfsexp_flags(cred, exp);
/* discard any old override before preparing the new set */ /* discard any old override before preparing the new set */
revert_creds(get_cred(current_real_cred())); put_cred(revert_creds(get_cred(current_real_cred())));
new = prepare_creds(); new = prepare_creds();
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
@ -80,7 +80,6 @@ int nfsd_setuser(struct svc_cred *cred, struct svc_export *exp)
new->cap_effective = cap_raise_nfsd_set(new->cap_effective, new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
new->cap_permitted); new->cap_permitted);
put_cred(override_creds(new)); put_cred(override_creds(new));
put_cred(new);
return 0; return 0;
oom: oom:

View File

@ -1248,7 +1248,7 @@ nfsd_file_acquire_local(struct net *net, struct svc_cred *cred,
beres = nfsd_file_do_acquire(NULL, net, cred, client, beres = nfsd_file_do_acquire(NULL, net, cred, client,
fhp, may_flags, NULL, pnf, true); fhp, may_flags, NULL, pnf, true);
revert_creds(save_cred); put_cred(revert_creds(save_cred));
return beres; return beres;
} }

View File

@ -82,14 +82,13 @@ nfs4_save_creds(const struct cred **original_creds)
new->fsuid = GLOBAL_ROOT_UID; new->fsuid = GLOBAL_ROOT_UID;
new->fsgid = GLOBAL_ROOT_GID; new->fsgid = GLOBAL_ROOT_GID;
*original_creds = override_creds(new); *original_creds = override_creds(new);
put_cred(new);
return 0; return 0;
} }
static void static void
nfs4_reset_creds(const struct cred *original) nfs4_reset_creds(const struct cred *original)
{ {
revert_creds(original); put_cred(revert_creds(original));
} }
static void static void

View File

@ -222,7 +222,6 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
cap_raise_nfsd_set(new->cap_effective, cap_raise_nfsd_set(new->cap_effective,
new->cap_permitted); new->cap_permitted);
put_cred(override_creds(new)); put_cred(override_creds(new));
put_cred(new);
} else { } else {
error = nfsd_setuser_and_check_port(rqstp, cred, exp); error = nfsd_setuser_and_check_port(rqstp, cred, exp);
if (error) if (error)

View File

@ -402,7 +402,6 @@ static bool access_need_override_creds(int flags)
static const struct cred *access_override_creds(void) static const struct cred *access_override_creds(void)
{ {
const struct cred *old_cred;
struct cred *override_cred; struct cred *override_cred;
override_cred = prepare_creds(); override_cred = prepare_creds();
@ -447,13 +446,7 @@ static const struct cred *access_override_creds(void)
* freeing. * freeing.
*/ */
override_cred->non_rcu = 1; override_cred->non_rcu = 1;
return override_creds(override_cred);
old_cred = override_creds(override_cred);
/* override_cred() gets its own ref */
put_cred(override_cred);
return old_cred;
} }
static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) static long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
@ -523,7 +516,7 @@ out_path_release:
} }
out: out:
if (old_cred) if (old_cred)
revert_creds(old_cred); put_cred(revert_creds(old_cred));
return res; return res;
} }

View File

@ -575,12 +575,12 @@ static const struct cred *ovl_setup_cred_for_create(struct dentry *dentry,
} }
/* /*
* Caller is going to match this with revert_creds_light() and drop * Caller is going to match this with revert_creds() and drop
* referenec on the returned creds. * referenec on the returned creds.
* We must be called with creator creds already, otherwise we risk * We must be called with creator creds already, otherwise we risk
* leaking creds. * leaking creds.
*/ */
old_cred = override_creds_light(override_cred); old_cred = override_creds(override_cred);
WARN_ON_ONCE(old_cred != ovl_creds(dentry->d_sb)); WARN_ON_ONCE(old_cred != ovl_creds(dentry->d_sb));
return override_cred; return override_cred;

View File

@ -65,12 +65,12 @@ const struct cred *ovl_override_creds(struct super_block *sb)
{ {
struct ovl_fs *ofs = OVL_FS(sb); struct ovl_fs *ofs = OVL_FS(sb);
return override_creds_light(ofs->creator_cred); return override_creds(ofs->creator_cred);
} }
void ovl_revert_creds(const struct cred *old_cred) void ovl_revert_creds(const struct cred *old_cred)
{ {
revert_creds_light(old_cred); revert_creds(old_cred);
} }
/* /*

View File

@ -781,10 +781,6 @@ int __ksmbd_override_fsids(struct ksmbd_work *work,
WARN_ON(work->saved_cred); WARN_ON(work->saved_cred);
work->saved_cred = override_creds(cred); work->saved_cred = override_creds(cred);
if (!work->saved_cred) {
abort_creds(cred);
return -EINVAL;
}
return 0; return 0;
} }
@ -796,13 +792,11 @@ int ksmbd_override_fsids(struct ksmbd_work *work)
void ksmbd_revert_fsids(struct ksmbd_work *work) void ksmbd_revert_fsids(struct ksmbd_work *work)
{ {
const struct cred *cred; const struct cred *cred;
WARN_ON(!work->saved_cred); WARN_ON(!work->saved_cred);
cred = current_cred(); cred = revert_creds(work->saved_cred);
revert_creds(work->saved_cred);
put_cred(cred);
work->saved_cred = NULL; work->saved_cred = NULL;
put_cred(cred);
} }
__le32 smb_map_generic_desired_access(__le32 daccess) __le32 smb_map_generic_desired_access(__le32 daccess)

View File

@ -155,8 +155,6 @@ extern struct cred *prepare_creds(void);
extern struct cred *prepare_exec_creds(void); extern struct cred *prepare_exec_creds(void);
extern int commit_creds(struct cred *); extern int commit_creds(struct cred *);
extern void abort_creds(struct cred *); extern void abort_creds(struct cred *);
extern const struct cred *override_creds(const struct cred *);
extern void revert_creds(const struct cred *);
extern struct cred *prepare_kernel_cred(struct task_struct *); extern struct cred *prepare_kernel_cred(struct task_struct *);
extern int set_security_override(struct cred *, u32); extern int set_security_override(struct cred *, u32);
extern int set_security_override_from_ctx(struct cred *, const char *); extern int set_security_override_from_ctx(struct cred *, const char *);
@ -172,12 +170,7 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred)
cred->cap_inheritable)); cred->cap_inheritable));
} }
/* static inline const struct cred *override_creds(const struct cred *override_cred)
* Override creds without bumping reference count. Caller must ensure
* reference remains valid or has taken reference. Almost always not the
* interface you want. Use override_creds()/revert_creds() instead.
*/
static inline const struct cred *override_creds_light(const struct cred *override_cred)
{ {
const struct cred *old = current->cred; const struct cred *old = current->cred;
@ -185,35 +178,12 @@ static inline const struct cred *override_creds_light(const struct cred *overrid
return old; return old;
} }
static inline void revert_creds_light(const struct cred *revert_cred) static inline const struct cred *revert_creds(const struct cred *revert_cred)
{ {
const struct cred *override_cred = current->cred;
rcu_assign_pointer(current->cred, revert_cred); rcu_assign_pointer(current->cred, revert_cred);
} return override_cred;
/**
* get_new_cred_many - Get references on a new set of credentials
* @cred: The new credentials to reference
* @nr: Number of references to acquire
*
* Get references on the specified set of new credentials. The caller must
* release all acquired references.
*/
static inline struct cred *get_new_cred_many(struct cred *cred, int nr)
{
atomic_long_add(nr, &cred->usage);
return cred;
}
/**
* get_new_cred - Get a reference on a new set of credentials
* @cred: The new credentials to reference
*
* Get a reference on the specified set of new credentials. The caller must
* release the reference.
*/
static inline struct cred *get_new_cred(struct cred *cred)
{
return get_new_cred_many(cred, 1);
} }
/** /**
@ -236,7 +206,8 @@ static inline const struct cred *get_cred_many(const struct cred *cred, int nr)
if (!cred) if (!cred)
return cred; return cred;
nonconst_cred->non_rcu = 0; nonconst_cred->non_rcu = 0;
return get_new_cred_many(nonconst_cred, nr); atomic_long_add(nr, &nonconst_cred->usage);
return cred;
} }
/* /*

View File

@ -476,56 +476,6 @@ void abort_creds(struct cred *new)
} }
EXPORT_SYMBOL(abort_creds); EXPORT_SYMBOL(abort_creds);
/**
* override_creds - Override the current process's subjective credentials
* @new: The credentials to be assigned
*
* Install a set of temporary override subjective credentials on the current
* process, returning the old set for later reversion.
*/
const struct cred *override_creds(const struct cred *new)
{
const struct cred *old;
kdebug("override_creds(%p{%ld})", new,
atomic_long_read(&new->usage));
/*
* NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
*
* That means that we do not clear the 'non_rcu' flag, since
* we are only installing the cred into the thread-synchronous
* '->cred' pointer, not the '->real_cred' pointer that is
* visible to other threads under RCU.
*/
get_new_cred((struct cred *)new);
old = override_creds_light(new);
kdebug("override_creds() = %p{%ld}", old,
atomic_long_read(&old->usage));
return old;
}
EXPORT_SYMBOL(override_creds);
/**
* revert_creds - Revert a temporary subjective credentials override
* @old: The credentials to be restored
*
* Revert a temporary set of override subjective credentials to an old set,
* discarding the override set.
*/
void revert_creds(const struct cred *old)
{
const struct cred *override = current->cred;
kdebug("revert_creds(%p{%ld})", old,
atomic_long_read(&old->usage));
revert_creds_light(old);
put_cred(override);
}
EXPORT_SYMBOL(revert_creds);
/** /**
* cred_fscmp - Compare two credentials with respect to filesystem access. * cred_fscmp - Compare two credentials with respect to filesystem access.
* @a: The first credential * @a: The first credential