Skip to content

Commit

Permalink
SUNRPC: Don't spam gssd with upcall requests when the kerberos key ex…
Browse files Browse the repository at this point in the history
…pired

Now that the rpc.gssd daemon can explicitly tell us that the key expired,
we should cache that information to avoid spamming gssd.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed May 14, 2010
1 parent 9bb0b81 commit 126e216
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
1 change: 1 addition & 0 deletions include/linux/sunrpc/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct rpc_cred {
#define RPCAUTH_CRED_NEW 0
#define RPCAUTH_CRED_UPTODATE 1
#define RPCAUTH_CRED_HASHED 2
#define RPCAUTH_CRED_NEGATIVE 3

#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0

Expand Down
1 change: 1 addition & 0 deletions include/linux/sunrpc/auth_gss.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct gss_cred {
enum rpc_gss_svc gc_service;
struct gss_cl_ctx *gc_ctx;
struct gss_upcall_msg *gc_upcall;
unsigned long gc_upcall_timestamp;
unsigned char gc_machine_cred : 1;
};

Expand Down
65 changes: 53 additions & 12 deletions net/sunrpc/auth_gss/auth_gss.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops;
static const struct rpc_credops gss_credops;
static const struct rpc_credops gss_nullops;

#define GSS_RETRY_EXPIRED 5
static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;

#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
Expand Down Expand Up @@ -349,6 +352,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
spin_unlock(&inode->i_lock);
}

static void
gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg)
{
switch (gss_msg->msg.errno) {
case 0:
if (gss_msg->ctx == NULL)
break;
clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx);
break;
case -EKEYEXPIRED:
set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
}
gss_cred->gc_upcall_timestamp = jiffies;
gss_cred->gc_upcall = NULL;
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
}

static void
gss_upcall_callback(struct rpc_task *task)
{
Expand All @@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task)
struct inode *inode = &gss_msg->inode->vfs_inode;

spin_lock(&inode->i_lock);
if (gss_msg->ctx)
gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
else
task->tk_status = gss_msg->msg.errno;
gss_cred->gc_upcall = NULL;
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
gss_handle_downcall_result(gss_cred, gss_msg);
spin_unlock(&inode->i_lock);
task->tk_status = gss_msg->msg.errno;
gss_release_msg(gss_msg);
}

Expand Down Expand Up @@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task)
spin_lock(&inode->i_lock);
if (gss_cred->gc_upcall != NULL)
rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
else if (gss_msg->ctx != NULL) {
gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
gss_cred->gc_upcall = NULL;
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
} else if (gss_msg->msg.errno >= 0) {
else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
task->tk_timeout = 0;
gss_cred->gc_upcall = gss_msg;
/* gss_upcall_callback will release the reference to gss_upcall_msg */
atomic_inc(&gss_msg->count);
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
} else
} else {
gss_handle_downcall_result(gss_cred, gss_msg);
err = gss_msg->msg.errno;
}
spin_unlock(&inode->i_lock);
gss_release_msg(gss_msg);
out:
Expand Down Expand Up @@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
return 0;
}

static int gss_cred_is_negative_entry(struct rpc_cred *cred)
{
if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) {
unsigned long now = jiffies;
unsigned long begin, expire;
struct gss_cred *gss_cred;

gss_cred = container_of(cred, struct gss_cred, gc_base);
begin = gss_cred->gc_upcall_timestamp;
expire = begin + gss_expired_cred_retry_delay * HZ;

if (time_in_range_open(now, begin, expire))
return 1;
}
return 0;
}

/*
* Refresh credentials. XXX - finish
*/
Expand All @@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task)
struct rpc_cred *cred = task->tk_msg.rpc_cred;
int ret = 0;

if (gss_cred_is_negative_entry(cred))
return -EKEYEXPIRED;

if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
!test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
ret = gss_renew_cred(task);
Expand Down Expand Up @@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void)
}

MODULE_LICENSE("GPL");
module_param_named(expired_cred_retry_delay,
gss_expired_cred_retry_delay,
uint, 0644);
MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until "
"the RPC engine retries an expired credential");

module_init(init_rpcsec_gss)
module_exit(exit_rpcsec_gss)

0 comments on commit 126e216

Please sign in to comment.