aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/auth.h15
-rw-r--r--include/linux/sunrpc/xdr.h1
-rw-r--r--net/sunrpc/auth.c63
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c204
-rw-r--r--net/sunrpc/auth_null.c31
-rw-r--r--net/sunrpc/auth_unix.c42
-rw-r--r--net/sunrpc/clnt.c88
7 files changed, 243 insertions, 201 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 96e237f8e60b..c51e1893f77e 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -134,11 +134,12 @@ struct rpc_credops {
134 int (*crmarshal)(struct rpc_task *task, 134 int (*crmarshal)(struct rpc_task *task,
135 struct xdr_stream *xdr); 135 struct xdr_stream *xdr);
136 int (*crrefresh)(struct rpc_task *); 136 int (*crrefresh)(struct rpc_task *);
137 __be32 * (*crvalidate)(struct rpc_task *, __be32 *); 137 int (*crvalidate)(struct rpc_task *task,
138 struct xdr_stream *xdr);
138 int (*crwrap_req)(struct rpc_task *task, 139 int (*crwrap_req)(struct rpc_task *task,
139 struct xdr_stream *xdr); 140 struct xdr_stream *xdr);
140 int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t, 141 int (*crunwrap_resp)(struct rpc_task *task,
141 void *, __be32 *, void *); 142 struct xdr_stream *xdr);
142 int (*crkey_timeout)(struct rpc_cred *); 143 int (*crkey_timeout)(struct rpc_cred *);
143 char * (*crstringify_acceptor)(struct rpc_cred *); 144 char * (*crstringify_acceptor)(struct rpc_cred *);
144 bool (*crneed_reencode)(struct rpc_task *); 145 bool (*crneed_reencode)(struct rpc_task *);
@@ -168,12 +169,16 @@ struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
168void put_rpccred(struct rpc_cred *); 169void put_rpccred(struct rpc_cred *);
169int rpcauth_marshcred(struct rpc_task *task, 170int rpcauth_marshcred(struct rpc_task *task,
170 struct xdr_stream *xdr); 171 struct xdr_stream *xdr);
171__be32 * rpcauth_checkverf(struct rpc_task *, __be32 *); 172int rpcauth_checkverf(struct rpc_task *task,
173 struct xdr_stream *xdr);
172int rpcauth_wrap_req_encode(struct rpc_task *task, 174int rpcauth_wrap_req_encode(struct rpc_task *task,
173 struct xdr_stream *xdr); 175 struct xdr_stream *xdr);
174int rpcauth_wrap_req(struct rpc_task *task, 176int rpcauth_wrap_req(struct rpc_task *task,
175 struct xdr_stream *xdr); 177 struct xdr_stream *xdr);
176int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj); 178int rpcauth_unwrap_resp_decode(struct rpc_task *task,
179 struct xdr_stream *xdr);
180int rpcauth_unwrap_resp(struct rpc_task *task,
181 struct xdr_stream *xdr);
177bool rpcauth_xmit_need_reencode(struct rpc_task *task); 182bool rpcauth_xmit_need_reencode(struct rpc_task *task);
178int rpcauth_refreshcred(struct rpc_task *); 183int rpcauth_refreshcred(struct rpc_task *);
179void rpcauth_invalcred(struct rpc_task *); 184void rpcauth_invalcred(struct rpc_task *);
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index c54041950cc0..65af6a204b75 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -89,6 +89,7 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
89 89
90#define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL) 90#define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
91#define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX) 91#define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
92#define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT)
92#define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS) 93#define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)
93 94
94#define rpc_call cpu_to_be32(RPC_CALL) 95#define rpc_call cpu_to_be32(RPC_CALL)
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index add2135d9b01..e7861026b9e5 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -17,6 +17,8 @@
17#include <linux/sunrpc/gss_api.h> 17#include <linux/sunrpc/gss_api.h>
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19 19
20#include <trace/events/sunrpc.h>
21
20#define RPC_CREDCACHE_DEFAULT_HASHBITS (4) 22#define RPC_CREDCACHE_DEFAULT_HASHBITS (4)
21struct rpc_cred_cache { 23struct rpc_cred_cache {
22 struct hlist_head *hashtable; 24 struct hlist_head *hashtable;
@@ -773,14 +775,6 @@ int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr)
773 return ops->crmarshal(task, xdr); 775 return ops->crmarshal(task, xdr);
774} 776}
775 777
776__be32 *
777rpcauth_checkverf(struct rpc_task *task, __be32 *p)
778{
779 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
780
781 return cred->cr_ops->crvalidate(task, p);
782}
783
784/** 778/**
785 * rpcauth_wrap_req_encode - XDR encode the RPC procedure 779 * rpcauth_wrap_req_encode - XDR encode the RPC procedure
786 * @task: controlling RPC task 780 * @task: controlling RPC task
@@ -814,27 +808,52 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
814 return ops->crwrap_req(task, xdr); 808 return ops->crwrap_req(task, xdr);
815} 809}
816 810
817static int 811/**
818rpcauth_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp, 812 * rpcauth_checkverf - Validate verifier in RPC Reply header
819 __be32 *data, void *obj) 813 * @task: controlling RPC task
814 * @xdr: xdr_stream containing RPC Reply header
815 *
816 * On success, @xdr is updated to point past the verifier and
817 * zero is returned. Otherwise, @xdr is in an undefined state
818 * and a negative errno is returned.
819 */
820int
821rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
820{ 822{
821 struct xdr_stream xdr; 823 const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
822 824
823 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, data, rqstp); 825 return ops->crvalidate(task, xdr);
824 return decode(rqstp, &xdr, obj);
825} 826}
826 827
828/**
829 * rpcauth_unwrap_resp_decode - Invoke XDR decode function
830 * @task: controlling RPC task
831 * @xdr: stream where the Reply message resides
832 *
833 * Returns zero on success; otherwise a negative errno is returned.
834 */
827int 835int
828rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, 836rpcauth_unwrap_resp_decode(struct rpc_task *task, struct xdr_stream *xdr)
829 __be32 *data, void *obj)
830{ 837{
831 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 838 kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode;
839
840 return decode(task->tk_rqstp, xdr, task->tk_msg.rpc_resp);
841}
842EXPORT_SYMBOL_GPL(rpcauth_unwrap_resp_decode);
843
844/**
845 * rpcauth_unwrap_resp - Invoke unwrap and decode function for the cred
846 * @task: controlling RPC task
847 * @xdr: stream where the Reply message resides
848 *
849 * Returns zero on success; otherwise a negative errno is returned.
850 */
851int
852rpcauth_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
853{
854 const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
832 855
833 if (cred->cr_ops->crunwrap_resp) 856 return ops->crunwrap_resp(task, xdr);
834 return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
835 data, obj);
836 /* By default, we decode the arguments normally. */
837 return rpcauth_unwrap_req_decode(decode, rqstp, data, obj);
838} 857}
839 858
840bool 859bool
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index b333b1bdad45..206788e8b787 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1671,59 +1671,62 @@ gss_refresh_null(struct rpc_task *task)
1671 return 0; 1671 return 0;
1672} 1672}
1673 1673
1674static __be32 * 1674static int
1675gss_validate(struct rpc_task *task, __be32 *p) 1675gss_validate(struct rpc_task *task, struct xdr_stream *xdr)
1676{ 1676{
1677 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 1677 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
1678 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 1678 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1679 __be32 *seq = NULL; 1679 __be32 *p, *seq = NULL;
1680 struct kvec iov; 1680 struct kvec iov;
1681 struct xdr_buf verf_buf; 1681 struct xdr_buf verf_buf;
1682 struct xdr_netobj mic; 1682 struct xdr_netobj mic;
1683 u32 flav,len; 1683 u32 len, maj_stat;
1684 u32 maj_stat; 1684 int status;
1685 __be32 *ret = ERR_PTR(-EIO);
1686 1685
1687 dprintk("RPC: %5u %s\n", task->tk_pid, __func__); 1686 p = xdr_inline_decode(xdr, 2 * sizeof(*p));
1687 if (!p)
1688 goto validate_failed;
1689 if (*p++ != rpc_auth_gss)
1690 goto validate_failed;
1691 len = be32_to_cpup(p);
1692 if (len > RPC_MAX_AUTH_SIZE)
1693 goto validate_failed;
1694 p = xdr_inline_decode(xdr, len);
1695 if (!p)
1696 goto validate_failed;
1688 1697
1689 flav = ntohl(*p++);
1690 if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE)
1691 goto out_bad;
1692 if (flav != RPC_AUTH_GSS)
1693 goto out_bad;
1694 seq = kmalloc(4, GFP_NOFS); 1698 seq = kmalloc(4, GFP_NOFS);
1695 if (!seq) 1699 if (!seq)
1696 goto out_bad; 1700 goto validate_failed;
1697 *seq = htonl(task->tk_rqstp->rq_seqno); 1701 *seq = cpu_to_be32(task->tk_rqstp->rq_seqno);
1698 iov.iov_base = seq; 1702 iov.iov_base = seq;
1699 iov.iov_len = 4; 1703 iov.iov_len = 4;
1700 xdr_buf_from_iov(&iov, &verf_buf); 1704 xdr_buf_from_iov(&iov, &verf_buf);
1701 mic.data = (u8 *)p; 1705 mic.data = (u8 *)p;
1702 mic.len = len; 1706 mic.len = len;
1703
1704 ret = ERR_PTR(-EACCES);
1705 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 1707 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
1706 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1708 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1707 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1709 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1708 if (maj_stat) { 1710 if (maj_stat)
1709 dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n", 1711 goto bad_mic;
1710 task->tk_pid, __func__, maj_stat); 1712
1711 goto out_bad;
1712 }
1713 /* We leave it to unwrap to calculate au_rslack. For now we just 1713 /* We leave it to unwrap to calculate au_rslack. For now we just
1714 * calculate the length of the verifier: */ 1714 * calculate the length of the verifier: */
1715 cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; 1715 cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
1716 status = 0;
1717out:
1716 gss_put_ctx(ctx); 1718 gss_put_ctx(ctx);
1717 dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n",
1718 task->tk_pid, __func__);
1719 kfree(seq);
1720 return p + XDR_QUADLEN(len);
1721out_bad:
1722 gss_put_ctx(ctx);
1723 dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__,
1724 PTR_ERR(ret));
1725 kfree(seq); 1719 kfree(seq);
1726 return ret; 1720 return status;
1721
1722validate_failed:
1723 status = -EIO;
1724 goto out;
1725bad_mic:
1726 dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n",
1727 task->tk_pid, __func__, maj_stat);
1728 status = -EACCES;
1729 goto out;
1727} 1730}
1728 1731
1729static int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1732static int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
@@ -1921,79 +1924,98 @@ out:
1921 return status; 1924 return status;
1922} 1925}
1923 1926
1924static inline int 1927static int
1928gss_unwrap_resp_auth(struct rpc_cred *cred)
1929{
1930 cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize;
1931 return 0;
1932}
1933
1934static int
1925gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1935gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1926 struct rpc_rqst *rqstp, __be32 **p) 1936 struct rpc_rqst *rqstp, struct xdr_stream *xdr)
1927{ 1937{
1928 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; 1938 struct xdr_buf integ_buf, *rcv_buf = &rqstp->rq_rcv_buf;
1929 struct xdr_buf integ_buf; 1939 u32 data_offset, mic_offset, integ_len, maj_stat;
1930 struct xdr_netobj mic; 1940 struct xdr_netobj mic;
1931 u32 data_offset, mic_offset; 1941 __be32 *p;
1932 u32 integ_len;
1933 u32 maj_stat;
1934 int status = -EIO;
1935 1942
1936 integ_len = ntohl(*(*p)++); 1943 p = xdr_inline_decode(xdr, 2 * sizeof(*p));
1944 if (unlikely(!p))
1945 goto unwrap_failed;
1946 integ_len = be32_to_cpup(p++);
1937 if (integ_len & 3) 1947 if (integ_len & 3)
1938 return status; 1948 goto unwrap_failed;
1939 data_offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; 1949 data_offset = (u8 *)(p) - (u8 *)rcv_buf->head[0].iov_base;
1940 mic_offset = integ_len + data_offset; 1950 mic_offset = integ_len + data_offset;
1941 if (mic_offset > rcv_buf->len) 1951 if (mic_offset > rcv_buf->len)
1942 return status; 1952 goto unwrap_failed;
1943 if (ntohl(*(*p)++) != rqstp->rq_seqno) 1953 if (be32_to_cpup(p) != rqstp->rq_seqno)
1944 return status; 1954 goto unwrap_failed;
1945
1946 if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset,
1947 mic_offset - data_offset))
1948 return status;
1949 1955
1956 if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, integ_len))
1957 goto unwrap_failed;
1950 if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) 1958 if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
1951 return status; 1959 goto unwrap_failed;
1952
1953 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 1960 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
1954 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1961 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1955 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1962 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1956 if (maj_stat != GSS_S_COMPLETE) 1963 if (maj_stat != GSS_S_COMPLETE)
1957 return status; 1964 goto bad_mic;
1965
1966 cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + 2 +
1967 1 + XDR_QUADLEN(mic.len);
1958 return 0; 1968 return 0;
1969unwrap_failed:
1970 return -EIO;
1971bad_mic:
1972 dprintk("RPC: %s: gss_verify_mic returned error 0x%08x\n",
1973 __func__, maj_stat);
1974 return -EIO;
1959} 1975}
1960 1976
1961static inline int 1977static int
1962gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1978gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1963 struct rpc_rqst *rqstp, __be32 **p) 1979 struct rpc_rqst *rqstp, struct xdr_stream *xdr)
1964{ 1980{
1965 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; 1981 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf;
1966 u32 offset; 1982 struct kvec *head = rqstp->rq_rcv_buf.head;
1967 u32 opaque_len; 1983 unsigned int savedlen = rcv_buf->len;
1968 u32 maj_stat; 1984 u32 offset, opaque_len, maj_stat;
1969 int status = -EIO; 1985 __be32 *p;
1970 1986
1971 opaque_len = ntohl(*(*p)++); 1987 p = xdr_inline_decode(xdr, 2 * sizeof(*p));
1972 offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; 1988 if (unlikely(!p))
1989 goto unwrap_failed;
1990 opaque_len = be32_to_cpup(p++);
1991 offset = (u8 *)(p) - (u8 *)head->iov_base;
1973 if (offset + opaque_len > rcv_buf->len) 1992 if (offset + opaque_len > rcv_buf->len)
1974 return status; 1993 goto unwrap_failed;
1975 /* remove padding: */
1976 rcv_buf->len = offset + opaque_len; 1994 rcv_buf->len = offset + opaque_len;
1977 1995
1978 maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); 1996 maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
1979 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1997 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1980 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1998 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1981 if (maj_stat != GSS_S_COMPLETE) 1999 if (maj_stat != GSS_S_COMPLETE)
1982 return status; 2000 goto bad_unwrap;
1983 if (ntohl(*(*p)++) != rqstp->rq_seqno) 2001 /* gss_unwrap decrypted the sequence number */
1984 return status; 2002 if (be32_to_cpup(p++) != rqstp->rq_seqno)
1985 2003 goto unwrap_failed;
1986 return 0;
1987}
1988 2004
1989static int 2005 /* gss_unwrap redacts the opaque blob from the head iovec.
1990gss_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp, 2006 * rcv_buf has changed, thus the stream needs to be reset.
1991 __be32 *p, void *obj) 2007 */
1992{ 2008 xdr_init_decode(xdr, rcv_buf, p, rqstp);
1993 struct xdr_stream xdr;
1994 2009
1995 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p, rqstp); 2010 cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + 2 +
1996 return decode(rqstp, &xdr, obj); 2011 XDR_QUADLEN(savedlen - rcv_buf->len);
2012 return 0;
2013unwrap_failed:
2014 return -EIO;
2015bad_unwrap:
2016 dprintk("RPC: %s: gss_unwrap returned error 0x%08x\n",
2017 __func__, maj_stat);
2018 return -EIO;
1997} 2019}
1998 2020
1999static bool 2021static bool
@@ -2037,39 +2059,33 @@ out:
2037} 2059}
2038 2060
2039static int 2061static int
2040gss_unwrap_resp(struct rpc_task *task, 2062gss_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
2041 kxdrdproc_t decode, void *rqstp, __be32 *p, void *obj)
2042{ 2063{
2043 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 2064 struct rpc_rqst *rqstp = task->tk_rqstp;
2065 struct rpc_cred *cred = rqstp->rq_cred;
2044 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 2066 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
2045 gc_base); 2067 gc_base);
2046 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 2068 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
2047 __be32 *savedp = p; 2069 int status = -EIO;
2048 struct kvec *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
2049 int savedlen = head->iov_len;
2050 int status = -EIO;
2051 2070
2052 if (ctx->gc_proc != RPC_GSS_PROC_DATA) 2071 if (ctx->gc_proc != RPC_GSS_PROC_DATA)
2053 goto out_decode; 2072 goto out_decode;
2054 switch (gss_cred->gc_service) { 2073 switch (gss_cred->gc_service) {
2055 case RPC_GSS_SVC_NONE: 2074 case RPC_GSS_SVC_NONE:
2075 status = gss_unwrap_resp_auth(cred);
2056 break; 2076 break;
2057 case RPC_GSS_SVC_INTEGRITY: 2077 case RPC_GSS_SVC_INTEGRITY:
2058 status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p); 2078 status = gss_unwrap_resp_integ(cred, ctx, rqstp, xdr);
2059 if (status)
2060 goto out;
2061 break; 2079 break;
2062 case RPC_GSS_SVC_PRIVACY: 2080 case RPC_GSS_SVC_PRIVACY:
2063 status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p); 2081 status = gss_unwrap_resp_priv(cred, ctx, rqstp, xdr);
2064 if (status)
2065 goto out;
2066 break; 2082 break;
2067 } 2083 }
2068 /* take into account extra slack for integrity and privacy cases: */ 2084 if (status)
2069 cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp) 2085 goto out;
2070 + (savedlen - head->iov_len); 2086
2071out_decode: 2087out_decode:
2072 status = gss_unwrap_req_decode(decode, rqstp, p, obj); 2088 status = rpcauth_unwrap_resp_decode(task, xdr);
2073out: 2089out:
2074 gss_put_ctx(ctx); 2090 gss_put_ctx(ctx);
2075 dprintk("RPC: %5u %s returning %d\n", 2091 dprintk("RPC: %5u %s returning %d\n",
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 797f8472c21b..bf96975ffc4b 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -86,25 +86,19 @@ nul_refresh(struct rpc_task *task)
86 return 0; 86 return 0;
87} 87}
88 88
89static __be32 * 89static int
90nul_validate(struct rpc_task *task, __be32 *p) 90nul_validate(struct rpc_task *task, struct xdr_stream *xdr)
91{ 91{
92 rpc_authflavor_t flavor; 92 __be32 *p;
93 u32 size; 93
94 94 p = xdr_inline_decode(xdr, 2 * sizeof(*p));
95 flavor = ntohl(*p++); 95 if (!p)
96 if (flavor != RPC_AUTH_NULL) { 96 return -EIO;
97 printk("RPC: bad verf flavor: %u\n", flavor); 97 if (*p++ != rpc_auth_null)
98 return ERR_PTR(-EIO); 98 return -EIO;
99 } 99 if (*p != xdr_zero)
100 100 return -EIO;
101 size = ntohl(*p++); 101 return 0;
102 if (size != 0) {
103 printk("RPC: bad verf size: %u\n", size);
104 return ERR_PTR(-EIO);
105 }
106
107 return p;
108} 102}
109 103
110const struct rpc_authops authnull_ops = { 104const struct rpc_authops authnull_ops = {
@@ -134,6 +128,7 @@ const struct rpc_credops null_credops = {
134 .crwrap_req = rpcauth_wrap_req_encode, 128 .crwrap_req = rpcauth_wrap_req_encode,
135 .crrefresh = nul_refresh, 129 .crrefresh = nul_refresh,
136 .crvalidate = nul_validate, 130 .crvalidate = nul_validate,
131 .crunwrap_resp = rpcauth_unwrap_resp_decode,
137}; 132};
138 133
139static 134static
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 1d5b7ed9c6f7..5ea84a96f96e 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -160,29 +160,32 @@ unx_refresh(struct rpc_task *task)
160 return 0; 160 return 0;
161} 161}
162 162
163static __be32 * 163static int
164unx_validate(struct rpc_task *task, __be32 *p) 164unx_validate(struct rpc_task *task, struct xdr_stream *xdr)
165{ 165{
166 rpc_authflavor_t flavor; 166 __be32 *p;
167 u32 size; 167 u32 size;
168
169 flavor = ntohl(*p++);
170 if (flavor != RPC_AUTH_NULL &&
171 flavor != RPC_AUTH_UNIX &&
172 flavor != RPC_AUTH_SHORT) {
173 printk("RPC: bad verf flavor: %u\n", flavor);
174 return ERR_PTR(-EIO);
175 }
176 168
177 size = ntohl(*p++); 169 p = xdr_inline_decode(xdr, 2 * sizeof(*p));
178 if (size > RPC_MAX_AUTH_SIZE) { 170 if (!p)
179 printk("RPC: giant verf size: %u\n", size); 171 return -EIO;
180 return ERR_PTR(-EIO); 172 switch (*p++) {
173 case rpc_auth_null:
174 case rpc_auth_unix:
175 case rpc_auth_short:
176 break;
177 default:
178 return -EIO;
181 } 179 }
182 task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; 180 size = be32_to_cpup(p);
183 p += (size >> 2); 181 if (size > RPC_MAX_AUTH_SIZE)
182 return -EIO;
183 p = xdr_inline_decode(xdr, size);
184 if (!p)
185 return -EIO;
184 186
185 return p; 187 task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2;
188 return 0;
186} 189}
187 190
188int __init rpc_init_authunix(void) 191int __init rpc_init_authunix(void)
@@ -223,4 +226,5 @@ const struct rpc_credops unix_credops = {
223 .crwrap_req = rpcauth_wrap_req_encode, 226 .crwrap_req = rpcauth_wrap_req_encode,
224 .crrefresh = unx_refresh, 227 .crrefresh = unx_refresh,
225 .crvalidate = unx_validate, 228 .crvalidate = unx_validate,
229 .crunwrap_resp = rpcauth_unwrap_resp_decode,
226}; 230};
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index e9735089bd66..803e93105af1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -79,7 +79,8 @@ static void call_connect_status(struct rpc_task *task);
79 79
80static int rpc_encode_header(struct rpc_task *task, 80static int rpc_encode_header(struct rpc_task *task,
81 struct xdr_stream *xdr); 81 struct xdr_stream *xdr);
82static __be32 *rpc_decode_header(struct rpc_task *task); 82static int rpc_decode_header(struct rpc_task *task,
83 struct xdr_stream *xdr);
83static int rpc_ping(struct rpc_clnt *clnt); 84static int rpc_ping(struct rpc_clnt *clnt);
84 85
85static void rpc_register_client(struct rpc_clnt *clnt) 86static void rpc_register_client(struct rpc_clnt *clnt)
@@ -2251,12 +2252,11 @@ call_decode(struct rpc_task *task)
2251{ 2252{
2252 struct rpc_clnt *clnt = task->tk_client; 2253 struct rpc_clnt *clnt = task->tk_client;
2253 struct rpc_rqst *req = task->tk_rqstp; 2254 struct rpc_rqst *req = task->tk_rqstp;
2254 kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode; 2255 struct xdr_stream xdr;
2255 __be32 *p;
2256 2256
2257 dprint_status(task); 2257 dprint_status(task);
2258 2258
2259 if (!decode) { 2259 if (!task->tk_msg.rpc_proc->p_decode) {
2260 task->tk_action = rpc_exit_task; 2260 task->tk_action = rpc_exit_task;
2261 return; 2261 return;
2262 } 2262 }
@@ -2292,29 +2292,27 @@ call_decode(struct rpc_task *task)
2292 goto out_retry; 2292 goto out_retry;
2293 } 2293 }
2294 2294
2295 p = rpc_decode_header(task); 2295 xdr_init_decode(&xdr, &req->rq_rcv_buf,
2296 if (IS_ERR(p)) { 2296 req->rq_rcv_buf.head[0].iov_base, req);
2297 if (p == ERR_PTR(-EAGAIN)) 2297 switch (rpc_decode_header(task, &xdr)) {
2298 goto out_retry; 2298 case 0:
2299 task->tk_action = rpc_exit_task;
2300 task->tk_status = rpcauth_unwrap_resp(task, &xdr);
2301 dprintk("RPC: %5u %s result %d\n",
2302 task->tk_pid, __func__, task->tk_status);
2299 return; 2303 return;
2300 } 2304 case -EAGAIN:
2301 task->tk_action = rpc_exit_task;
2302
2303 task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
2304 task->tk_msg.rpc_resp);
2305
2306 dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
2307 task->tk_status);
2308 return;
2309out_retry: 2305out_retry:
2310 task->tk_status = 0; 2306 task->tk_status = 0;
2311 /* Note: rpc_decode_header() may have freed the RPC slot */ 2307 /* Note: rpc_decode_header() may have freed the RPC slot */
2312 if (task->tk_rqstp == req) { 2308 if (task->tk_rqstp == req) {
2313 xdr_free_bvec(&req->rq_rcv_buf); 2309 xdr_free_bvec(&req->rq_rcv_buf);
2314 req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; 2310 req->rq_reply_bytes_recvd = 0;
2315 if (task->tk_client->cl_discrtry) 2311 req->rq_rcv_buf.len = 0;
2316 xprt_conditional_disconnect(req->rq_xprt, 2312 if (task->tk_client->cl_discrtry)
2317 req->rq_connect_cookie); 2313 xprt_conditional_disconnect(req->rq_xprt,
2314 req->rq_connect_cookie);
2315 }
2318 } 2316 }
2319} 2317}
2320 2318
@@ -2347,14 +2345,12 @@ out_fail:
2347 return error; 2345 return error;
2348} 2346}
2349 2347
2350static noinline __be32 * 2348static noinline int
2351rpc_decode_header(struct rpc_task *task) 2349rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr)
2352{ 2350{
2353 struct rpc_clnt *clnt = task->tk_client; 2351 struct rpc_clnt *clnt = task->tk_client;
2354 struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
2355 int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
2356 __be32 *p = iov->iov_base;
2357 int error = -EACCES; 2352 int error = -EACCES;
2353 __be32 *p;
2358 2354
2359 /* RFC-1014 says that the representation of XDR data must be a 2355 /* RFC-1014 says that the representation of XDR data must be a
2360 * multiple of four bytes 2356 * multiple of four bytes
@@ -2363,25 +2359,26 @@ rpc_decode_header(struct rpc_task *task)
2363 */ 2359 */
2364 if (task->tk_rqstp->rq_rcv_buf.len & 3) 2360 if (task->tk_rqstp->rq_rcv_buf.len & 3)
2365 goto out_badlen; 2361 goto out_badlen;
2366 if ((len -= 3) < 0)
2367 goto out_unparsable;
2368 2362
2363 p = xdr_inline_decode(xdr, 3 * sizeof(*p));
2364 if (!p)
2365 goto out_unparsable;
2369 p++; /* skip XID */ 2366 p++; /* skip XID */
2370 if (*p++ != rpc_reply) 2367 if (*p++ != rpc_reply)
2371 goto out_unparsable; 2368 goto out_unparsable;
2372 if (*p++ != rpc_msg_accepted) 2369 if (*p++ != rpc_msg_accepted)
2373 goto out_msg_denied; 2370 goto out_msg_denied;
2374 2371
2375 p = rpcauth_checkverf(task, p); 2372 error = rpcauth_checkverf(task, xdr);
2376 if (IS_ERR(p)) 2373 if (error)
2377 goto out_verifier; 2374 goto out_verifier;
2378 2375
2379 len = p - (__be32 *)iov->iov_base - 1; 2376 p = xdr_inline_decode(xdr, sizeof(*p));
2380 if (len < 0) 2377 if (!p)
2381 goto out_unparsable; 2378 goto out_unparsable;
2382 switch (*p++) { 2379 switch (*p) {
2383 case rpc_success: 2380 case rpc_success:
2384 return p; 2381 return 0;
2385 case rpc_prog_unavail: 2382 case rpc_prog_unavail:
2386 trace_rpc__prog_unavail(task); 2383 trace_rpc__prog_unavail(task);
2387 error = -EPFNOSUPPORT; 2384 error = -EPFNOSUPPORT;
@@ -2406,11 +2403,11 @@ out_garbage:
2406 if (task->tk_garb_retry) { 2403 if (task->tk_garb_retry) {
2407 task->tk_garb_retry--; 2404 task->tk_garb_retry--;
2408 task->tk_action = call_encode; 2405 task->tk_action = call_encode;
2409 return ERR_PTR(-EAGAIN); 2406 return -EAGAIN;
2410 } 2407 }
2411out_err: 2408out_err:
2412 rpc_exit(task, error); 2409 rpc_exit(task, error);
2413 return ERR_PTR(error); 2410 return error;
2414 2411
2415out_badlen: 2412out_badlen:
2416 trace_rpc__unparsable(task); 2413 trace_rpc__unparsable(task);
@@ -2424,10 +2421,12 @@ out_unparsable:
2424 2421
2425out_verifier: 2422out_verifier:
2426 trace_rpc_bad_verifier(task); 2423 trace_rpc_bad_verifier(task);
2427 error = PTR_ERR(p);
2428 goto out_garbage; 2424 goto out_garbage;
2429 2425
2430out_msg_denied: 2426out_msg_denied:
2427 p = xdr_inline_decode(xdr, sizeof(*p));
2428 if (!p)
2429 goto out_unparsable;
2431 switch (*p++) { 2430 switch (*p++) {
2432 case rpc_auth_error: 2431 case rpc_auth_error:
2433 break; 2432 break;
@@ -2441,6 +2440,9 @@ out_msg_denied:
2441 goto out_err; 2440 goto out_err;
2442 } 2441 }
2443 2442
2443 p = xdr_inline_decode(xdr, sizeof(*p));
2444 if (!p)
2445 goto out_unparsable;
2444 switch (*p++) { 2446 switch (*p++) {
2445 case rpc_autherr_rejectedcred: 2447 case rpc_autherr_rejectedcred:
2446 case rpc_autherr_rejectedverf: 2448 case rpc_autherr_rejectedverf:
@@ -2454,7 +2456,7 @@ out_msg_denied:
2454 /* Ensure we obtain a new XID! */ 2456 /* Ensure we obtain a new XID! */
2455 xprt_release(task); 2457 xprt_release(task);
2456 task->tk_action = call_reserve; 2458 task->tk_action = call_reserve;
2457 return ERR_PTR(-EAGAIN); 2459 return -EAGAIN;
2458 case rpc_autherr_badcred: 2460 case rpc_autherr_badcred:
2459 case rpc_autherr_badverf: 2461 case rpc_autherr_badverf:
2460 /* possibly garbled cred/verf? */ 2462 /* possibly garbled cred/verf? */
@@ -2463,7 +2465,7 @@ out_msg_denied:
2463 task->tk_garb_retry--; 2465 task->tk_garb_retry--;
2464 trace_rpc__bad_creds(task); 2466 trace_rpc__bad_creds(task);
2465 task->tk_action = call_encode; 2467 task->tk_action = call_encode;
2466 return ERR_PTR(-EAGAIN); 2468 return -EAGAIN;
2467 case rpc_autherr_tooweak: 2469 case rpc_autherr_tooweak:
2468 trace_rpc__auth_tooweak(task); 2470 trace_rpc__auth_tooweak(task);
2469 pr_warn("RPC: server %s requires stronger authentication.\n", 2471 pr_warn("RPC: server %s requires stronger authentication.\n",