Message ID | 1354560315-2393-2-git-send-email-andros@netapp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, 2012-12-03 at 13:45 -0500, andros@netapp.com wrote: > From: Andy Adamson <andros@netapp.com> > > This code works in conjunction with nfslogin and nfslogout programs > which enforce the use of the keyring Kerberos credential cache of the > form KEYRING:krb5cc_<UID> and adds a gss-ctx key to the krb5cc_<UID> keyring. > > When kdestroy is called on the keyring context the .destroy function of the > new key is called which marks all gss_context's associated with the UID as > out of date. > > Signed-off-by: Andy Adamson <andros@netapp.com> > --- > net/sunrpc/auth_gss/auth_gss.c | 85 ++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 85 insertions(+), 0 deletions(-) > > diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c > index 082e579..2d8fbf1 100644 > --- a/net/sunrpc/auth_gss/auth_gss.c > +++ b/net/sunrpc/auth_gss/auth_gss.c > @@ -51,6 +51,12 @@ > #include <linux/sunrpc/rpc_pipe_fs.h> > #include <linux/sunrpc/gss_api.h> > #include <asm/uaccess.h> > +#include <linux/key.h> > +#include <linux/keyctl.h> > +#include <linux/key-type.h> > +#include <keys/user-type.h> > + > +#include "../netns.h" > > static const struct rpc_authops authgss_ops; > > @@ -95,6 +101,83 @@ static void gss_free_ctx(struct gss_cl_ctx *); > static const struct rpc_pipe_ops gss_upcall_ops_v0; > static const struct rpc_pipe_ops gss_upcall_ops_v1; > > +/* > + * Search all rpc_clnt auth's and invalidate any RPC_AUT_GSS Kerberos > + * gss contexts belonging to uid. Triggered by kdestroy of keyring > + * kerberos credentials. > + */ > +static void > +gss_kdestroy_cred(uid_t uid) > +{ > + struct net *net = current->nsproxy->net_ns; > + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); > + struct rpc_clnt *clnt; > + struct rpc_cred *cr; > + struct auth_cred ac = { > + .uid = uid, > + }; > + > + dprintk("--> %s uid %d\n", __func__, uid); > + spin_lock(&sn->rpc_client_lock); > + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { > + if ((clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5) || > + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5I) || > + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5P)) { > + cr = rpcauth_lookup_credcache(clnt->cl_auth, &ac, 0); > + if (IS_ERR(cr) || cr == NULL) > + continue; > + dprintk("%s invalidated cred %p from auth %p crcache\n", > + __func__, cr, clnt->cl_auth); > + smp_mb__before_clear_bit(); > + clear_bit(RPCAUTH_CRED_UPTODATE, &cr->cr_flags); > + smp_mb__after_clear_bit(); > + put_rpccred(cr); /* balance get in lookup credcache */ > + } > + } > + spin_unlock(&sn->rpc_client_lock); > +} > + > +static void > +gss_user_destroy(struct key *key) > +{ > + struct user_key_payload *upayload; > + int uid = 0; > + > + upayload = rcu_dereference_key(key); > + memcpy((void *)&uid, upayload->data, sizeof(int)); It seems to me that this code allows me to kill anyone's rpcsec_gss sessions by creating a key with their uid, and then destroying it. One solution is to replace user_instantiate() with something that sets the payload to a value determined by the kernel itself. We'd definitely want to include the uid, but perhaps also add a cookie that is unique to this key (using the idr/ida stuff from include/linux/idr.h ?), and that can be used to distinguish it from keys generated from other processes. If we were to use the same key to label the auth_gss creds, then we could have user_gss_destroy() kill _only_ the auth_gss creds that it spawned. Ultimately, though, I think we might want to let the user set at least _part_ of the payload to something that might be useful to gssd when it goes looking for credentials. Since the nfslogin and gssd will be shipped as part of the nfs-utils package, it would be nice to allow them to use the gss-ctx key in order to communicate. Interesting information might include the KRB5CCNAME. > + gss_kdestroy_cred((uid_t)uid); > + return user_destroy(key); > +} > + > +static struct key_type key_type_gss_ctx = { > + .name = "gss-ctx", > + .instantiate = user_instantiate, > + .match = user_match, > + .revoke = user_revoke, > + .destroy = gss_user_destroy, > + .describe = user_describe, > + .read = user_read, > +}; > + > + > +/* Register the gss-ctx key type for use by nfslogin and nfslogout */ > +static int gss_register_ctx_keytype(void) > +{ > + int ret; > + > + ret = register_key_type(&key_type_gss_ctx); > + > + pr_notice("NFS: Registering the %s key type ret %d\n", > + key_type_gss_ctx.name, ret); > + > + return ret; > +} > + > +static void gss_unregister_ctx_keytype(void) > +{ > + unregister_key_type(&key_type_gss_ctx); > +} > + > static inline struct gss_cl_ctx * > gss_get_ctx(struct gss_cl_ctx *ctx) > { > @@ -1748,6 +1831,7 @@ static int __init init_rpcsec_gss(void) > if (err) > goto out_svc_exit; > rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); > + gss_register_ctx_keytype(); > return 0; > out_svc_exit: > gss_svc_shutdown(); > @@ -1762,6 +1846,7 @@ static void __exit exit_rpcsec_gss(void) > unregister_pernet_subsys(&rpcsec_gss_net_ops); > gss_svc_shutdown(); > rpcauth_unregister(&authgss_ops); > + gss_unregister_ctx_keytype(); > rcu_barrier(); /* Wait for completion of call_rcu()'s */ > } > -- Trond Myklebust Linux NFS client maintainer NetApp Trond.Myklebust@netapp.com www.netapp.com
On Dec 3, 2012, at 4:06 PM, "Myklebust, Trond" <Trond.Myklebust@netapp.com> wrote: > On Mon, 2012-12-03 at 13:45 -0500, andros@netapp.com wrote: >> From: Andy Adamson <andros@netapp.com> >> >> This code works in conjunction with nfslogin and nfslogout programs >> which enforce the use of the keyring Kerberos credential cache of the >> form KEYRING:krb5cc_<UID> and adds a gss-ctx key to the krb5cc_<UID> keyring. >> >> When kdestroy is called on the keyring context the .destroy function of the >> new key is called which marks all gss_context's associated with the UID as >> out of date. >> >> Signed-off-by: Andy Adamson <andros@netapp.com> >> --- >> net/sunrpc/auth_gss/auth_gss.c | 85 ++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 85 insertions(+), 0 deletions(-) >> >> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c >> index 082e579..2d8fbf1 100644 >> --- a/net/sunrpc/auth_gss/auth_gss.c >> +++ b/net/sunrpc/auth_gss/auth_gss.c >> @@ -51,6 +51,12 @@ >> #include <linux/sunrpc/rpc_pipe_fs.h> >> #include <linux/sunrpc/gss_api.h> >> #include <asm/uaccess.h> >> +#include <linux/key.h> >> +#include <linux/keyctl.h> >> +#include <linux/key-type.h> >> +#include <keys/user-type.h> >> + >> +#include "../netns.h" >> >> static const struct rpc_authops authgss_ops; >> >> @@ -95,6 +101,83 @@ static void gss_free_ctx(struct gss_cl_ctx *); >> static const struct rpc_pipe_ops gss_upcall_ops_v0; >> static const struct rpc_pipe_ops gss_upcall_ops_v1; >> >> +/* >> + * Search all rpc_clnt auth's and invalidate any RPC_AUT_GSS Kerberos >> + * gss contexts belonging to uid. Triggered by kdestroy of keyring >> + * kerberos credentials. >> + */ >> +static void >> +gss_kdestroy_cred(uid_t uid) >> +{ >> + struct net *net = current->nsproxy->net_ns; >> + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); >> + struct rpc_clnt *clnt; >> + struct rpc_cred *cr; >> + struct auth_cred ac = { >> + .uid = uid, >> + }; >> + >> + dprintk("--> %s uid %d\n", __func__, uid); >> + spin_lock(&sn->rpc_client_lock); >> + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { >> + if ((clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5) || >> + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5I) || >> + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5P)) { >> + cr = rpcauth_lookup_credcache(clnt->cl_auth, &ac, 0); >> + if (IS_ERR(cr) || cr == NULL) >> + continue; >> + dprintk("%s invalidated cred %p from auth %p crcache\n", >> + __func__, cr, clnt->cl_auth); >> + smp_mb__before_clear_bit(); >> + clear_bit(RPCAUTH_CRED_UPTODATE, &cr->cr_flags); >> + smp_mb__after_clear_bit(); >> + put_rpccred(cr); /* balance get in lookup credcache */ >> + } >> + } >> + spin_unlock(&sn->rpc_client_lock); >> +} >> + >> +static void >> +gss_user_destroy(struct key *key) >> +{ >> + struct user_key_payload *upayload; >> + int uid = 0; >> + >> + upayload = rcu_dereference_key(key); >> + memcpy((void *)&uid, upayload->data, sizeof(int)); > > It seems to me that this code allows me to kill anyone's rpcsec_gss > sessions by creating a key with their uid, and then destroying it. Yes - just proof of concept code. There is a lot to consider. > > One solution is to replace user_instantiate() with something that sets > the payload to a value determined by the kernel itself. We'd definitely > want to include the uid, but perhaps also add a cookie that is unique to > this key (using the idr/ida stuff from include/linux/idr.h ?), and that > can be used to distinguish it from keys generated from other processes. > If we were to use the same key to label the auth_gss creds, then we > could have user_gss_destroy() kill _only_ the auth_gss creds that it > spawned. Yes, killing only the auth it spawned is indeed what we want. > > Ultimately, though, I think we might want to let the user set at least > _part_ of the payload to something that might be useful to gssd when it > goes looking for credentials. Since the nfslogin and gssd will be > shipped as part of the nfs-utils package, it would be nice to allow them > to use the gss-ctx key in order to communicate. Interesting information > might include the KRB5CCNAME. Thanks for the good suggestions. -->Andy > >> + gss_kdestroy_cred((uid_t)uid); >> + return user_destroy(key); >> +} >> + >> +static struct key_type key_type_gss_ctx = { >> + .name = "gss-ctx", >> + .instantiate = user_instantiate, >> + .match = user_match, >> + .revoke = user_revoke, >> + .destroy = gss_user_destroy, >> + .describe = user_describe, >> + .read = user_read, >> +}; >> + >> + >> +/* Register the gss-ctx key type for use by nfslogin and nfslogout */ >> +static int gss_register_ctx_keytype(void) >> +{ >> + int ret; >> + >> + ret = register_key_type(&key_type_gss_ctx); >> + >> + pr_notice("NFS: Registering the %s key type ret %d\n", >> + key_type_gss_ctx.name, ret); >> + >> + return ret; >> +} >> + >> +static void gss_unregister_ctx_keytype(void) >> +{ >> + unregister_key_type(&key_type_gss_ctx); >> +} >> + >> static inline struct gss_cl_ctx * >> gss_get_ctx(struct gss_cl_ctx *ctx) >> { >> @@ -1748,6 +1831,7 @@ static int __init init_rpcsec_gss(void) >> if (err) >> goto out_svc_exit; >> rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); >> + gss_register_ctx_keytype(); >> return 0; >> out_svc_exit: >> gss_svc_shutdown(); >> @@ -1762,6 +1846,7 @@ static void __exit exit_rpcsec_gss(void) >> unregister_pernet_subsys(&rpcsec_gss_net_ops); >> gss_svc_shutdown(); >> rpcauth_unregister(&authgss_ops); >> + gss_unregister_ctx_keytype(); >> rcu_barrier(); /* Wait for completion of call_rcu()'s */ >> } >> > > -- > Trond Myklebust > Linux NFS client maintainer > > NetApp > Trond.Myklebust@netapp.com > www.netapp.com -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
T24gTW9uLCAyMDEyLTEyLTAzIGF0IDIyOjM5ICswMDAwLCBBZGFtc29uLCBBbmR5IHdyb3RlOg0K PiBPbiBEZWMgMywgMjAxMiwgYXQgNDowNiBQTSwgIk15a2xlYnVzdCwgVHJvbmQiIDxUcm9uZC5N eWtsZWJ1c3RAbmV0YXBwLmNvbT4NCj4gIHdyb3RlOg0KDQo+ID4gSXQgc2VlbXMgdG8gbWUgdGhh dCB0aGlzIGNvZGUgYWxsb3dzIG1lIHRvIGtpbGwgYW55b25lJ3MgcnBjc2VjX2dzcw0KPiA+IHNl c3Npb25zIGJ5IGNyZWF0aW5nIGEga2V5IHdpdGggdGhlaXIgdWlkLCBhbmQgdGhlbiBkZXN0cm95 aW5nIGl0Lg0KPiANCj4gWWVzIC0ganVzdCBwcm9vZiBvZiBjb25jZXB0IGNvZGUuIFRoZXJlIGlz IGEgbG90IHRvIGNvbnNpZGVyLg0KPiANCj4gPiANCj4gPiBPbmUgc29sdXRpb24gaXMgdG8gcmVw bGFjZSB1c2VyX2luc3RhbnRpYXRlKCkgd2l0aCBzb21ldGhpbmcgdGhhdCBzZXRzDQo+ID4gdGhl IHBheWxvYWQgdG8gYSB2YWx1ZSBkZXRlcm1pbmVkIGJ5IHRoZSBrZXJuZWwgaXRzZWxmLiBXZSdk IGRlZmluaXRlbHkNCj4gPiB3YW50IHRvIGluY2x1ZGUgdGhlIHVpZCwgYnV0IHBlcmhhcHMgYWxz byBhZGQgYSBjb29raWUgdGhhdCBpcyB1bmlxdWUgdG8NCj4gPiB0aGlzIGtleSAodXNpbmcgdGhl IGlkci9pZGEgc3R1ZmYgZnJvbSBpbmNsdWRlL2xpbnV4L2lkci5oID8pLCBhbmQgdGhhdA0KPiA+ IGNhbiBiZSB1c2VkIHRvIGRpc3Rpbmd1aXNoIGl0IGZyb20ga2V5cyBnZW5lcmF0ZWQgZnJvbSBv dGhlciBwcm9jZXNzZXMuDQo+ID4gSWYgd2Ugd2VyZSB0byB1c2UgdGhlIHNhbWUga2V5IHRvIGxh YmVsIHRoZSBhdXRoX2dzcyBjcmVkcywgdGhlbiB3ZQ0KPiA+IGNvdWxkIGhhdmUgdXNlcl9nc3Nf ZGVzdHJveSgpIGtpbGwgX29ubHlfIHRoZSBhdXRoX2dzcyBjcmVkcyB0aGF0IGl0DQo+ID4gc3Bh d25lZC4NCj4gDQo+IFllcywga2lsbGluZyBvbmx5IHRoZSBhdXRoIGl0IHNwYXduZWQgaXMgaW5k ZWVkIHdoYXQgd2Ugd2FudC4NCj4gDQo+ID4gDQo+ID4gVWx0aW1hdGVseSwgdGhvdWdoLCBJIHRo aW5rIHdlIG1pZ2h0IHdhbnQgdG8gbGV0IHRoZSB1c2VyIHNldCBhdCBsZWFzdA0KPiA+IF9wYXJ0 XyBvZiB0aGUgcGF5bG9hZCB0byBzb21ldGhpbmcgdGhhdCBtaWdodCBiZSB1c2VmdWwgdG8gZ3Nz ZCB3aGVuIGl0DQo+ID4gZ29lcyBsb29raW5nIGZvciBjcmVkZW50aWFscy4gU2luY2UgdGhlIG5m c2xvZ2luIGFuZCBnc3NkIHdpbGwgYmUNCj4gPiBzaGlwcGVkIGFzIHBhcnQgb2YgdGhlIG5mcy11 dGlscyBwYWNrYWdlLCBpdCB3b3VsZCBiZSBuaWNlIHRvIGFsbG93IHRoZW0NCj4gPiB0byB1c2Ug dGhlIGdzcy1jdHgga2V5IGluIG9yZGVyIHRvIGNvbW11bmljYXRlLiBJbnRlcmVzdGluZyBpbmZv cm1hdGlvbg0KPiA+IG1pZ2h0IGluY2x1ZGUgdGhlIEtSQjVDQ05BTUUuDQo+IA0KPiBUaGFua3Mg Zm9yIHRoZSBnb29kIHN1Z2dlc3Rpb25zLg0KDQpTbywgSSd2ZSBnb3QgYSBxdWVzdGlvbjogQ2Fu IHdlIHJlcGxhY2Ugc29tZSBvZiB0aGUgc3R1ZmYgaW4gdGhlICJSRkMNCkF2b2lkIGV4cGlyZWQg Y3JlZGVudGlhbCBrZXlzIGZvciBidWZmZXJlZCB3cml0ZXMiIHBhdGNoIHNlcmllcyB3aXRoDQp0 aGlzPw0KDQpNeSB0aGlua2luZyBpcyB0aGF0IHNpbmNlIHRoZSB1c2VyX2dzc19kZXN0cm95KCkg aGFzIHRvIHN5bmMgYWxsIGZpbGVzDQphbmQgdGhlbiBpbnZhbGlkYXRlIHRoZSBycGNzZWNfZ3Nz IGNyZWRzLCB3ZSdyZSBwcmV0dHkgbXVjaCBkb2luZyB0aGUNCnNhbWUgdGhpbmcgYXMgaW4gdGhl IGFib3ZlIFJGQyBwYXRjaCBzZXJpZXMuIElmIG5mc2xvZ2luIHdlcmUgdG8gdGVsbA0KdGhlIGdz cy1jdHgga2V5IGhvdyBsb25nIHVudGlsIHRoZSBrZXJiZXJvcyB0Z3QgZXhwaXJlcywgY291bGRu J3Qgd2UNCmhhdmUgYSB3b3JrIHF1ZXVlIGpvYiB3YWtlIHVwIGp1c3QgYmVmb3JlIHRoZSB0Z3Qg aXMgYWJvdXQgdG8gZXhwaXJlLA0KYW5kIHNpbXBseSBjYWxsIHVzZXJfZ3NzX2Rlc3Ryb3kgYnkg cmV2b2tpbmcgdGhlIGdzcy1jdHgga2V5Pw0KSWYsIG9uIHRoZSBvdGhlciBoYW5kLCB0aGUgdXNl ciByZW5ld3MgdGhlIHRndCB1c2luZyBuZnNsb2dpbiwgdGhlbiB3ZQ0KY291bGQgdXBkYXRlIHRo ZSBnc3MtY3R4IGtleSwgYW5kIGRlZmVyIHRoZSB3b3JrIHF1ZXVlIGpvYiB1bnRpbCB0aGUgbmV3 DQpleHBpcnQgdGltZS4NCg0KLS0gDQpUcm9uZCBNeWtsZWJ1c3QNCkxpbnV4IE5GUyBjbGllbnQg bWFpbnRhaW5lcg0KDQpOZXRBcHANClRyb25kLk15a2xlYnVzdEBuZXRhcHAuY29tDQp3d3cubmV0 YXBwLmNvbQ0K -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Dec 4, 2012, at 9:56 AM, "Myklebust, Trond" <Trond.Myklebust@netapp.com> wrote: > On Mon, 2012-12-03 at 22:39 +0000, Adamson, Andy wrote: >> On Dec 3, 2012, at 4:06 PM, "Myklebust, Trond" <Trond.Myklebust@netapp.com> >> wrote: > >>> It seems to me that this code allows me to kill anyone's rpcsec_gss >>> sessions by creating a key with their uid, and then destroying it. >> >> Yes - just proof of concept code. There is a lot to consider. >> >>> >>> One solution is to replace user_instantiate() with something that sets >>> the payload to a value determined by the kernel itself. We'd definitely >>> want to include the uid, but perhaps also add a cookie that is unique to >>> this key (using the idr/ida stuff from include/linux/idr.h ?), and that >>> can be used to distinguish it from keys generated from other processes. >>> If we were to use the same key to label the auth_gss creds, then we >>> could have user_gss_destroy() kill _only_ the auth_gss creds that it >>> spawned. >> >> Yes, killing only the auth it spawned is indeed what we want. >> >>> >>> Ultimately, though, I think we might want to let the user set at least >>> _part_ of the payload to something that might be useful to gssd when it >>> goes looking for credentials. Since the nfslogin and gssd will be >>> shipped as part of the nfs-utils package, it would be nice to allow them >>> to use the gss-ctx key in order to communicate. Interesting information >>> might include the KRB5CCNAME. >> >> Thanks for the good suggestions. > > So, I've got a question: Can we replace some of the stuff in the "RFC > Avoid expired credential keys for buffered writes" patch series with > this? > > My thinking is that since the user_gss_destroy() has to sync all files > and then invalidate the rpcsec_gss creds, we're pretty much doing the > same thing as in the above RFC patch series. I was thinking the other way 'round. When gss_user_destroy gets called due to nfslogout (kdestroy) it triggers the RPC avoid expiration on buffered writes code with one difference: It does not allow _any_ new writes or _any_ other RPCs to use a GSS context with a valid lifetime but to be destroyed due to logout. So instead of gss_user_destroy marking a GSS context as out of date, it will be marked as to be ONLY used for flushing writes that were buffered before the nfslogout (kdestroy) and associated commits. > If nfslogin were to tell > the gss-ctx key how long until the kerberos tgt expires, We already have an expired time for the TGT in the GSS context downcall. Why do we need nfslogin to repeat the information? If you want to have a work queue job wake up based on the TGT lifetime, the info is already in the GSS context. > couldn't we > have a work queue job wake up just before the tgt is about to expire, > and simply call user_gss_destroy by revoking the gss-ctx key? I think using the TGT lifetime that existed to at the creation of the GSS context trigger the RPC avoid cred expiration code works really well. I don't see a need for a workqueue thread. > If, on the other hand, the user renews the tgt using nfslogin, Yes - this is in plan. nfslogin (e.g. TGT renewal) will update an existing gss-ctx key which in turn will trigger an upcall on associated GSS contexts to have them renewed. I didn't want to bother with this until the idea of nfslogin/nfslogout had been flown :) > then we > could update the gss-ctx key, and defer the work queue job until the new > expirt time. With nfslogin updating the GSS context, the same will happen with the current RPC avoid expired cred code. -->Andy > > -- > Trond Myklebust > Linux NFS client maintainer > > NetApp > Trond.Myklebust@netapp.com > www.netapp.com -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
T24gVHVlLCAyMDEyLTEyLTA0IGF0IDE1OjU4ICswMDAwLCBBZGFtc29uLCBBbmR5IHdyb3RlOg0K PiBPbiBEZWMgNCwgMjAxMiwgYXQgOTo1NiBBTSwgIk15a2xlYnVzdCwgVHJvbmQiIDxUcm9uZC5N eWtsZWJ1c3RAbmV0YXBwLmNvbT4NCj4gIHdyb3RlOg0KPiANCj4gPiBPbiBNb24sIDIwMTItMTIt MDMgYXQgMjI6MzkgKzAwMDAsIEFkYW1zb24sIEFuZHkgd3JvdGU6DQo+ID4+IE9uIERlYyAzLCAy MDEyLCBhdCA0OjA2IFBNLCAiTXlrbGVidXN0LCBUcm9uZCIgPFRyb25kLk15a2xlYnVzdEBuZXRh cHAuY29tPg0KPiA+PiB3cm90ZToNCj4gPiANCj4gPj4+IEl0IHNlZW1zIHRvIG1lIHRoYXQgdGhp cyBjb2RlIGFsbG93cyBtZSB0byBraWxsIGFueW9uZSdzIHJwY3NlY19nc3MNCj4gPj4+IHNlc3Np b25zIGJ5IGNyZWF0aW5nIGEga2V5IHdpdGggdGhlaXIgdWlkLCBhbmQgdGhlbiBkZXN0cm95aW5n IGl0Lg0KPiA+PiANCj4gPj4gWWVzIC0ganVzdCBwcm9vZiBvZiBjb25jZXB0IGNvZGUuIFRoZXJl IGlzIGEgbG90IHRvIGNvbnNpZGVyLg0KPiA+PiANCj4gPj4+IA0KPiA+Pj4gT25lIHNvbHV0aW9u IGlzIHRvIHJlcGxhY2UgdXNlcl9pbnN0YW50aWF0ZSgpIHdpdGggc29tZXRoaW5nIHRoYXQgc2V0 cw0KPiA+Pj4gdGhlIHBheWxvYWQgdG8gYSB2YWx1ZSBkZXRlcm1pbmVkIGJ5IHRoZSBrZXJuZWwg aXRzZWxmLiBXZSdkIGRlZmluaXRlbHkNCj4gPj4+IHdhbnQgdG8gaW5jbHVkZSB0aGUgdWlkLCBi dXQgcGVyaGFwcyBhbHNvIGFkZCBhIGNvb2tpZSB0aGF0IGlzIHVuaXF1ZSB0bw0KPiA+Pj4gdGhp cyBrZXkgKHVzaW5nIHRoZSBpZHIvaWRhIHN0dWZmIGZyb20gaW5jbHVkZS9saW51eC9pZHIuaCA/ KSwgYW5kIHRoYXQNCj4gPj4+IGNhbiBiZSB1c2VkIHRvIGRpc3Rpbmd1aXNoIGl0IGZyb20ga2V5 cyBnZW5lcmF0ZWQgZnJvbSBvdGhlciBwcm9jZXNzZXMuDQo+ID4+PiBJZiB3ZSB3ZXJlIHRvIHVz ZSB0aGUgc2FtZSBrZXkgdG8gbGFiZWwgdGhlIGF1dGhfZ3NzIGNyZWRzLCB0aGVuIHdlDQo+ID4+ PiBjb3VsZCBoYXZlIHVzZXJfZ3NzX2Rlc3Ryb3koKSBraWxsIF9vbmx5XyB0aGUgYXV0aF9nc3Mg Y3JlZHMgdGhhdCBpdA0KPiA+Pj4gc3Bhd25lZC4NCj4gPj4gDQo+ID4+IFllcywga2lsbGluZyBv bmx5IHRoZSBhdXRoIGl0IHNwYXduZWQgaXMgaW5kZWVkIHdoYXQgd2Ugd2FudC4NCj4gPj4gDQo+ ID4+PiANCj4gPj4+IFVsdGltYXRlbHksIHRob3VnaCwgSSB0aGluayB3ZSBtaWdodCB3YW50IHRv IGxldCB0aGUgdXNlciBzZXQgYXQgbGVhc3QNCj4gPj4+IF9wYXJ0XyBvZiB0aGUgcGF5bG9hZCB0 byBzb21ldGhpbmcgdGhhdCBtaWdodCBiZSB1c2VmdWwgdG8gZ3NzZCB3aGVuIGl0DQo+ID4+PiBn b2VzIGxvb2tpbmcgZm9yIGNyZWRlbnRpYWxzLiBTaW5jZSB0aGUgbmZzbG9naW4gYW5kIGdzc2Qg d2lsbCBiZQ0KPiA+Pj4gc2hpcHBlZCBhcyBwYXJ0IG9mIHRoZSBuZnMtdXRpbHMgcGFja2FnZSwg aXQgd291bGQgYmUgbmljZSB0byBhbGxvdyB0aGVtDQo+ID4+PiB0byB1c2UgdGhlIGdzcy1jdHgg a2V5IGluIG9yZGVyIHRvIGNvbW11bmljYXRlLiBJbnRlcmVzdGluZyBpbmZvcm1hdGlvbg0KPiA+ Pj4gbWlnaHQgaW5jbHVkZSB0aGUgS1JCNUNDTkFNRS4NCj4gPj4gDQo+ID4+IFRoYW5rcyBmb3Ig dGhlIGdvb2Qgc3VnZ2VzdGlvbnMuDQo+ID4gDQo+ID4gU28sIEkndmUgZ290IGEgcXVlc3Rpb246 IENhbiB3ZSByZXBsYWNlIHNvbWUgb2YgdGhlIHN0dWZmIGluIHRoZSAiUkZDDQo+ID4gQXZvaWQg ZXhwaXJlZCBjcmVkZW50aWFsIGtleXMgZm9yIGJ1ZmZlcmVkIHdyaXRlcyIgcGF0Y2ggc2VyaWVz IHdpdGgNCj4gPiB0aGlzPw0KPiA+IA0KPiA+IE15IHRoaW5raW5nIGlzIHRoYXQgc2luY2UgdGhl IHVzZXJfZ3NzX2Rlc3Ryb3koKSBoYXMgdG8gc3luYyBhbGwgZmlsZXMNCj4gPiBhbmQgdGhlbiBp bnZhbGlkYXRlIHRoZSBycGNzZWNfZ3NzIGNyZWRzLCB3ZSdyZSBwcmV0dHkgbXVjaCBkb2luZyB0 aGUNCj4gPiBzYW1lIHRoaW5nIGFzIGluIHRoZSBhYm92ZSBSRkMgcGF0Y2ggc2VyaWVzLg0KPiAN Cj4gSSB3YXMgdGhpbmtpbmcgdGhlIG90aGVyIHdheSAncm91bmQuIFdoZW4gZ3NzX3VzZXJfZGVz dHJveSBnZXRzIGNhbGxlZCBkdWUgdG8gbmZzbG9nb3V0IChrZGVzdHJveSkgaXQgdHJpZ2dlcnMg dGhlIFJQQyBhdm9pZCBleHBpcmF0aW9uIG9uIGJ1ZmZlcmVkIHdyaXRlcyBjb2RlIHdpdGggb25l IGRpZmZlcmVuY2U6IEl0IGRvZXMgbm90IGFsbG93IF9hbnlfIG5ldyB3cml0ZXMgb3IgX2FueV8g b3RoZXIgUlBDcyB0byB1c2UgYSBHU1MgY29udGV4dCAgd2l0aCBhIHZhbGlkIGxpZmV0aW1lIGJ1 dCB0byBiZSBkZXN0cm95ZWQgZHVlIHRvIGxvZ291dC4gDQo+IA0KPiBTbyBpbnN0ZWFkIG9mIGdz c191c2VyX2Rlc3Ryb3kgbWFya2luZyBhIEdTUyBjb250ZXh0IGFzIG91dCBvZiBkYXRlLCBpdCB3 aWxsIGJlIG1hcmtlZCBhcyB0byBiZSBPTkxZIHVzZWQgZm9yIGZsdXNoaW5nIHdyaXRlcyB0aGF0 IHdlcmUgYnVmZmVyZWQgYmVmb3JlIHRoZSBuZnNsb2dvdXQgKGtkZXN0cm95KSBhbmQgYXNzb2Np YXRlZCBjb21taXRzLg0KPiANCj4gPiBJZiBuZnNsb2dpbiB3ZXJlIHRvIHRlbGwNCj4gPiB0aGUg Z3NzLWN0eCBrZXkgaG93IGxvbmcgdW50aWwgdGhlIGtlcmJlcm9zIHRndCBleHBpcmVzLA0KPiAN Cj4gV2UgYWxyZWFkeSBoYXZlIGFuIGV4cGlyZWQgdGltZSBmb3IgdGhlIFRHVCBpbiB0aGUgR1NT IGNvbnRleHQgZG93bmNhbGwuIFdoeSBkbyB3ZSBuZWVkIG5mc2xvZ2luIHRvIHJlcGVhdCB0aGUg aW5mb3JtYXRpb24/IElmIHlvdSB3YW50IHRvIGhhdmUgYSB3b3JrIHF1ZXVlIGpvYiB3YWtlIHVw IGJhc2VkIG9uIHRoZSBUR1QgbGlmZXRpbWUsIHRoZSBpbmZvIGlzIGFscmVhZHkgaW4gdGhlIEdT UyBjb250ZXh0Lg0KDQpGb3IgZGVhbGluZyB3aXRoIHRndCByZW5ld2Fscy4gVGhlIEdTUyBjb250 ZXh0IG9ubHkgY29udGFpbnMgdGhlIGV4cGlyZQ0KdGltZSB0aGF0IHdhcyBrbm93biB3aGVuIHRo ZSBjb250ZXh0IHdhcyBjcmVhdGVkLiBJdCBkb2Vzbid0IGtub3csIGFuZA0KY2FuJ3QgdHJhY2sg d2hldGhlciBvciBub3QgdGhlIHVzZXIgcmVuZXdlZCB0aGUgdGd0Lg0KDQo+ID4gY291bGRuJ3Qg d2UNCj4gPiBoYXZlIGEgd29yayBxdWV1ZSBqb2Igd2FrZSB1cCBqdXN0IGJlZm9yZSB0aGUgdGd0 IGlzIGFib3V0IHRvIGV4cGlyZSwNCj4gPiBhbmQgc2ltcGx5IGNhbGwgdXNlcl9nc3NfZGVzdHJv eSBieSByZXZva2luZyB0aGUgZ3NzLWN0eCBrZXk/DQo+IA0KPiBJIHRoaW5rIHVzaW5nICB0aGUg VEdUIGxpZmV0aW1lIHRoYXQgZXhpc3RlZCB0byBhdCB0aGUgY3JlYXRpb24gb2YgdGhlIEdTUyBj b250ZXh0IHRyaWdnZXIgdGhlIFJQQyBhdm9pZCBjcmVkIGV4cGlyYXRpb24gY29kZSB3b3JrcyBy ZWFsbHkgd2VsbC4gSSBkb24ndCBzZWUgYSBuZWVkIGZvciBhIHdvcmtxdWV1ZSB0aHJlYWQuDQo+ IA0KPiA+IElmLCBvbiB0aGUgb3RoZXIgaGFuZCwgdGhlIHVzZXIgcmVuZXdzIHRoZSB0Z3QgdXNp bmcgbmZzbG9naW4sDQo+IA0KPiBZZXMgLSB0aGlzIGlzIGluIHBsYW4uIG5mc2xvZ2luIChlLmcu IFRHVCByZW5ld2FsKSB3aWxsIHVwZGF0ZSBhbiBleGlzdGluZyBnc3MtY3R4IGtleSB3aGljaCBp biB0dXJuIHdpbGwgdHJpZ2dlciBhbiB1cGNhbGwgb24gYXNzb2NpYXRlZCBHU1MgY29udGV4dHMg dG8gaGF2ZSB0aGVtIHJlbmV3ZWQuICBJIGRpZG4ndCB3YW50IHRvIGJvdGhlciB3aXRoIHRoaXMg dW50aWwgdGhlIGlkZWEgb2YgbmZzbG9naW4vbmZzbG9nb3V0IGhhZCBiZWVuIGZsb3duIDopDQo+ IA0KPiA+IHRoZW4gd2UNCj4gPiBjb3VsZCB1cGRhdGUgdGhlIGdzcy1jdHgga2V5LCBhbmQgZGVm ZXIgdGhlIHdvcmsgcXVldWUgam9iIHVudGlsIHRoZSBuZXcNCj4gPiBleHBpcnQgdGltZS4NCj4g DQo+IFdpdGggbmZzbG9naW4gdXBkYXRpbmcgdGhlIEdTUyBjb250ZXh0LCB0aGUgc2FtZSB3aWxs IGhhcHBlbiB3aXRoIHRoZSBjdXJyZW50IFJQQyBhdm9pZCBleHBpcmVkIGNyZWQgY29kZS4NCj4g DQo+IC0tPkFuZHkNCj4gDQo+ID4gDQo+ID4gLS0gDQo+ID4gVHJvbmQgTXlrbGVidXN0DQo+ID4g TGludXggTkZTIGNsaWVudCBtYWludGFpbmVyDQo+ID4gDQo+ID4gTmV0QXBwDQo+ID4gVHJvbmQu TXlrbGVidXN0QG5ldGFwcC5jb20NCj4gPiB3d3cubmV0YXBwLmNvbQ0KPiANCg0KLS0gDQpUcm9u ZCBNeWtsZWJ1c3QNCkxpbnV4IE5GUyBjbGllbnQgbWFpbnRhaW5lcg0KDQpOZXRBcHANClRyb25k Lk15a2xlYnVzdEBuZXRhcHAuY29tDQp3d3cubmV0YXBwLmNvbQ0K -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 082e579..2d8fbf1 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -51,6 +51,12 @@ #include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/gss_api.h> #include <asm/uaccess.h> +#include <linux/key.h> +#include <linux/keyctl.h> +#include <linux/key-type.h> +#include <keys/user-type.h> + +#include "../netns.h" static const struct rpc_authops authgss_ops; @@ -95,6 +101,83 @@ static void gss_free_ctx(struct gss_cl_ctx *); static const struct rpc_pipe_ops gss_upcall_ops_v0; static const struct rpc_pipe_ops gss_upcall_ops_v1; +/* + * Search all rpc_clnt auth's and invalidate any RPC_AUT_GSS Kerberos + * gss contexts belonging to uid. Triggered by kdestroy of keyring + * kerberos credentials. + */ +static void +gss_kdestroy_cred(uid_t uid) +{ + struct net *net = current->nsproxy->net_ns; + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + struct rpc_clnt *clnt; + struct rpc_cred *cr; + struct auth_cred ac = { + .uid = uid, + }; + + dprintk("--> %s uid %d\n", __func__, uid); + spin_lock(&sn->rpc_client_lock); + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { + if ((clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5) || + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5I) || + (clnt->cl_auth->au_flavor == RPC_AUTH_GSS_KRB5P)) { + cr = rpcauth_lookup_credcache(clnt->cl_auth, &ac, 0); + if (IS_ERR(cr) || cr == NULL) + continue; + dprintk("%s invalidated cred %p from auth %p crcache\n", + __func__, cr, clnt->cl_auth); + smp_mb__before_clear_bit(); + clear_bit(RPCAUTH_CRED_UPTODATE, &cr->cr_flags); + smp_mb__after_clear_bit(); + put_rpccred(cr); /* balance get in lookup credcache */ + } + } + spin_unlock(&sn->rpc_client_lock); +} + +static void +gss_user_destroy(struct key *key) +{ + struct user_key_payload *upayload; + int uid = 0; + + upayload = rcu_dereference_key(key); + memcpy((void *)&uid, upayload->data, sizeof(int)); + gss_kdestroy_cred((uid_t)uid); + return user_destroy(key); +} + +static struct key_type key_type_gss_ctx = { + .name = "gss-ctx", + .instantiate = user_instantiate, + .match = user_match, + .revoke = user_revoke, + .destroy = gss_user_destroy, + .describe = user_describe, + .read = user_read, +}; + + +/* Register the gss-ctx key type for use by nfslogin and nfslogout */ +static int gss_register_ctx_keytype(void) +{ + int ret; + + ret = register_key_type(&key_type_gss_ctx); + + pr_notice("NFS: Registering the %s key type ret %d\n", + key_type_gss_ctx.name, ret); + + return ret; +} + +static void gss_unregister_ctx_keytype(void) +{ + unregister_key_type(&key_type_gss_ctx); +} + static inline struct gss_cl_ctx * gss_get_ctx(struct gss_cl_ctx *ctx) { @@ -1748,6 +1831,7 @@ static int __init init_rpcsec_gss(void) if (err) goto out_svc_exit; rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); + gss_register_ctx_keytype(); return 0; out_svc_exit: gss_svc_shutdown(); @@ -1762,6 +1846,7 @@ static void __exit exit_rpcsec_gss(void) unregister_pernet_subsys(&rpcsec_gss_net_ops); gss_svc_shutdown(); rpcauth_unregister(&authgss_ops); + gss_unregister_ctx_keytype(); rcu_barrier(); /* Wait for completion of call_rcu()'s */ }