Skip to content

Commit

Permalink
CVE-2017-12898/NFS: Fix bounds checking.
Browse files Browse the repository at this point in the history
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 Sep 13, 2017
1 parent 1dcd10a commit 19d25dd
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 6 deletions.
13 changes: 7 additions & 6 deletions print-nfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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)));
Expand Down Expand Up @@ -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]),
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions tests/TESTLIST
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 19d25dd

Please sign in to comment.