Skip to content
Permalink
Browse files

CVE-2017-12898/NFS: Fix bounds checking.

Fix the bounds checking for the NFSv3 WRITE procedure to check whether the
length of the opaque data being written is present in the captured data,
not just whether the byte count is present in the captured data.
furthest forward in the packet, not the item before it.  (This also lets
us eliminate the check for the "stable" argument being present in the
captured data; rewrite the code to print that to make it a bit clearer.)

Check that the entire ar_stat field is present in the capture.

Note that parse_wcc_attr() is called after we've already checked whether
the wcc_data is present.

Check before fetching the "access" part of the NFSv3 ACCESS results.
This fixes a buffer over-read discovered by Kamil Frankowicz.

Include a test for the "check before fetching the "access" part..." fix,
using the capture supplied by the reporter(s).
  • Loading branch information...
guyharris authored and infrastation committed Feb 3, 2017
1 parent 1dcd10a commit 19d25dd8781620cd41bf178a5e2e27fc1cf242d0
Showing with 313 additions and 6 deletions.
  1. +7 −6 print-nfs.c
  2. +1 −0 tests/TESTLIST
  3. +305 −0 tests/nfs-attr-oobr.out
  4. BIN tests/nfs-attr-oobr.pcap
@@ -628,17 +628,15 @@ nfsreq_print_noaddr(netdissect_options *ndo,
if ((dp = parsereq(ndo, rp, length)) != NULL &&
(dp = parsefh(ndo, dp, v3)) != NULL) {
if (v3) {
ND_TCHECK(dp[2]);
ND_TCHECK(dp[4]);
ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64,
EXTRACT_32BITS(&dp[4]),
EXTRACT_32BITS(&dp[2]),
EXTRACT_64BITS(&dp[0])));
if (ndo->ndo_vflag) {
dp += 3;
ND_TCHECK(dp[0]);
ND_PRINT((ndo, " <%s>",
tok2str(nfsv3_writemodes,
NULL, EXTRACT_32BITS(dp))));
NULL, EXTRACT_32BITS(&dp[3]))));
}
} else {
ND_TCHECK(dp[3]);
@@ -1002,11 +1000,11 @@ parserep(netdissect_options *ndo,
* skip past the ar_verf credentials.
*/
dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t);
ND_TCHECK2(dp[0], 0);

/*
* now we can check the ar_stat field
*/
ND_TCHECK(dp[0]);
astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp);
if (astat != SUNRPC_SUCCESS) {
ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat)));
@@ -1243,6 +1241,7 @@ static const uint32_t *
parse_wcc_attr(netdissect_options *ndo,
const uint32_t *dp)
{
/* Our caller has already checked this */
ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0])));
ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u",
EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]),
@@ -1511,8 +1510,10 @@ interp_reply(netdissect_options *ndo,
ND_PRINT((ndo, " attr:"));
if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
break;
if (!er)
if (!er) {
ND_TCHECK(dp[0]);
ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0])));
}
return;

case NFSPROC_READLINK:
@@ -443,6 +443,7 @@ hoobr_pimv1 hoobr_pimv1.pcap hoobr_pimv1.out
hoobr_safeputs hoobr_safeputs.pcap hoobr_safeputs.out
isakmp-rfc3948-oobr isakmp-rfc3948-oobr.pcap isakmp-rfc3948-oobr.out
isoclns-oobr isoclns-oobr.pcap isoclns-oobr.out
nfs-attr-oobr nfs-attr-oobr.pcap nfs-attr-oobr.out

# bad packets from Wilfried Kirsch
slip-bad-direction slip-bad-direction.pcap slip-bad-direction.out -ve

0 comments on commit 19d25dd

Please sign in to comment.
You can’t perform that action at this time.