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

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

 



On Dec 3, 2012, at 4:06 PM, "Myklebust, Trond" <Trond.Myklebust@xxxxxxxxxx>
 wrote:

> On Mon, 2012-12-03 at 13:45 -0500, andros@xxxxxxxxxx wrote:
>> From: Andy Adamson <andros@xxxxxxxxxx>
>> 
>> 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@xxxxxxxxxx>
>> ---
>> 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@xxxxxxxxxx
> www.netapp.com

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux