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

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

 



On Sat, 2016-04-23 at 17:58 -0500, Shirish Pargaonkar wrote:
> Looks correct. May be init functions for idmap and spnego could be
> merged..

Thanks Sirish,

They have #ifdef..#endif set for different config options so I thought
it is better that they are initialised separately.

Sachin Prabhu

> 
> 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

--
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