diff mbox

[1/1] SUNRPC: new keyring key_type for gss context destruction at kdestroy

Message ID 1354560315-2393-2-git-send-email-andros@netapp.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andy Adamson Dec. 3, 2012, 6:45 p.m. UTC
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(-)

Comments

Trond Myklebust Dec. 3, 2012, 9:06 p.m. UTC | #1
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
Adamson, Andy Dec. 3, 2012, 10:39 p.m. UTC | #2
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
Trond Myklebust Dec. 4, 2012, 2:56 p.m. UTC | #3
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
Adamson, Andy Dec. 4, 2012, 3:58 p.m. UTC | #4
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
Trond Myklebust Dec. 4, 2012, 4:04 p.m. UTC | #5
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 mbox

Patch

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 */
 }