On Fri, Jan 26, 2024 at 1:57 AM Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxx> wrote: > > Add a light version of override/revert_creds(), this should only be > used when the credentials in question will outlive the critical > section and the critical section doesn't change the ->usage of the > credentials. > > To make their usage less error prone, introduce cleanup guards asto be > used like this: > > guard(cred)(credentials_to_override_and_restore); > > or this: > > scoped_guard(cred, credentials_to_override_and_restore) { > /* with credentials overridden */ > } > > Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxx> You may add: Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx> I would also add: Suggested-by: Christian Brauner <brauner@xxxxxxxxxx> Thanks, Amir. > --- > include/linux/cred.h | 21 +++++++++++++++++++++ > kernel/cred.c | 6 +++--- > 2 files changed, 24 insertions(+), 3 deletions(-) > > diff --git a/include/linux/cred.h b/include/linux/cred.h > index 2976f534a7a3..e9f2237e4bf8 100644 > --- a/include/linux/cred.h > +++ b/include/linux/cred.h > @@ -172,6 +172,27 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred) > cred->cap_inheritable)); > } > > +/* > + * 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; > + > + rcu_assign_pointer(current->cred, override_cred); > + return old; > +} > + > +static inline void revert_creds_light(const struct cred *revert_cred) > +{ > + rcu_assign_pointer(current->cred, revert_cred); > +} > + > +DEFINE_GUARD(cred, const struct cred *, _T = override_creds_light(_T), > + revert_creds_light(_T)); > + > /** > * get_new_cred_many - Get references on a new set of credentials > * @cred: The new credentials to reference > diff --git a/kernel/cred.c b/kernel/cred.c > index c033a201c808..f95f71e3ac1d 100644 > --- a/kernel/cred.c > +++ b/kernel/cred.c > @@ -485,7 +485,7 @@ EXPORT_SYMBOL(abort_creds); > */ > const struct cred *override_creds(const struct cred *new) > { > - const struct cred *old = current->cred; > + const struct cred *old; > > kdebug("override_creds(%p{%ld})", new, > atomic_long_read(&new->usage)); > @@ -499,7 +499,7 @@ const struct cred *override_creds(const struct cred *new) > * visible to other threads under RCU. > */ > get_new_cred((struct cred *)new); > - rcu_assign_pointer(current->cred, new); > + old = override_creds_light(new); > > kdebug("override_creds() = %p{%ld}", old, > atomic_long_read(&old->usage)); > @@ -521,7 +521,7 @@ void revert_creds(const struct cred *old) > kdebug("revert_creds(%p{%ld})", old, > atomic_long_read(&old->usage)); > > - rcu_assign_pointer(current->cred, old); > + revert_creds_light(old); > put_cred(override); > } > EXPORT_SYMBOL(revert_creds); > -- > 2.43.0 >