Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759304Ab0G3SwX (ORCPT ); Fri, 30 Jul 2010 14:52:23 -0400 Received: from kroah.org ([198.145.64.141]:35625 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759363Ab0G3ReW (ORCPT ); Fri, 30 Jul 2010 13:34:22 -0400 X-Mailbox-Line: From gregkh@clark.site Fri Jul 30 10:31:05 2010 Message-Id: <20100730173105.833469906@clark.site> User-Agent: quilt/0.48-11.2 Date: Fri, 30 Jul 2010 10:29:59 -0700 From: Greg KH To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: stable-review@kernel.org, torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Trond Myklebust Subject: [034/140] SUNRPC: Fix a re-entrancy bug in xs_tcp_read_calldir() In-Reply-To: <20100730173205.GA22581@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3559 Lines: 109 2.6.33-stable review patch. If anyone has any objections, please let us know. ------------------ From: Trond Myklebust commit b76ce56192bcf618013fb9aecd83488cffd645cc upstream. If the attempt to read the calldir fails, then instead of storing the read bytes, we currently discard them. This leads to a garbage final result when upon re-entry to the same routine, we read the remaining bytes. Fixes the regression in bugzilla number 16213. Please see https://bugzilla.kernel.org/show_bug.cgi?id=16213 Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -224,7 +224,8 @@ struct sock_xprt { * State of TCP reply receive */ __be32 tcp_fraghdr, - tcp_xid; + tcp_xid, + tcp_calldir; u32 tcp_offset, tcp_reclen; @@ -947,7 +948,7 @@ static inline void xs_tcp_read_calldir(s { size_t len, used; u32 offset; - __be32 calldir; + char *p; /* * We want transport->tcp_offset to be 8 at the end of this routine @@ -956,26 +957,33 @@ static inline void xs_tcp_read_calldir(s * transport->tcp_offset is 4 (after having already read the xid). */ offset = transport->tcp_offset - sizeof(transport->tcp_xid); - len = sizeof(calldir) - offset; + len = sizeof(transport->tcp_calldir) - offset; dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len); - used = xdr_skb_read_bits(desc, &calldir, len); + p = ((char *) &transport->tcp_calldir) + offset; + used = xdr_skb_read_bits(desc, p, len); transport->tcp_offset += used; if (used != len) return; transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR; - transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; - transport->tcp_flags |= TCP_RCV_COPY_DATA; /* * We don't yet have the XDR buffer, so we will write the calldir * out after we get the buffer from the 'struct rpc_rqst' */ - if (ntohl(calldir) == RPC_REPLY) + switch (ntohl(transport->tcp_calldir)) { + case RPC_REPLY: + transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; + transport->tcp_flags |= TCP_RCV_COPY_DATA; transport->tcp_flags |= TCP_RPC_REPLY; - else + break; + case RPC_CALL: + transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; + transport->tcp_flags |= TCP_RCV_COPY_DATA; transport->tcp_flags &= ~TCP_RPC_REPLY; - dprintk("RPC: reading %s CALL/REPLY flag %08x\n", - (transport->tcp_flags & TCP_RPC_REPLY) ? - "reply for" : "request with", calldir); + break; + default: + dprintk("RPC: invalid request message type\n"); + xprt_force_disconnect(&transport->xprt); + } xs_tcp_check_fraghdr(transport); } @@ -995,12 +1003,10 @@ static inline void xs_tcp_read_common(st /* * Save the RPC direction in the XDR buffer */ - __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ? - htonl(RPC_REPLY) : 0; - memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied, - &calldir, sizeof(calldir)); - transport->tcp_copied += sizeof(calldir); + &transport->tcp_calldir, + sizeof(transport->tcp_calldir)); + transport->tcp_copied += sizeof(transport->tcp_calldir); transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR; } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/