Re: [PATCH] cifs: Create dedicated keyring for spnego operations

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

 



Looks correct. May be init functions for idmap and spnego could be merged..

Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>

On Fri, Apr 22, 2016 at 2:58 PM, Sachin Prabhu <sprabhu@xxxxxxxxxx> wrote:
> The session key is the default keyring set for request_key operations.
> This session key is revoked when the user owning the session logs out.
> Any long running daemon processes started by this session ends up with
> revoked session keyring which prevents these processes from using the
> request_key mechanism from obtaining the krb5 keys.
>
> The problem has been reported by a large number of autofs users. The
> problem is also seen with multiuser mounts where the share may be used
> by processes run by a user who has since logged out. A reproducer using
> automount is available on the Red Hat bz.
>
> The patch creates a new keyring which is used to cache cifs spnego
> upcalls.
>
> Red Hat bz: 1267754
>
> Signed-off-by: Sachin Prabhu <sprabhu@xxxxxxxxxx>
> Reported-by: Scott Mayhew <smayhew@xxxxxxxxxx>
> ---
>  fs/cifs/cifs_spnego.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/cifs/cifsfs.c      |  4 +--
>  fs/cifs/cifsproto.h   |  2 ++
>  3 files changed, 71 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
> index 6908080..248ab43 100644
> --- a/fs/cifs/cifs_spnego.c
> +++ b/fs/cifs/cifs_spnego.c
> @@ -24,11 +24,14 @@
>  #include <linux/string.h>
>  #include <keys/user-type.h>
>  #include <linux/key-type.h>
> +#include <linux/keyctl.h>
>  #include <linux/inet.h>
>  #include "cifsglob.h"
>  #include "cifs_spnego.h"
>  #include "cifs_debug.h"
>
> +static const struct cred *spnego_cred;
> +
>  /* create a new cifs key */
>  static int
>  cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
> @@ -102,6 +105,7 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
>         size_t desc_len;
>         struct key *spnego_key;
>         const char *hostname = server->hostname;
> +       const struct cred *saved_cred;
>
>         /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
>            host=hostname sec=mechanism uid=0xFF user=username */
> @@ -163,7 +167,9 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
>         sprintf(dp, ";pid=0x%x", current->pid);
>
>         cifs_dbg(FYI, "key description = %s\n", description);
> +       saved_cred = override_creds(spnego_cred);
>         spnego_key = request_key(&cifs_spnego_key_type, description, "");
> +       revert_creds(saved_cred);
>
>  #ifdef CONFIG_CIFS_DEBUG2
>         if (cifsFYI && !IS_ERR(spnego_key)) {
> @@ -177,3 +183,64 @@ out:
>         kfree(description);
>         return spnego_key;
>  }
> +
> +int
> +init_cifs_spnego(void)
> +{
> +       struct cred *cred;
> +       struct key *keyring;
> +       int ret;
> +
> +       cifs_dbg(FYI, "Registering the %s key type\n",
> +                cifs_spnego_key_type.name);
> +
> +       /*
> +        * Create an override credential set with special thread keyring for
> +        * spnego upcalls.
> +        */
> +
> +       cred = prepare_kernel_cred(NULL);
> +       if (!cred)
> +               return -ENOMEM;
> +
> +       keyring = keyring_alloc(".cifs_spnego",
> +                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
> +                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
> +                               KEY_USR_VIEW | KEY_USR_READ,
> +                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
> +       if (IS_ERR(keyring)) {
> +               ret = PTR_ERR(keyring);
> +               goto failed_put_cred;
> +       }
> +
> +       ret = register_key_type(&cifs_spnego_key_type);
> +       if (ret < 0)
> +               goto failed_put_key;
> +
> +       /*
> +        * instruct request_key() to use this special keyring as a cache for
> +        * the results it looks up
> +        */
> +       set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
> +       cred->thread_keyring = keyring;
> +       cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
> +       spnego_cred = cred;
> +
> +       cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring));
> +       return 0;
> +
> +failed_put_key:
> +       key_put(keyring);
> +failed_put_cred:
> +       put_cred(cred);
> +       return ret;
> +}
> +
> +void
> +exit_cifs_spnego(void)
> +{
> +       key_revoke(spnego_cred->thread_keyring);
> +       unregister_key_type(&cifs_spnego_key_type);
> +       put_cred(spnego_cred);
> +       cifs_dbg(FYI, "Unregistered %s key type\n", cifs_spnego_key_type.name);
> +}
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 8920156..9852044 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -1307,7 +1307,7 @@ init_cifs(void)
>                 goto out_destroy_mids;
>
>  #ifdef CONFIG_CIFS_UPCALL
> -       rc = register_key_type(&cifs_spnego_key_type);
> +       rc = init_cifs_spnego();
>         if (rc)
>                 goto out_destroy_request_bufs;
>  #endif /* CONFIG_CIFS_UPCALL */
> @@ -1330,7 +1330,7 @@ out_init_cifs_idmap:
>  out_register_key_type:
>  #endif
>  #ifdef CONFIG_CIFS_UPCALL
> -       unregister_key_type(&cifs_spnego_key_type);
> +       exit_cifs_spnego();
>  out_destroy_request_bufs:
>  #endif
>         cifs_destroy_request_bufs();
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index eed7ff5..ca618b0 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -60,6 +60,8 @@ do {                                                          \
>  } while (0)
>  extern int init_cifs_idmap(void);
>  extern void exit_cifs_idmap(void);
> +extern int init_cifs_spnego(void);
> +extern int exit_cifs_spnego(void);
>  extern char *build_path_from_dentry(struct dentry *);
>  extern char *cifs_build_path_to_root(struct smb_vol *vol,
>                                      struct cifs_sb_info *cifs_sb,
> --
> 2.5.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux