Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc432dd9 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Enforce atomic updates of rpc_cred->cr_flags



Convert to the use of atomic bitops...

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 696e38df
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -36,19 +36,19 @@ struct rpc_cred {
	struct hlist_node	cr_hash;	/* hash chain */
	struct rpc_auth *	cr_auth;
	const struct rpc_credops *cr_ops;
	unsigned long		cr_expire;	/* when to gc */
	atomic_t		cr_count;	/* ref count */
	unsigned short		cr_flags;	/* various flags */
#ifdef RPC_DEBUG
	unsigned long		cr_magic;	/* 0x0f4aa4f0 */
#endif
	unsigned long		cr_expire;	/* when to gc */
	unsigned long		cr_flags;	/* various flags */
	atomic_t		cr_count;	/* ref count */

	uid_t			cr_uid;

	/* per-flavor data */
};
#define RPCAUTH_CRED_NEW	0x0001
#define RPCAUTH_CRED_UPTODATE	0x0002
#define RPCAUTH_CRED_NEW	0
#define RPCAUTH_CRED_UPTODATE	1

#define RPCAUTH_CRED_MAGIC	0x0f4aa4f0

+12 −10
Original line number Diff line number Diff line
@@ -190,8 +190,8 @@ rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist
	if (atomic_read(&cred->cr_count) != 1)
	       return;
	if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
	if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) {
		__hlist_del(&cred->cr_hash);
		hlist_add_head(&cred->cr_hash, free);
	}
@@ -267,7 +267,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
		if (!IS_ERR(new))
			goto retry;
		cred = new;
	} else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
	} else if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
			&& cred->cr_ops->cr_init != NULL
			&& !(flags & RPCAUTH_LOOKUP_NEW)) {
		int res = cred->cr_ops->cr_init(auth, cred);
@@ -440,17 +440,19 @@ rpcauth_refreshcred(struct rpc_task *task)
void
rpcauth_invalcred(struct rpc_task *task)
{
	struct rpc_cred *cred = task->tk_msg.rpc_cred;

	dprintk("RPC: %5u invalidating %s cred %p\n",
		task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
	spin_lock(&rpc_credcache_lock);
	if (task->tk_msg.rpc_cred)
		task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
	spin_unlock(&rpc_credcache_lock);
		task->tk_pid, task->tk_auth->au_ops->au_name, cred);
	if (cred)
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
}

int
rpcauth_uptodatecred(struct rpc_task *task)
{
	return !(task->tk_msg.rpc_cred) ||
		(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
	struct rpc_cred *cred = task->tk_msg.rpc_cred;

	return cred == NULL ||
		test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
}
+11 −11
Original line number Diff line number Diff line
@@ -114,8 +114,8 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
	write_lock(&gss_ctx_lock);
	old = gss_cred->gc_ctx;
	gss_cred->gc_ctx = ctx;
	cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
	cred->cr_flags &= ~RPCAUTH_CRED_NEW;
	set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
	write_unlock(&gss_ctx_lock);
	if (old)
		gss_put_ctx(old);
@@ -128,7 +128,7 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
	int res = 0;

	read_lock(&gss_ctx_lock);
	if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
	if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
		res = 1;
	read_unlock(&gss_ctx_lock);
	return res;
@@ -732,7 +732,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
	 * Note: in order to force a call to call_refresh(), we deliberately
	 * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
	 */
	cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
	cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
	cred->gc_service = gss_auth->service;
	return &cred->gc_base;

@@ -764,7 +764,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
	 * we don't really care if the credential has expired or not,
	 * since the caller should be prepared to reinitialise it.
	 */
	if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
	if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
		goto out;
	/* Don't match with creds that have expired. */
	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
@@ -820,7 +820,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
	mic.data = (u8 *)(p + 1);
	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
	if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	} else if (maj_stat != 0) {
		printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
		goto out_put_ctx;
@@ -873,7 +873,7 @@ gss_validate(struct rpc_task *task, __be32 *p)

	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	if (maj_stat)
		goto out_bad;
	/* We leave it to unwrap to calculate au_rslack. For now we just
@@ -927,7 +927,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
	status = -EIO; /* XXX? */
	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	else if (maj_stat)
		return status;
	q = xdr_encode_opaque(p, NULL, mic.len);
@@ -1026,7 +1026,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
	 * done anyway, so it's safe to put the request on the wire: */
	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	else if (maj_stat)
		return status;

@@ -1113,7 +1113,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,

	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	if (maj_stat != GSS_S_COMPLETE)
		return status;
	return 0;
@@ -1138,7 +1138,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,

	maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
		clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
	if (maj_stat != GSS_S_COMPLETE)
		return status;
	if (ntohl(*(*p)++) != rqstp->rq_seqno)
+2 −2
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ nul_marshal(struct rpc_task *task, __be32 *p)
static int
nul_refresh(struct rpc_task *task)
{
	task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
	return 0;
}

@@ -136,7 +136,7 @@ struct rpc_cred null_cred = {
	.cr_auth	= &null_auth,
	.cr_ops		= &null_credops,
	.cr_count	= ATOMIC_INIT(1),
	.cr_flags	= RPCAUTH_CRED_UPTODATE,
	.cr_flags	= 1UL << RPCAUTH_CRED_UPTODATE,
#ifdef RPC_DEBUG
	.cr_magic	= RPCAUTH_CRED_MAGIC,
#endif
+2 −2
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
		return ERR_PTR(-ENOMEM);

	rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
	cred->uc_base.cr_flags = RPCAUTH_CRED_UPTODATE;
	cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
	if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
		cred->uc_uid = 0;
		cred->uc_gid = 0;
@@ -172,7 +172,7 @@ unx_marshal(struct rpc_task *task, __be32 *p)
static int
unx_refresh(struct rpc_task *task)
{
	task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
	return 0;
}