Skip to content

Commit

Permalink
SUNRPC: Use struct xdr_stream when decoding RPC Reply header
Browse files Browse the repository at this point in the history
Modernize and harden the code path that parses an RPC Reply
message.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
  • Loading branch information
Chuck Lever authored and Anna Schumaker committed Feb 14, 2019
1 parent 7f5667a commit a0584ee
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 201 deletions.
15 changes: 10 additions & 5 deletions include/linux/sunrpc/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,12 @@ struct rpc_credops {
int (*crmarshal)(struct rpc_task *task,
struct xdr_stream *xdr);
int (*crrefresh)(struct rpc_task *);
__be32 * (*crvalidate)(struct rpc_task *, __be32 *);
int (*crvalidate)(struct rpc_task *task,
struct xdr_stream *xdr);
int (*crwrap_req)(struct rpc_task *task,
struct xdr_stream *xdr);
int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t,
void *, __be32 *, void *);
int (*crunwrap_resp)(struct rpc_task *task,
struct xdr_stream *xdr);
int (*crkey_timeout)(struct rpc_cred *);
char * (*crstringify_acceptor)(struct rpc_cred *);
bool (*crneed_reencode)(struct rpc_task *);
Expand Down Expand Up @@ -168,12 +169,16 @@ struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
void put_rpccred(struct rpc_cred *);
int rpcauth_marshcred(struct rpc_task *task,
struct xdr_stream *xdr);
__be32 * rpcauth_checkverf(struct rpc_task *, __be32 *);
int rpcauth_checkverf(struct rpc_task *task,
struct xdr_stream *xdr);
int rpcauth_wrap_req_encode(struct rpc_task *task,
struct xdr_stream *xdr);
int rpcauth_wrap_req(struct rpc_task *task,
struct xdr_stream *xdr);
int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj);
int rpcauth_unwrap_resp_decode(struct rpc_task *task,
struct xdr_stream *xdr);
int rpcauth_unwrap_resp(struct rpc_task *task,
struct xdr_stream *xdr);
bool rpcauth_xmit_need_reencode(struct rpc_task *task);
int rpcauth_refreshcred(struct rpc_task *);
void rpcauth_invalcred(struct rpc_task *);
Expand Down
1 change: 1 addition & 0 deletions include/linux/sunrpc/xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)

#define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
#define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
#define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT)
#define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)

#define rpc_call cpu_to_be32(RPC_CALL)
Expand Down
63 changes: 41 additions & 22 deletions net/sunrpc/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <linux/sunrpc/gss_api.h>
#include <linux/spinlock.h>

#include <trace/events/sunrpc.h>

#define RPC_CREDCACHE_DEFAULT_HASHBITS (4)
struct rpc_cred_cache {
struct hlist_head *hashtable;
Expand Down Expand Up @@ -773,14 +775,6 @@ int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr)
return ops->crmarshal(task, xdr);
}

__be32 *
rpcauth_checkverf(struct rpc_task *task, __be32 *p)
{
struct rpc_cred *cred = task->tk_rqstp->rq_cred;

return cred->cr_ops->crvalidate(task, p);
}

/**
* rpcauth_wrap_req_encode - XDR encode the RPC procedure
* @task: controlling RPC task
Expand Down Expand Up @@ -814,27 +808,52 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
return ops->crwrap_req(task, xdr);
}

static int
rpcauth_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp,
__be32 *data, void *obj)
/**
* rpcauth_checkverf - Validate verifier in RPC Reply header
* @task: controlling RPC task
* @xdr: xdr_stream containing RPC Reply header
*
* On success, @xdr is updated to point past the verifier and
* zero is returned. Otherwise, @xdr is in an undefined state
* and a negative errno is returned.
*/
int
rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
{
struct xdr_stream xdr;
const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;

xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, data, rqstp);
return decode(rqstp, &xdr, obj);
return ops->crvalidate(task, xdr);
}

/**
* rpcauth_unwrap_resp_decode - Invoke XDR decode function
* @task: controlling RPC task
* @xdr: stream where the Reply message resides
*
* Returns zero on success; otherwise a negative errno is returned.
*/
int
rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp,
__be32 *data, void *obj)
rpcauth_unwrap_resp_decode(struct rpc_task *task, struct xdr_stream *xdr)
{
struct rpc_cred *cred = task->tk_rqstp->rq_cred;
kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode;

return decode(task->tk_rqstp, xdr, task->tk_msg.rpc_resp);
}
EXPORT_SYMBOL_GPL(rpcauth_unwrap_resp_decode);

/**
* rpcauth_unwrap_resp - Invoke unwrap and decode function for the cred
* @task: controlling RPC task
* @xdr: stream where the Reply message resides
*
* Returns zero on success; otherwise a negative errno is returned.
*/
int
rpcauth_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
{
const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;

if (cred->cr_ops->crunwrap_resp)
return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
data, obj);
/* By default, we decode the arguments normally. */
return rpcauth_unwrap_req_decode(decode, rqstp, data, obj);
return ops->crunwrap_resp(task, xdr);
}

bool
Expand Down
Loading

0 comments on commit a0584ee

Please sign in to comment.