@@ -68,6 +68,7 @@ struct rpc_cred {
#define RPCAUTH_CRED_UPTODATE 1
#define RPCAUTH_CRED_HASHED 2
#define RPCAUTH_CRED_NEGATIVE 3
+#define RPCAUTH_CRED_KEY_DESTROYED 4
#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
@@ -115,12 +115,52 @@ 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;
+/**
+ * The UID Kerberos credential has been destroyed. Search all gss_auth
+ * credential caches and mark all UID gss_creds RPCAUTH_CRED_KEY_DESTROYED.
+ */
+static void
+gss_mark_cred_destroy(uid_t uid, key_serial_t serial)
+{
+ struct gss_auth *ga;
+ struct rpc_cred *cr;
+ struct gss_cred *gc;
+ struct auth_cred ac = {
+ .uid = uid,
+ };
+ int i;
+
+ spin_lock(&gss_auth_hash_lock);
+ hash_for_each(gss_auth_hash_table, i, ga, hash) {
+ /* check all supported pseudoflavors */
+ if (ga->rpc_auth.au_flavor > RPC_AUTH_MAXFLAVOR) {
+ cr = rpcauth_lookup_credcache(&ga->rpc_auth, &ac, 0);
+ if (IS_ERR(cr) || cr == NULL)
+ continue;
+ gc = container_of(cr, struct gss_cred, gc_base);
+ if (gc->gc_serial == serial) {
+ set_bit(RPCAUTH_CRED_KEY_DESTROYED,
+ &cr->cr_flags);
+ }
+ put_rpccred(cr); /* balance get in lookup credcache */
+ }
+ }
+ spin_unlock(&gss_auth_hash_lock);
+}
+
+static void
+gss_user_destroy(struct key *key)
+{
+ gss_mark_cred_destroy(key->uid, key->serial);
+ 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 = user_destroy,
+ .destroy = gss_user_destroy,
.describe = user_describe,
.read = user_read,
};
@@ -1471,6 +1511,9 @@ check_expire:
if (ret == 0)
return ret;
+ if (test_bit(RPCAUTH_CRED_KEY_DESTROYED, &rc->cr_flags))
+ return 0;
+
/* Notify acred users of GSS context expiration timeout */
if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags) &&
(gss_key_timeout(rc) != 0)) {