Commit 97b78ae9 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

SUNRPC: Ensure we respect the RPCSEC_GSS sequence number limit

According to RFC2203, the RPCSEC_GSS sequence numbers are bounded to
an upper limit of MAXSEQ = 0x80000000. Ensure that we handle that
correctly.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent e66721f0
...@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p) ...@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
cred_len = p++; cred_len = p++;
spin_lock(&ctx->gc_seq_lock); spin_lock(&ctx->gc_seq_lock);
req->rq_seqno = ctx->gc_seq++; req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
spin_unlock(&ctx->gc_seq_lock); spin_unlock(&ctx->gc_seq_lock);
if (req->rq_seqno == MAXSEQ)
goto out_expired;
*p++ = htonl((u32) RPC_GSS_VERSION); *p++ = htonl((u32) RPC_GSS_VERSION);
*p++ = htonl((u32) ctx->gc_proc); *p++ = htonl((u32) ctx->gc_proc);
...@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p) ...@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
mic.data = (u8 *)(p + 1); mic.data = (u8 *)(p + 1);
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) { if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); goto out_expired;
} else if (maj_stat != 0) { } else if (maj_stat != 0) {
printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
task->tk_status = -EIO;
goto out_put_ctx; goto out_put_ctx;
} }
p = xdr_encode_opaque(p, NULL, mic.len); p = xdr_encode_opaque(p, NULL, mic.len);
gss_put_ctx(ctx); gss_put_ctx(ctx);
return p; return p;
out_expired:
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
task->tk_status = -EKEYEXPIRED;
out_put_ctx: out_put_ctx:
gss_put_ctx(ctx); gss_put_ctx(ctx);
return NULL; return NULL;
......
...@@ -1741,11 +1741,8 @@ rpc_xdr_encode(struct rpc_task *task) ...@@ -1741,11 +1741,8 @@ rpc_xdr_encode(struct rpc_task *task)
req->rq_rcvsize); req->rq_rcvsize);
p = rpc_encode_header(task); p = rpc_encode_header(task);
if (p == NULL) { if (p == NULL)
printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
rpc_exit(task, -EIO);
return; return;
}
encode = task->tk_msg.rpc_proc->p_encode; encode = task->tk_msg.rpc_proc->p_encode;
if (encode == NULL) if (encode == NULL)
...@@ -1770,10 +1767,17 @@ call_encode(struct rpc_task *task) ...@@ -1770,10 +1767,17 @@ call_encode(struct rpc_task *task)
/* Did the encode result in an error condition? */ /* Did the encode result in an error condition? */
if (task->tk_status != 0) { if (task->tk_status != 0) {
/* Was the error nonfatal? */ /* Was the error nonfatal? */
if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM) switch (task->tk_status) {
case -EAGAIN:
case -ENOMEM:
rpc_delay(task, HZ >> 4); rpc_delay(task, HZ >> 4);
else break;
case -EKEYEXPIRED:
task->tk_action = call_refresh;
break;
default:
rpc_exit(task, task->tk_status); rpc_exit(task, task->tk_status);
}
return; return;
} }
...@@ -2335,6 +2339,7 @@ rpc_encode_header(struct rpc_task *task) ...@@ -2335,6 +2339,7 @@ rpc_encode_header(struct rpc_task *task)
*p++ = htonl(clnt->cl_vers); /* program version */ *p++ = htonl(clnt->cl_vers); /* program version */
*p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */
p = rpcauth_marshcred(task, p); p = rpcauth_marshcred(task, p);
if (p)
req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
return p; return p;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment