Skip to content

Commit 126e216

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
SUNRPC: Don't spam gssd with upcall requests when the kerberos key expired
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 <[email protected]>
1 parent 9bb0b81 commit 126e216

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

include/linux/sunrpc/auth.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct rpc_cred {
5454
#define RPCAUTH_CRED_NEW 0
5555
#define RPCAUTH_CRED_UPTODATE 1
5656
#define RPCAUTH_CRED_HASHED 2
57+
#define RPCAUTH_CRED_NEGATIVE 3
5758

5859
#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
5960

include/linux/sunrpc/auth_gss.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct gss_cred {
8282
enum rpc_gss_svc gc_service;
8383
struct gss_cl_ctx *gc_ctx;
8484
struct gss_upcall_msg *gc_upcall;
85+
unsigned long gc_upcall_timestamp;
8586
unsigned char gc_machine_cred : 1;
8687
};
8788

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops;
5757
static const struct rpc_credops gss_credops;
5858
static const struct rpc_credops gss_nullops;
5959

60+
#define GSS_RETRY_EXPIRED 5
61+
static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
62+
6063
#ifdef RPC_DEBUG
6164
# define RPCDBG_FACILITY RPCDBG_AUTH
6265
#endif
@@ -349,6 +352,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
349352
spin_unlock(&inode->i_lock);
350353
}
351354

355+
static void
356+
gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg)
357+
{
358+
switch (gss_msg->msg.errno) {
359+
case 0:
360+
if (gss_msg->ctx == NULL)
361+
break;
362+
clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
363+
gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx);
364+
break;
365+
case -EKEYEXPIRED:
366+
set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
367+
}
368+
gss_cred->gc_upcall_timestamp = jiffies;
369+
gss_cred->gc_upcall = NULL;
370+
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
371+
}
372+
352373
static void
353374
gss_upcall_callback(struct rpc_task *task)
354375
{
@@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task)
358379
struct inode *inode = &gss_msg->inode->vfs_inode;
359380

360381
spin_lock(&inode->i_lock);
361-
if (gss_msg->ctx)
362-
gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
363-
else
364-
task->tk_status = gss_msg->msg.errno;
365-
gss_cred->gc_upcall = NULL;
366-
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
382+
gss_handle_downcall_result(gss_cred, gss_msg);
367383
spin_unlock(&inode->i_lock);
384+
task->tk_status = gss_msg->msg.errno;
368385
gss_release_msg(gss_msg);
369386
}
370387

@@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task)
513530
spin_lock(&inode->i_lock);
514531
if (gss_cred->gc_upcall != NULL)
515532
rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
516-
else if (gss_msg->ctx != NULL) {
517-
gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
518-
gss_cred->gc_upcall = NULL;
519-
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
520-
} else if (gss_msg->msg.errno >= 0) {
533+
else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
521534
task->tk_timeout = 0;
522535
gss_cred->gc_upcall = gss_msg;
523536
/* gss_upcall_callback will release the reference to gss_upcall_msg */
524537
atomic_inc(&gss_msg->count);
525538
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
526-
} else
539+
} else {
540+
gss_handle_downcall_result(gss_cred, gss_msg);
527541
err = gss_msg->msg.errno;
542+
}
528543
spin_unlock(&inode->i_lock);
529544
gss_release_msg(gss_msg);
530545
out:
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
11231138
return 0;
11241139
}
11251140

1141+
static int gss_cred_is_negative_entry(struct rpc_cred *cred)
1142+
{
1143+
if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) {
1144+
unsigned long now = jiffies;
1145+
unsigned long begin, expire;
1146+
struct gss_cred *gss_cred;
1147+
1148+
gss_cred = container_of(cred, struct gss_cred, gc_base);
1149+
begin = gss_cred->gc_upcall_timestamp;
1150+
expire = begin + gss_expired_cred_retry_delay * HZ;
1151+
1152+
if (time_in_range_open(now, begin, expire))
1153+
return 1;
1154+
}
1155+
return 0;
1156+
}
1157+
11261158
/*
11271159
* Refresh credentials. XXX - finish
11281160
*/
@@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task)
11321164
struct rpc_cred *cred = task->tk_msg.rpc_cred;
11331165
int ret = 0;
11341166

1167+
if (gss_cred_is_negative_entry(cred))
1168+
return -EKEYEXPIRED;
1169+
11351170
if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
11361171
!test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
11371172
ret = gss_renew_cred(task);
@@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void)
15851620
}
15861621

15871622
MODULE_LICENSE("GPL");
1623+
module_param_named(expired_cred_retry_delay,
1624+
gss_expired_cred_retry_delay,
1625+
uint, 0644);
1626+
MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until "
1627+
"the RPC engine retries an expired credential");
1628+
15881629
module_init(init_rpcsec_gss)
15891630
module_exit(exit_rpcsec_gss)

0 commit comments

Comments
 (0)