Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Use struct xdr_stream when decoding RPC Reply header

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>

authored by

Chuck Lever and committed by
Anna Schumaker
a0584ee9 7f5667a5

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