Commit 4aed9c46 authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd4: fix bad bounds checking

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.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent b7052cd7
...@@ -1072,8 +1072,9 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename ...@@ -1072,8 +1072,9 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename
READ_BUF(4); READ_BUF(4);
rename->rn_snamelen = be32_to_cpup(p++); rename->rn_snamelen = be32_to_cpup(p++);
READ_BUF(rename->rn_snamelen + 4); READ_BUF(rename->rn_snamelen);
SAVEMEM(rename->rn_sname, rename->rn_snamelen); SAVEMEM(rename->rn_sname, rename->rn_snamelen);
READ_BUF(4);
rename->rn_tnamelen = be32_to_cpup(p++); rename->rn_tnamelen = be32_to_cpup(p++);
READ_BUF(rename->rn_tnamelen); READ_BUF(rename->rn_tnamelen);
SAVEMEM(rename->rn_tname, rename->rn_tnamelen); SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
...@@ -1155,13 +1156,14 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient ...@@ -1155,13 +1156,14 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
READ_BUF(8); READ_BUF(8);
setclientid->se_callback_prog = be32_to_cpup(p++); setclientid->se_callback_prog = be32_to_cpup(p++);
setclientid->se_callback_netid_len = be32_to_cpup(p++); setclientid->se_callback_netid_len = be32_to_cpup(p++);
READ_BUF(setclientid->se_callback_netid_len);
READ_BUF(setclientid->se_callback_netid_len + 4);
SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
READ_BUF(4);
setclientid->se_callback_addr_len = be32_to_cpup(p++); setclientid->se_callback_addr_len = be32_to_cpup(p++);
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); SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
READ_BUF(4);
setclientid->se_callback_ident = be32_to_cpup(p++); setclientid->se_callback_ident = be32_to_cpup(p++);
DECODE_TAIL; DECODE_TAIL;
...@@ -1835,8 +1837,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) ...@@ -1835,8 +1837,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
READ_BUF(4); READ_BUF(4);
argp->taglen = be32_to_cpup(p++); argp->taglen = be32_to_cpup(p++);
READ_BUF(argp->taglen + 8); READ_BUF(argp->taglen);
SAVEMEM(argp->tag, argp->taglen); SAVEMEM(argp->tag, argp->taglen);
READ_BUF(8);
argp->minorversion = be32_to_cpup(p++); argp->minorversion = be32_to_cpup(p++);
argp->opcnt = be32_to_cpup(p++); argp->opcnt = be32_to_cpup(p++);
max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2); max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment