Commit 6d52fdcb authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] XDR 'encode' phase move [2/6]

The RPCSEC_GSS user context defines a 'sequence number' in the AUTH header
fields in order to provide protection against replay attacks. This
number needs to lie within a given 'window', and is required to be updated
even when retransmitting dropped requests.

In order to allow this update to occur, move the XDR 'encode' phase
so that it is done immediately before writing the data to the socket.
parent 756a93f7
......@@ -187,6 +187,7 @@ void xprt_set_timeout(struct rpc_timeout *, unsigned int,
unsigned long);
void xprt_reserve(struct rpc_task *);
int xprt_prepare_transmit(struct rpc_task *);
void xprt_transmit(struct rpc_task *);
void xprt_receive(struct rpc_task *);
int xprt_adjust_timeout(struct rpc_timeout *);
......
......@@ -470,7 +470,7 @@ call_allocate(struct rpc_task *task)
dprintk("RPC: %4d call_allocate (status %d)\n",
task->tk_pid, task->tk_status);
task->tk_action = call_encode;
task->tk_action = call_bind;
if (task->tk_buffer)
return;
......@@ -510,8 +510,6 @@ call_encode(struct rpc_task *task)
dprintk("RPC: %4d call_encode (status %d)\n",
task->tk_pid, task->tk_status);
task->tk_action = call_bind;
/* Default buffer setup */
bufsiz = task->tk_bufsize >> 1;
sndbuf->head[0].iov_base = (void *)task->tk_buffer;
......@@ -533,7 +531,8 @@ call_encode(struct rpc_task *task)
if (!(p = call_header(task))) {
printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
rpc_exit(task, -EIO);
} else
return;
}
if (encode && (status = encode(req, p, task->tk_msg.rpc_argp)) < 0) {
printk(KERN_WARNING "%s: can't encode arguments: %d\n",
clnt->cl_protname, -status);
......@@ -615,10 +614,19 @@ call_transmit(struct rpc_task *task)
task->tk_pid, task->tk_status);
task->tk_action = call_status;
if (task->tk_status < 0)
return;
task->tk_status = xprt_prepare_transmit(task);
if (task->tk_status < 0)
return;
/* Encode here so that rpcsec_gss can use correct sequence number. */
call_encode(task);
if (task->tk_status < 0)
return;
xprt_transmit(task);
if (!task->tk_msg.rpc_proc->p_decode && task->tk_status >= 0) {
if (task->tk_status < 0)
return;
if (!task->tk_msg.rpc_proc->p_decode) {
task->tk_action = NULL;
rpc_wake_up_task(task);
}
......@@ -758,7 +766,7 @@ call_decode(struct rpc_task *task)
if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
task->tk_flags ^= RPC_CALL_REALUID;
task->tk_action = call_encode;
task->tk_action = call_bind;
task->tk_suid_retry--;
return;
}
......@@ -864,7 +872,7 @@ call_verify(struct rpc_task *task)
task->tk_garb_retry--;
dprintk("RPC: %4d call_verify: retry garbled creds\n",
task->tk_pid);
task->tk_action = call_encode;
task->tk_action = call_bind;
return NULL;
case RPC_AUTH_TOOWEAK:
printk(KERN_NOTICE "call_verify: server requires stronger "
......@@ -899,7 +907,7 @@ call_verify(struct rpc_task *task)
if (task->tk_garb_retry) {
task->tk_garb_retry--;
dprintk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid);
task->tk_action = call_encode;
task->tk_action = call_bind;
return NULL;
}
printk(KERN_WARNING "RPC: garbage, exit EIO\n");
......
......@@ -83,7 +83,6 @@
* Local functions
*/
static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);
static void do_xprt_transmit(struct rpc_task *);
static inline void do_xprt_reserve(struct rpc_task *);
static void xprt_disconnect(struct rpc_xprt *);
static void xprt_conn_status(struct rpc_task *task);
......@@ -1091,51 +1090,40 @@ xprt_timer(struct rpc_task *task)
* Place the actual RPC call.
* We have to copy the iovec because sendmsg fiddles with its contents.
*/
void
xprt_transmit(struct rpc_task *task)
int
xprt_prepare_transmit(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
int err = 0;
dprintk("RPC: %4d xprt_transmit(%x)\n", task->tk_pid,
*(u32 *)(req->rq_svec[0].iov_base));
dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid);
if (xprt->shutdown)
task->tk_status = -EIO;
return -EIO;
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
if (task->tk_status < 0)
return;
return -ENOTCONN;
if (task->tk_rpcwait)
rpc_remove_wait_queue(task);
/* set up everything as needed. */
/* Write the record marker */
if (xprt->stream) {
u32 *marker = req->rq_svec[0].iov_base;
*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
}
spin_lock_bh(&xprt->sock_lock);
if (!__xprt_lock_write(xprt, task)) {
spin_unlock_bh(&xprt->sock_lock);
return;
err = -EAGAIN;
goto out_unlock;
}
if (list_empty(&req->rq_list)) {
list_add_tail(&req->rq_list, &xprt->recv);
req->rq_received = 0;
}
out_unlock:
spin_unlock_bh(&xprt->sock_lock);
do_xprt_transmit(task);
return err;
}
static void
do_xprt_transmit(struct rpc_task *task)
void
xprt_transmit(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp;
......@@ -1143,6 +1131,16 @@ do_xprt_transmit(struct rpc_task *task)
int status, retry = 0;
dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
/* set up everything as needed. */
/* Write the record marker */
if (xprt->stream) {
u32 *marker = req->rq_svec[0].iov_base;
*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
}
/* Continue transmitting the packet/record. We must be careful
* to cope with writespace callbacks arriving _after_ we have
* called xprt_sendmsg().
......
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