Commit 9e84df77 authored by Trond Myklebust's avatar Trond Myklebust

RPC: call_verify

	Don't label all retries as "server seeing garbage".
	Report correct error for buffer overflows.
	Fix incorrect buffer overflow test that was masking
		AUTH_REJECTEDCRED, AUTH_REJECTEDVERF,... errors.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent c4c7eb1a
...@@ -970,23 +970,31 @@ call_verify(struct rpc_task *task) ...@@ -970,23 +970,31 @@ call_verify(struct rpc_task *task)
struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
int len = task->tk_rqstp->rq_rcv_buf.len >> 2; int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
u32 *p = iov->iov_base, n; u32 *p = iov->iov_base, n;
int error = -EACCES;
if ((len -= 3) < 0) if ((len -= 3) < 0)
goto garbage; goto out_overflow;
p += 1; /* skip XID */ p += 1; /* skip XID */
if ((n = ntohl(*p++)) != RPC_REPLY) { if ((n = ntohl(*p++)) != RPC_REPLY) {
printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
goto garbage; goto out_retry;
} }
if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
int error = -EACCES;
if (--len < 0) if (--len < 0)
goto garbage; goto out_overflow;
if ((n = ntohl(*p++)) != RPC_AUTH_ERROR) { switch ((n = ntohl(*p++))) {
printk(KERN_WARNING "call_verify: RPC call rejected: %x\n", n); case RPC_AUTH_ERROR:
} else if (--len < 0) break;
case RPC_MISMATCH:
printk(KERN_WARNING "%s: RPC call version mismatch!\n", __FUNCTION__);
goto out_eio;
default:
printk(KERN_WARNING "%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
goto out_eio;
}
if (--len < 0)
goto out_overflow;
switch ((n = ntohl(*p++))) { switch ((n = ntohl(*p++))) {
case RPC_AUTH_REJECTEDCRED: case RPC_AUTH_REJECTEDCRED:
case RPC_AUTH_REJECTEDVERF: case RPC_AUTH_REJECTEDVERF:
...@@ -1017,20 +1025,18 @@ call_verify(struct rpc_task *task) ...@@ -1017,20 +1025,18 @@ call_verify(struct rpc_task *task)
default: default:
printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n); printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
error = -EIO; error = -EIO;
} else }
goto garbage;
dprintk("RPC: %4d call_verify: call rejected %d\n", dprintk("RPC: %4d call_verify: call rejected %d\n",
task->tk_pid, n); task->tk_pid, n);
rpc_exit(task, error); goto out_err;
return NULL;
} }
if (!(p = rpcauth_checkverf(task, p))) { if (!(p = rpcauth_checkverf(task, p))) {
printk(KERN_WARNING "call_verify: auth check failed\n"); printk(KERN_WARNING "call_verify: auth check failed\n");
goto garbage; /* bad verifier, retry */ goto out_retry; /* bad verifier, retry */
} }
len = p - (u32 *)iov->iov_base - 1; len = p - (u32 *)iov->iov_base - 1;
if (len < 0) if (len < 0)
goto garbage; goto out_overflow;
switch ((n = ntohl(*p++))) { switch ((n = ntohl(*p++))) {
case RPC_SUCCESS: case RPC_SUCCESS:
return p; return p;
...@@ -1053,23 +1059,28 @@ call_verify(struct rpc_task *task) ...@@ -1053,23 +1059,28 @@ call_verify(struct rpc_task *task)
task->tk_client->cl_server); task->tk_client->cl_server);
goto out_eio; goto out_eio;
case RPC_GARBAGE_ARGS: case RPC_GARBAGE_ARGS:
dprintk("RPC: %4d %s: server saw garbage\n", task->tk_pid, __FUNCTION__);
break; /* retry */ break; /* retry */
default: default:
printk(KERN_WARNING "call_verify: server accept status: %x\n", n); printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
/* Also retry */ /* Also retry */
} }
garbage: out_retry:
dprintk("RPC: %4d call_verify: server saw garbage\n", task->tk_pid);
task->tk_client->cl_stats->rpcgarbage++; task->tk_client->cl_stats->rpcgarbage++;
if (task->tk_garb_retry) { if (task->tk_garb_retry) {
task->tk_garb_retry--; task->tk_garb_retry--;
dprintk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid); dprintk(KERN_WARNING "RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
task->tk_action = call_bind; task->tk_action = call_bind;
return NULL; return NULL;
} }
printk(KERN_WARNING "RPC: garbage, exit EIO\n"); printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
out_eio: out_eio:
rpc_exit(task, -EIO); error = -EIO;
out_err:
rpc_exit(task, error);
return NULL; return NULL;
out_overflow:
printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
goto out_retry;
} }
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