Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753726AbcDZXNi (ORCPT ); Tue, 26 Apr 2016 19:13:38 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:39567 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752862AbcDZXN1 (ORCPT ); Tue, 26 Apr 2016 19:13:27 -0400 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "J. Bruce Fields" Date: Wed, 27 Apr 2016 01:02:24 +0200 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.2 016/115] nfsd4: fix bad bounds checking In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8426:ae4:c500:9cba:69ae:962d:6167 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2192 Lines: 69 3.2.80-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: "J. Bruce Fields" commit 4aed9c46afb80164401143aa0fdcfe3798baa9d5 upstream. A number of spots in the xdr decoding follow a pattern like n = be32_to_cpup(p++); READ_BUF(n + 4); where n is a u32. The only bounds checking is done in READ_BUF itself, but since it's checking (n + 4), it won't catch cases where n is very large, (u32)(-4) or higher. I'm not sure exactly what the consequences are, but we've seen crashes soon after. Instead, just break these up into two READ_BUF()s. Signed-off-by: J. Bruce Fields [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings --- fs/nfsd/nfs4xdr.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -931,8 +931,9 @@ nfsd4_decode_rename(struct nfsd4_compoun READ_BUF(4); READ32(rename->rn_snamelen); - READ_BUF(rename->rn_snamelen + 4); + READ_BUF(rename->rn_snamelen); SAVEMEM(rename->rn_sname, rename->rn_snamelen); + READ_BUF(4); READ32(rename->rn_tnamelen); READ_BUF(rename->rn_tnamelen); SAVEMEM(rename->rn_tname, rename->rn_tnamelen); @@ -1009,13 +1010,14 @@ nfsd4_decode_setclientid(struct nfsd4_co READ_BUF(8); READ32(setclientid->se_callback_prog); READ32(setclientid->se_callback_netid_len); - - READ_BUF(setclientid->se_callback_netid_len + 4); + READ_BUF(setclientid->se_callback_netid_len); SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); + READ_BUF(4); READ32(setclientid->se_callback_addr_len); - READ_BUF(setclientid->se_callback_addr_len + 4); + READ_BUF(setclientid->se_callback_addr_len); SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); + READ_BUF(4); READ32(setclientid->se_callback_ident); DECODE_TAIL; @@ -1584,8 +1586,9 @@ nfsd4_decode_compound(struct nfsd4_compo */ READ_BUF(4); READ32(argp->taglen); - READ_BUF(argp->taglen + 8); + READ_BUF(argp->taglen); SAVEMEM(argp->tag, argp->taglen); + READ_BUF(8); READ32(argp->minorversion); READ32(argp->opcnt);