aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2019-02-11 11:24:48 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2019-02-13 13:45:17 -0500
commite8680a24a269bd6dcb533f4e4a5faba9ae58925c (patch)
tree04b8b8e697090b86f314c5ae1e024122c240d3a4
parentfe9a270519c72bccb3af524db7ea6c7b67700d50 (diff)
SUNRPC: Use struct xdr_stream when constructing RPC Call header
Modernize and harden the code path that constructs each RPC Call message. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--include/linux/sunrpc/auth.h15
-rw-r--r--include/linux/sunrpc/xdr.h6
-rw-r--r--include/trace/events/sunrpc.h29
-rw-r--r--net/sunrpc/auth.c56
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c191
-rw-r--r--net/sunrpc/auth_null.c23
-rw-r--r--net/sunrpc/auth_unix.c61
-rw-r--r--net/sunrpc/clnt.c66
8 files changed, 266 insertions, 181 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index eed3cb16ccf1..96e237f8e60b 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -131,11 +131,12 @@ struct rpc_credops {
131 void (*crdestroy)(struct rpc_cred *); 131 void (*crdestroy)(struct rpc_cred *);
132 132
133 int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); 133 int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
134 __be32 * (*crmarshal)(struct rpc_task *, __be32 *); 134 int (*crmarshal)(struct rpc_task *task,
135 struct xdr_stream *xdr);
135 int (*crrefresh)(struct rpc_task *); 136 int (*crrefresh)(struct rpc_task *);
136 __be32 * (*crvalidate)(struct rpc_task *, __be32 *); 137 __be32 * (*crvalidate)(struct rpc_task *, __be32 *);
137 int (*crwrap_req)(struct rpc_task *, kxdreproc_t, 138 int (*crwrap_req)(struct rpc_task *task,
138 void *, __be32 *, void *); 139 struct xdr_stream *xdr);
139 int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t, 140 int (*crunwrap_resp)(struct rpc_task *, kxdrdproc_t,
140 void *, __be32 *, void *); 141 void *, __be32 *, void *);
141 int (*crkey_timeout)(struct rpc_cred *); 142 int (*crkey_timeout)(struct rpc_cred *);
@@ -165,9 +166,13 @@ struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *
165void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); 166void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
166struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); 167struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
167void put_rpccred(struct rpc_cred *); 168void put_rpccred(struct rpc_cred *);
168__be32 * rpcauth_marshcred(struct rpc_task *, __be32 *); 169int rpcauth_marshcred(struct rpc_task *task,
170 struct xdr_stream *xdr);
169__be32 * rpcauth_checkverf(struct rpc_task *, __be32 *); 171__be32 * rpcauth_checkverf(struct rpc_task *, __be32 *);
170int rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp, __be32 *data, void *obj); 172int rpcauth_wrap_req_encode(struct rpc_task *task,
173 struct xdr_stream *xdr);
174int rpcauth_wrap_req(struct rpc_task *task,
175 struct xdr_stream *xdr);
171int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj); 176int rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp, __be32 *data, void *obj);
172bool rpcauth_xmit_need_reencode(struct rpc_task *task); 177bool rpcauth_xmit_need_reencode(struct rpc_task *task);
173int rpcauth_refreshcred(struct rpc_task *); 178int rpcauth_refreshcred(struct rpc_task *);
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 787939d13643..6df9ac1ca471 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -87,6 +87,12 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
87#define xdr_one cpu_to_be32(1) 87#define xdr_one cpu_to_be32(1)
88#define xdr_two cpu_to_be32(2) 88#define xdr_two cpu_to_be32(2)
89 89
90#define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
91#define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
92#define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)
93
94#define rpc_call cpu_to_be32(RPC_CALL)
95
90#define rpc_success cpu_to_be32(RPC_SUCCESS) 96#define rpc_success cpu_to_be32(RPC_SUCCESS)
91#define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL) 97#define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL)
92#define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH) 98#define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH)
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index 627650800676..2b3f9d139e75 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -213,6 +213,35 @@ DECLARE_EVENT_CLASS(rpc_task_queued,
213DEFINE_RPC_QUEUED_EVENT(sleep); 213DEFINE_RPC_QUEUED_EVENT(sleep);
214DEFINE_RPC_QUEUED_EVENT(wakeup); 214DEFINE_RPC_QUEUED_EVENT(wakeup);
215 215
216DECLARE_EVENT_CLASS(rpc_failure,
217
218 TP_PROTO(const struct rpc_task *task),
219
220 TP_ARGS(task),
221
222 TP_STRUCT__entry(
223 __field(unsigned int, task_id)
224 __field(unsigned int, client_id)
225 ),
226
227 TP_fast_assign(
228 __entry->task_id = task->tk_pid;
229 __entry->client_id = task->tk_client->cl_clid;
230 ),
231
232 TP_printk("task:%u@%u",
233 __entry->task_id, __entry->client_id)
234);
235
236#define DEFINE_RPC_FAILURE(name) \
237 DEFINE_EVENT(rpc_failure, rpc_bad_##name, \
238 TP_PROTO( \
239 const struct rpc_task *task \
240 ), \
241 TP_ARGS(task))
242
243DEFINE_RPC_FAILURE(callhdr);
244
216TRACE_EVENT(rpc_stats_latency, 245TRACE_EVENT(rpc_stats_latency,
217 246
218 TP_PROTO( 247 TP_PROTO(
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 275e84e817b7..add2135d9b01 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -756,12 +756,21 @@ destroy:
756} 756}
757EXPORT_SYMBOL_GPL(put_rpccred); 757EXPORT_SYMBOL_GPL(put_rpccred);
758 758
759__be32 * 759/**
760rpcauth_marshcred(struct rpc_task *task, __be32 *p) 760 * rpcauth_marshcred - Append RPC credential to end of @xdr
761 * @task: controlling RPC task
762 * @xdr: xdr_stream containing initial portion of RPC Call header
763 *
764 * On success, an appropriate verifier is added to @xdr, @xdr is
765 * updated to point past the verifier, and zero is returned.
766 * Otherwise, @xdr is in an undefined state and a negative errno
767 * is returned.
768 */
769int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr)
761{ 770{
762 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 771 const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
763 772
764 return cred->cr_ops->crmarshal(task, p); 773 return ops->crmarshal(task, xdr);
765} 774}
766 775
767__be32 * 776__be32 *
@@ -772,26 +781,37 @@ rpcauth_checkverf(struct rpc_task *task, __be32 *p)
772 return cred->cr_ops->crvalidate(task, p); 781 return cred->cr_ops->crvalidate(task, p);
773} 782}
774 783
775static void rpcauth_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, 784/**
776 __be32 *data, void *obj) 785 * rpcauth_wrap_req_encode - XDR encode the RPC procedure
786 * @task: controlling RPC task
787 * @xdr: stream where on-the-wire bytes are to be marshalled
788 *
789 * On success, @xdr contains the encoded and wrapped message.
790 * Otherwise, @xdr is in an undefined state.
791 */
792int rpcauth_wrap_req_encode(struct rpc_task *task, struct xdr_stream *xdr)
777{ 793{
778 struct xdr_stream xdr; 794 kxdreproc_t encode = task->tk_msg.rpc_proc->p_encode;
779 795
780 xdr_init_encode(&xdr, &rqstp->rq_snd_buf, data, rqstp); 796 encode(task->tk_rqstp, xdr, task->tk_msg.rpc_argp);
781 encode(rqstp, &xdr, obj); 797 return 0;
782} 798}
799EXPORT_SYMBOL_GPL(rpcauth_wrap_req_encode);
783 800
784int 801/**
785rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp, 802 * rpcauth_wrap_req - XDR encode and wrap the RPC procedure
786 __be32 *data, void *obj) 803 * @task: controlling RPC task
804 * @xdr: stream where on-the-wire bytes are to be marshalled
805 *
806 * On success, @xdr contains the encoded and wrapped message,
807 * and zero is returned. Otherwise, @xdr is in an undefined
808 * state and a negative errno is returned.
809 */
810int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
787{ 811{
788 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 812 const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
789 813
790 if (cred->cr_ops->crwrap_req) 814 return ops->crwrap_req(task, xdr);
791 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
792 /* By default, we encode the arguments normally. */
793 rpcauth_wrap_req_encode(encode, rqstp, data, obj);
794 return 0;
795} 815}
796 816
797static int 817static int
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4b52e2b11c58..b333b1bdad45 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1526,18 +1526,20 @@ out:
1526} 1526}
1527 1527
1528/* 1528/*
1529* Marshal credentials. 1529 * Marshal credentials.
1530* Maybe we should keep a cached credential for performance reasons. 1530 *
1531*/ 1531 * The expensive part is computing the verifier. We can't cache a
1532static __be32 * 1532 * pre-computed version of the verifier because the seqno, which
1533gss_marshal(struct rpc_task *task, __be32 *p) 1533 * is different every time, is included in the MIC.
1534 */
1535static int gss_marshal(struct rpc_task *task, struct xdr_stream *xdr)
1534{ 1536{
1535 struct rpc_rqst *req = task->tk_rqstp; 1537 struct rpc_rqst *req = task->tk_rqstp;
1536 struct rpc_cred *cred = req->rq_cred; 1538 struct rpc_cred *cred = req->rq_cred;
1537 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 1539 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
1538 gc_base); 1540 gc_base);
1539 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 1541 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1540 __be32 *cred_len; 1542 __be32 *p, *cred_len;
1541 u32 maj_stat = 0; 1543 u32 maj_stat = 0;
1542 struct xdr_netobj mic; 1544 struct xdr_netobj mic;
1543 struct kvec iov; 1545 struct kvec iov;
@@ -1545,7 +1547,13 @@ gss_marshal(struct rpc_task *task, __be32 *p)
1545 1547
1546 dprintk("RPC: %5u %s\n", task->tk_pid, __func__); 1548 dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
1547 1549
1548 *p++ = htonl(RPC_AUTH_GSS); 1550 /* Credential */
1551
1552 p = xdr_reserve_space(xdr, 7 * sizeof(*p) +
1553 ctx->gc_wire_ctx.len);
1554 if (!p)
1555 goto out_put_ctx;
1556 *p++ = rpc_auth_gss;
1549 cred_len = p++; 1557 cred_len = p++;
1550 1558
1551 spin_lock(&ctx->gc_seq_lock); 1559 spin_lock(&ctx->gc_seq_lock);
@@ -1554,12 +1562,14 @@ gss_marshal(struct rpc_task *task, __be32 *p)
1554 if (req->rq_seqno == MAXSEQ) 1562 if (req->rq_seqno == MAXSEQ)
1555 goto out_expired; 1563 goto out_expired;
1556 1564
1557 *p++ = htonl((u32) RPC_GSS_VERSION); 1565 *p++ = cpu_to_be32(RPC_GSS_VERSION);
1558 *p++ = htonl((u32) ctx->gc_proc); 1566 *p++ = cpu_to_be32(ctx->gc_proc);
1559 *p++ = htonl((u32) req->rq_seqno); 1567 *p++ = cpu_to_be32(req->rq_seqno);
1560 *p++ = htonl((u32) gss_cred->gc_service); 1568 *p++ = cpu_to_be32(gss_cred->gc_service);
1561 p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); 1569 p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
1562 *cred_len = htonl((p - (cred_len + 1)) << 2); 1570 *cred_len = cpu_to_be32((p - (cred_len + 1)) << 2);
1571
1572 /* Verifier */
1563 1573
1564 /* We compute the checksum for the verifier over the xdr-encoded bytes 1574 /* We compute the checksum for the verifier over the xdr-encoded bytes
1565 * starting with the xid and ending at the end of the credential: */ 1575 * starting with the xid and ending at the end of the credential: */
@@ -1567,27 +1577,27 @@ gss_marshal(struct rpc_task *task, __be32 *p)
1567 iov.iov_len = (u8 *)p - (u8 *)iov.iov_base; 1577 iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
1568 xdr_buf_from_iov(&iov, &verf_buf); 1578 xdr_buf_from_iov(&iov, &verf_buf);
1569 1579
1570 /* set verifier flavor*/ 1580 p = xdr_reserve_space(xdr, sizeof(*p));
1571 *p++ = htonl(RPC_AUTH_GSS); 1581 if (!p)
1572 1582 goto out_put_ctx;
1583 *p++ = rpc_auth_gss;
1573 mic.data = (u8 *)(p + 1); 1584 mic.data = (u8 *)(p + 1);
1574 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 1585 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
1575 if (maj_stat == GSS_S_CONTEXT_EXPIRED) { 1586 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1576 goto out_expired; 1587 goto out_expired;
1577 } else if (maj_stat != 0) { 1588 else if (maj_stat != 0)
1578 pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); 1589 goto out_put_ctx;
1579 task->tk_status = -EIO; 1590 if (xdr_stream_encode_opaque_inline(xdr, (void **)&p, mic.len) < 0)
1580 goto out_put_ctx; 1591 goto out_put_ctx;
1581 }
1582 p = xdr_encode_opaque(p, NULL, mic.len);
1583 gss_put_ctx(ctx); 1592 gss_put_ctx(ctx);
1584 return p; 1593 return 0;
1585out_expired: 1594out_expired:
1595 gss_put_ctx(ctx);
1586 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1596 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1587 task->tk_status = -EKEYEXPIRED; 1597 return -EKEYEXPIRED;
1588out_put_ctx: 1598out_put_ctx:
1589 gss_put_ctx(ctx); 1599 gss_put_ctx(ctx);
1590 return NULL; 1600 return -EMSGSIZE;
1591} 1601}
1592 1602
1593static int gss_renew_cred(struct rpc_task *task) 1603static int gss_renew_cred(struct rpc_task *task)
@@ -1716,61 +1726,45 @@ out_bad:
1716 return ret; 1726 return ret;
1717} 1727}
1718 1728
1719static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, 1729static int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1720 __be32 *p, void *obj) 1730 struct rpc_task *task, struct xdr_stream *xdr)
1721{
1722 struct xdr_stream xdr;
1723
1724 xdr_init_encode(&xdr, &rqstp->rq_snd_buf, p, rqstp);
1725 encode(rqstp, &xdr, obj);
1726}
1727
1728static inline int
1729gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1730 kxdreproc_t encode, struct rpc_rqst *rqstp,
1731 __be32 *p, void *obj)
1732{ 1731{
1733 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; 1732 struct rpc_rqst *rqstp = task->tk_rqstp;
1734 struct xdr_buf integ_buf; 1733 struct xdr_buf integ_buf, *snd_buf = &rqstp->rq_snd_buf;
1735 __be32 *integ_len = NULL;
1736 struct xdr_netobj mic; 1734 struct xdr_netobj mic;
1737 u32 offset; 1735 __be32 *p, *integ_len;
1738 __be32 *q; 1736 u32 offset, maj_stat;
1739 struct kvec *iov;
1740 u32 maj_stat = 0;
1741 int status = -EIO;
1742 1737
1738 p = xdr_reserve_space(xdr, 2 * sizeof(*p));
1739 if (!p)
1740 goto wrap_failed;
1743 integ_len = p++; 1741 integ_len = p++;
1744 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 1742 *p = cpu_to_be32(rqstp->rq_seqno);
1745 *p++ = htonl(rqstp->rq_seqno);
1746 1743
1747 gss_wrap_req_encode(encode, rqstp, p, obj); 1744 if (rpcauth_wrap_req_encode(task, xdr))
1745 goto wrap_failed;
1748 1746
1747 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
1749 if (xdr_buf_subsegment(snd_buf, &integ_buf, 1748 if (xdr_buf_subsegment(snd_buf, &integ_buf,
1750 offset, snd_buf->len - offset)) 1749 offset, snd_buf->len - offset))
1751 return status; 1750 goto wrap_failed;
1752 *integ_len = htonl(integ_buf.len); 1751 *integ_len = cpu_to_be32(integ_buf.len);
1753 1752
1754 /* guess whether we're in the head or the tail: */ 1753 p = xdr_reserve_space(xdr, 0);
1755 if (snd_buf->page_len || snd_buf->tail[0].iov_len) 1754 if (!p)
1756 iov = snd_buf->tail; 1755 goto wrap_failed;
1757 else
1758 iov = snd_buf->head;
1759 p = iov->iov_base + iov->iov_len;
1760 mic.data = (u8 *)(p + 1); 1756 mic.data = (u8 *)(p + 1);
1761
1762 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 1757 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
1763 status = -EIO; /* XXX? */
1764 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1758 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1765 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1759 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1766 else if (maj_stat) 1760 else if (maj_stat)
1767 return status; 1761 goto wrap_failed;
1768 q = xdr_encode_opaque(p, NULL, mic.len); 1762 /* Check that the trailing MIC fit in the buffer, after the fact */
1769 1763 if (xdr_stream_encode_opaque_inline(xdr, (void **)&p, mic.len) < 0)
1770 offset = (u8 *)q - (u8 *)p; 1764 goto wrap_failed;
1771 iov->iov_len += offset;
1772 snd_buf->len += offset;
1773 return 0; 1765 return 0;
1766wrap_failed:
1767 return -EMSGSIZE;
1774} 1768}
1775 1769
1776static void 1770static void
@@ -1821,61 +1815,63 @@ out:
1821 return -EAGAIN; 1815 return -EAGAIN;
1822} 1816}
1823 1817
1824static inline int 1818static int gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1825gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1819 struct rpc_task *task, struct xdr_stream *xdr)
1826 kxdreproc_t encode, struct rpc_rqst *rqstp,
1827 __be32 *p, void *obj)
1828{ 1820{
1821 struct rpc_rqst *rqstp = task->tk_rqstp;
1829 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; 1822 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
1830 u32 offset; 1823 u32 pad, offset, maj_stat;
1831 u32 maj_stat;
1832 int status; 1824 int status;
1833 __be32 *opaque_len; 1825 __be32 *p, *opaque_len;
1834 struct page **inpages; 1826 struct page **inpages;
1835 int first; 1827 int first;
1836 int pad;
1837 struct kvec *iov; 1828 struct kvec *iov;
1838 char *tmp;
1839 1829
1830 status = -EIO;
1831 p = xdr_reserve_space(xdr, 2 * sizeof(*p));
1832 if (!p)
1833 goto wrap_failed;
1840 opaque_len = p++; 1834 opaque_len = p++;
1841 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 1835 *p = cpu_to_be32(rqstp->rq_seqno);
1842 *p++ = htonl(rqstp->rq_seqno);
1843 1836
1844 gss_wrap_req_encode(encode, rqstp, p, obj); 1837 if (rpcauth_wrap_req_encode(task, xdr))
1838 goto wrap_failed;
1845 1839
1846 status = alloc_enc_pages(rqstp); 1840 status = alloc_enc_pages(rqstp);
1847 if (status) 1841 if (unlikely(status))
1848 return status; 1842 goto wrap_failed;
1849 first = snd_buf->page_base >> PAGE_SHIFT; 1843 first = snd_buf->page_base >> PAGE_SHIFT;
1850 inpages = snd_buf->pages + first; 1844 inpages = snd_buf->pages + first;
1851 snd_buf->pages = rqstp->rq_enc_pages; 1845 snd_buf->pages = rqstp->rq_enc_pages;
1852 snd_buf->page_base -= first << PAGE_SHIFT; 1846 snd_buf->page_base -= first << PAGE_SHIFT;
1853 /* 1847 /*
1854 * Give the tail its own page, in case we need extra space in the 1848 * Move the tail into its own page, in case gss_wrap needs
1855 * head when wrapping: 1849 * more space in the head when wrapping.
1856 * 1850 *
1857 * call_allocate() allocates twice the slack space required 1851 * Still... Why can't gss_wrap just slide the tail down?
1858 * by the authentication flavor to rq_callsize.
1859 * For GSS, slack is GSS_CRED_SLACK.
1860 */ 1852 */
1861 if (snd_buf->page_len || snd_buf->tail[0].iov_len) { 1853 if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
1854 char *tmp;
1855
1862 tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]); 1856 tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
1863 memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len); 1857 memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
1864 snd_buf->tail[0].iov_base = tmp; 1858 snd_buf->tail[0].iov_base = tmp;
1865 } 1859 }
1860 status = -EIO;
1861 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
1866 maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); 1862 maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
1867 /* slack space should prevent this ever happening: */ 1863 /* slack space should prevent this ever happening: */
1868 BUG_ON(snd_buf->len > snd_buf->buflen); 1864 if (unlikely(snd_buf->len > snd_buf->buflen))
1869 status = -EIO; 1865 goto wrap_failed;
1870 /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was 1866 /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
1871 * done anyway, so it's safe to put the request on the wire: */ 1867 * done anyway, so it's safe to put the request on the wire: */
1872 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1868 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1873 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 1869 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1874 else if (maj_stat) 1870 else if (maj_stat)
1875 return status; 1871 goto wrap_failed;
1876 1872
1877 *opaque_len = htonl(snd_buf->len - offset); 1873 *opaque_len = cpu_to_be32(snd_buf->len - offset);
1878 /* guess whether we're in the head or the tail: */ 1874 /* guess whether the pad goes into the head or the tail: */
1879 if (snd_buf->page_len || snd_buf->tail[0].iov_len) 1875 if (snd_buf->page_len || snd_buf->tail[0].iov_len)
1880 iov = snd_buf->tail; 1876 iov = snd_buf->tail;
1881 else 1877 else
@@ -1887,37 +1883,36 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1887 snd_buf->len += pad; 1883 snd_buf->len += pad;
1888 1884
1889 return 0; 1885 return 0;
1886wrap_failed:
1887 return status;
1890} 1888}
1891 1889
1892static int 1890static int gss_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
1893gss_wrap_req(struct rpc_task *task,
1894 kxdreproc_t encode, void *rqstp, __be32 *p, void *obj)
1895{ 1891{
1896 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 1892 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
1897 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 1893 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
1898 gc_base); 1894 gc_base);
1899 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 1895 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1900 int status = -EIO; 1896 int status;
1901 1897
1902 dprintk("RPC: %5u %s\n", task->tk_pid, __func__); 1898 dprintk("RPC: %5u %s\n", task->tk_pid, __func__);
1899 status = -EIO;
1903 if (ctx->gc_proc != RPC_GSS_PROC_DATA) { 1900 if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
1904 /* The spec seems a little ambiguous here, but I think that not 1901 /* The spec seems a little ambiguous here, but I think that not
1905 * wrapping context destruction requests makes the most sense. 1902 * wrapping context destruction requests makes the most sense.
1906 */ 1903 */
1907 gss_wrap_req_encode(encode, rqstp, p, obj); 1904 status = rpcauth_wrap_req_encode(task, xdr);
1908 status = 0;
1909 goto out; 1905 goto out;
1910 } 1906 }
1911 switch (gss_cred->gc_service) { 1907 switch (gss_cred->gc_service) {
1912 case RPC_GSS_SVC_NONE: 1908 case RPC_GSS_SVC_NONE:
1913 gss_wrap_req_encode(encode, rqstp, p, obj); 1909 status = rpcauth_wrap_req_encode(task, xdr);
1914 status = 0;
1915 break; 1910 break;
1916 case RPC_GSS_SVC_INTEGRITY: 1911 case RPC_GSS_SVC_INTEGRITY:
1917 status = gss_wrap_req_integ(cred, ctx, encode, rqstp, p, obj); 1912 status = gss_wrap_req_integ(cred, ctx, task, xdr);
1918 break; 1913 break;
1919 case RPC_GSS_SVC_PRIVACY: 1914 case RPC_GSS_SVC_PRIVACY:
1920 status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj); 1915 status = gss_wrap_req_priv(cred, ctx, task, xdr);
1921 break; 1916 break;
1922 } 1917 }
1923out: 1918out:
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index d0ceac57c06e..797f8472c21b 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -59,15 +59,21 @@ nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
59/* 59/*
60 * Marshal credential. 60 * Marshal credential.
61 */ 61 */
62static __be32 * 62static int
63nul_marshal(struct rpc_task *task, __be32 *p) 63nul_marshal(struct rpc_task *task, struct xdr_stream *xdr)
64{ 64{
65 *p++ = htonl(RPC_AUTH_NULL); 65 __be32 *p;
66 *p++ = 0; 66
67 *p++ = htonl(RPC_AUTH_NULL); 67 p = xdr_reserve_space(xdr, 4 * sizeof(*p));
68 *p++ = 0; 68 if (!p)
69 69 return -EMSGSIZE;
70 return p; 70 /* Credential */
71 *p++ = rpc_auth_null;
72 *p++ = xdr_zero;
73 /* Verifier */
74 *p++ = rpc_auth_null;
75 *p = xdr_zero;
76 return 0;
71} 77}
72 78
73/* 79/*
@@ -125,6 +131,7 @@ const struct rpc_credops null_credops = {
125 .crdestroy = nul_destroy_cred, 131 .crdestroy = nul_destroy_cred,
126 .crmatch = nul_match, 132 .crmatch = nul_match,
127 .crmarshal = nul_marshal, 133 .crmarshal = nul_marshal,
134 .crwrap_req = rpcauth_wrap_req_encode,
128 .crrefresh = nul_refresh, 135 .crrefresh = nul_refresh,
129 .crvalidate = nul_validate, 136 .crvalidate = nul_validate,
130}; 137};
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index fc8a59134640..1d5b7ed9c6f7 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -99,37 +99,55 @@ unx_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
99 * Marshal credentials. 99 * Marshal credentials.
100 * Maybe we should keep a cached credential for performance reasons. 100 * Maybe we should keep a cached credential for performance reasons.
101 */ 101 */
102static __be32 * 102static int
103unx_marshal(struct rpc_task *task, __be32 *p) 103unx_marshal(struct rpc_task *task, struct xdr_stream *xdr)
104{ 104{
105 struct rpc_clnt *clnt = task->tk_client; 105 struct rpc_clnt *clnt = task->tk_client;
106 struct rpc_cred *cred = task->tk_rqstp->rq_cred; 106 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
107 __be32 *base, *hold; 107 __be32 *p, *cred_len, *gidarr_len;
108 int i; 108 int i;
109 struct group_info *gi = cred->cr_cred->group_info; 109 struct group_info *gi = cred->cr_cred->group_info;
110 110
111 *p++ = htonl(RPC_AUTH_UNIX); 111 /* Credential */
112 base = p++; 112
113 *p++ = htonl(jiffies/HZ); 113 p = xdr_reserve_space(xdr, 3 * sizeof(*p));
114 114 if (!p)
115 /* 115 goto marshal_failed;
116 * Copy the UTS nodename captured when the client was created. 116 *p++ = rpc_auth_unix;
117 */ 117 cred_len = p++;
118 p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); 118 *p++ = xdr_zero; /* stamp */
119 119 if (xdr_stream_encode_opaque(xdr, clnt->cl_nodename,
120 *p++ = htonl((u32) from_kuid(&init_user_ns, cred->cr_cred->fsuid)); 120 clnt->cl_nodelen) < 0)
121 *p++ = htonl((u32) from_kgid(&init_user_ns, cred->cr_cred->fsgid)); 121 goto marshal_failed;
122 hold = p++; 122 p = xdr_reserve_space(xdr, 3 * sizeof(*p));
123 if (!p)
124 goto marshal_failed;
125 *p++ = cpu_to_be32(from_kuid(&init_user_ns, cred->cr_cred->fsuid));
126 *p++ = cpu_to_be32(from_kgid(&init_user_ns, cred->cr_cred->fsgid));
127
128 gidarr_len = p++;
123 if (gi) 129 if (gi)
124 for (i = 0; i < UNX_NGROUPS && i < gi->ngroups; i++) 130 for (i = 0; i < UNX_NGROUPS && i < gi->ngroups; i++)
125 *p++ = htonl((u32) from_kgid(&init_user_ns, gi->gid[i])); 131 *p++ = cpu_to_be32(from_kgid(&init_user_ns,
126 *hold = htonl(p - hold - 1); /* gid array length */ 132 gi->gid[i]));
127 *base = htonl((p - base - 1) << 2); /* cred length */ 133 *gidarr_len = cpu_to_be32(p - gidarr_len - 1);
134 *cred_len = cpu_to_be32((p - cred_len - 1) << 2);
135 p = xdr_reserve_space(xdr, (p - gidarr_len - 1) << 2);
136 if (!p)
137 goto marshal_failed;
138
139 /* Verifier */
140
141 p = xdr_reserve_space(xdr, 2 * sizeof(*p));
142 if (!p)
143 goto marshal_failed;
144 *p++ = rpc_auth_null;
145 *p = xdr_zero;
128 146
129 *p++ = htonl(RPC_AUTH_NULL); 147 return 0;
130 *p++ = htonl(0);
131 148
132 return p; 149marshal_failed:
150 return -EMSGSIZE;
133} 151}
134 152
135/* 153/*
@@ -202,6 +220,7 @@ const struct rpc_credops unix_credops = {
202 .crdestroy = unx_destroy_cred, 220 .crdestroy = unx_destroy_cred,
203 .crmatch = unx_match, 221 .crmatch = unx_match,
204 .crmarshal = unx_marshal, 222 .crmarshal = unx_marshal,
223 .crwrap_req = rpcauth_wrap_req_encode,
205 .crrefresh = unx_refresh, 224 .crrefresh = unx_refresh,
206 .crvalidate = unx_validate, 225 .crvalidate = unx_validate,
207}; 226};
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index c4203f6138ef..d6750b7f169a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -77,7 +77,8 @@ static void call_timeout(struct rpc_task *task);
77static void call_connect(struct rpc_task *task); 77static void call_connect(struct rpc_task *task);
78static void call_connect_status(struct rpc_task *task); 78static void call_connect_status(struct rpc_task *task);
79 79
80static __be32 *rpc_encode_header(struct rpc_task *task); 80static int rpc_encode_header(struct rpc_task *task,
81 struct xdr_stream *xdr);
81static __be32 *rpc_verify_header(struct rpc_task *task); 82static __be32 *rpc_verify_header(struct rpc_task *task);
82static int rpc_ping(struct rpc_clnt *clnt); 83static int rpc_ping(struct rpc_clnt *clnt);
83 84
@@ -1728,10 +1729,7 @@ static void
1728rpc_xdr_encode(struct rpc_task *task) 1729rpc_xdr_encode(struct rpc_task *task)
1729{ 1730{
1730 struct rpc_rqst *req = task->tk_rqstp; 1731 struct rpc_rqst *req = task->tk_rqstp;
1731 kxdreproc_t encode; 1732 struct xdr_stream xdr;
1732 __be32 *p;
1733
1734 dprint_status(task);
1735 1733
1736 xdr_buf_init(&req->rq_snd_buf, 1734 xdr_buf_init(&req->rq_snd_buf,
1737 req->rq_buffer, 1735 req->rq_buffer,
@@ -1740,18 +1738,13 @@ rpc_xdr_encode(struct rpc_task *task)
1740 req->rq_rbuffer, 1738 req->rq_rbuffer,
1741 req->rq_rcvsize); 1739 req->rq_rcvsize);
1742 1740
1743 p = rpc_encode_header(task); 1741 req->rq_snd_buf.head[0].iov_len = 0;
1744 if (p == NULL) 1742 xdr_init_encode(&xdr, &req->rq_snd_buf,
1743 req->rq_snd_buf.head[0].iov_base, req);
1744 if (rpc_encode_header(task, &xdr))
1745 return; 1745 return;
1746 1746
1747 encode = task->tk_msg.rpc_proc->p_encode; 1747 task->tk_status = rpcauth_wrap_req(task, &xdr);
1748 if (encode == NULL)
1749 return;
1750
1751 task->tk_status = rpcauth_wrap_req(task, encode, req, p,
1752 task->tk_msg.rpc_argp);
1753 if (task->tk_status == 0)
1754 xprt_request_prepare(req);
1755} 1748}
1756 1749
1757/* 1750/*
@@ -1762,6 +1755,7 @@ call_encode(struct rpc_task *task)
1762{ 1755{
1763 if (!rpc_task_need_encode(task)) 1756 if (!rpc_task_need_encode(task))
1764 goto out; 1757 goto out;
1758 dprint_status(task);
1765 /* Encode here so that rpcsec_gss can use correct sequence number. */ 1759 /* Encode here so that rpcsec_gss can use correct sequence number. */
1766 rpc_xdr_encode(task); 1760 rpc_xdr_encode(task);
1767 /* Did the encode result in an error condition? */ 1761 /* Did the encode result in an error condition? */
@@ -1779,6 +1773,8 @@ call_encode(struct rpc_task *task)
1779 rpc_exit(task, task->tk_status); 1773 rpc_exit(task, task->tk_status);
1780 } 1774 }
1781 return; 1775 return;
1776 } else {
1777 xprt_request_prepare(task->tk_rqstp);
1782 } 1778 }
1783 1779
1784 /* Add task to reply queue before transmission to avoid races */ 1780 /* Add task to reply queue before transmission to avoid races */
@@ -2322,25 +2318,33 @@ out_retry:
2322 } 2318 }
2323} 2319}
2324 2320
2325static __be32 * 2321static int
2326rpc_encode_header(struct rpc_task *task) 2322rpc_encode_header(struct rpc_task *task, struct xdr_stream *xdr)
2327{ 2323{
2328 struct rpc_clnt *clnt = task->tk_client; 2324 struct rpc_clnt *clnt = task->tk_client;
2329 struct rpc_rqst *req = task->tk_rqstp; 2325 struct rpc_rqst *req = task->tk_rqstp;
2330 __be32 *p = req->rq_svec[0].iov_base; 2326 __be32 *p;
2331 2327 int error;
2332 /* FIXME: check buffer size? */ 2328
2333 2329 error = -EMSGSIZE;
2334 *p++ = req->rq_xid; /* XID */ 2330 p = xdr_reserve_space(xdr, RPC_CALLHDRSIZE << 2);
2335 *p++ = htonl(RPC_CALL); /* CALL */ 2331 if (!p)
2336 *p++ = htonl(RPC_VERSION); /* RPC version */ 2332 goto out_fail;
2337 *p++ = htonl(clnt->cl_prog); /* program number */ 2333 *p++ = req->rq_xid;
2338 *p++ = htonl(clnt->cl_vers); /* program version */ 2334 *p++ = rpc_call;
2339 *p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */ 2335 *p++ = cpu_to_be32(RPC_VERSION);
2340 p = rpcauth_marshcred(task, p); 2336 *p++ = cpu_to_be32(clnt->cl_prog);
2341 if (p) 2337 *p++ = cpu_to_be32(clnt->cl_vers);
2342 req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p); 2338 *p = cpu_to_be32(task->tk_msg.rpc_proc->p_proc);
2343 return p; 2339
2340 error = rpcauth_marshcred(task, xdr);
2341 if (error < 0)
2342 goto out_fail;
2343 return 0;
2344out_fail:
2345 trace_rpc_bad_callhdr(task);
2346 rpc_exit(task, error);
2347 return error;
2344} 2348}
2345 2349
2346static __be32 * 2350static __be32 *