提交 5d12e934 编写于 作者: Z ZhangXiaoxu 提交者: Xie XiuQi

SUNRPC: Use struct xdr_stream when decoding RPC Reply header

mainline inclusion
from mainline-v5.1-rc1
commit a0584ee9aed805446b044ce855e67264f0dc619e
category: bugfix
bugzilla: 13061
CVE: NA

-----------------------------------------------

Modernize and harden the code path that parses an RPC Reply
message.
Signed-off-by: NChuck Lever <chuck.lever@oracle.com>
Signed-off-by: NAnna Schumaker <Anna.Schumaker@Netapp.com>

Conflict:
	include/linux/sunrpc/auth.h
	include/linux/sunrpc/xdr.h
	net/sunrpc/auth.c
	net/sunrpc/auth_gss/auth_gss.c
	net/sunrpc/auth_null.c
	net/sunrpc/clnt.c
Partly merged because it can fix xfstests generic/095 failed with WARN_ON
when call_decode.
eb90a16e9087 ("SUNRPC: rpc_decode_header() must always return a non-zero
value on error") is not needed because we not merge the code:
	error = rpcauth_checkverf(task, xdr)
Signed-off-by: NZhangXiaoxu <zhangxiaoxu5@huawei.com>
Reviewed-by: Nyangerkun <yangerkun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 71626fd3
...@@ -1919,6 +1919,15 @@ gss_wrap_req(struct rpc_task *task, ...@@ -1919,6 +1919,15 @@ gss_wrap_req(struct rpc_task *task,
return status; return status;
} }
static inline int
gss_unwrap_resp_auth(struct rpc_cred *cred)
{
struct rpc_auth *auth = cred->cr_auth;
auth->au_rslack = auth->au_verfsize;
return 0;
}
static inline int static inline int
gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
struct rpc_rqst *rqstp, __be32 **p) struct rpc_rqst *rqstp, __be32 **p)
...@@ -1930,6 +1939,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, ...@@ -1930,6 +1939,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
u32 integ_len; u32 integ_len;
u32 maj_stat; u32 maj_stat;
int status = -EIO; int status = -EIO;
struct rpc_auth *auth = cred->cr_auth;
integ_len = ntohl(*(*p)++); integ_len = ntohl(*(*p)++);
if (integ_len & 3) if (integ_len & 3)
...@@ -1953,6 +1963,8 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, ...@@ -1953,6 +1963,8 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
if (maj_stat != GSS_S_COMPLETE) if (maj_stat != GSS_S_COMPLETE)
return status; return status;
auth->au_rslack = auth->au_verfsize + 2 + 1 + XDR_QUADLEN(mic.len);
return 0; return 0;
} }
...@@ -1965,6 +1977,8 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, ...@@ -1965,6 +1977,8 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
u32 opaque_len; u32 opaque_len;
u32 maj_stat; u32 maj_stat;
int status = -EIO; int status = -EIO;
unsigned int savedlen = rcv_buf->len;
struct rpc_auth *auth = cred->cr_auth;
opaque_len = ntohl(*(*p)++); opaque_len = ntohl(*(*p)++);
offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
...@@ -1981,6 +1995,8 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, ...@@ -1981,6 +1995,8 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
if (ntohl(*(*p)++) != rqstp->rq_seqno) if (ntohl(*(*p)++) != rqstp->rq_seqno)
return status; return status;
auth->au_rslack = auth->au_verfsize + 2 + XDR_QUADLEN(savedlen - rcv_buf->len);
return 0; return 0;
} }
...@@ -2002,15 +2018,13 @@ gss_unwrap_resp(struct rpc_task *task, ...@@ -2002,15 +2018,13 @@ gss_unwrap_resp(struct rpc_task *task,
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
gc_base); gc_base);
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
__be32 *savedp = p;
struct kvec *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
int savedlen = head->iov_len;
int status = -EIO; int status = -EIO;
if (ctx->gc_proc != RPC_GSS_PROC_DATA) if (ctx->gc_proc != RPC_GSS_PROC_DATA)
goto out_decode; goto out_decode;
switch (gss_cred->gc_service) { switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE: case RPC_GSS_SVC_NONE:
status = gss_unwrap_resp_auth(cred);
break; break;
case RPC_GSS_SVC_INTEGRITY: case RPC_GSS_SVC_INTEGRITY:
status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p); status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
...@@ -2023,9 +2037,6 @@ gss_unwrap_resp(struct rpc_task *task, ...@@ -2023,9 +2037,6 @@ gss_unwrap_resp(struct rpc_task *task,
goto out; goto out;
break; break;
} }
/* take into account extra slack for integrity and privacy cases: */
cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
+ (savedlen - head->iov_len);
out_decode: out_decode:
status = gss_unwrap_req_decode(decode, rqstp, p, obj); status = gss_unwrap_req_decode(decode, rqstp, p, obj);
out: out:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册