Re: [RFC v2 2/4] cred: Add a light version of override/revert_creds()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
>





[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux