802.15.4: fix various length checks and other issues.
authorGuy Harris <gharris@sonic.net>
Tue, 16 Nov 2021 07:42:04 +0000 (23:42 -0800)
committerGuy Harris <gharris@sonic.net>
Tue, 16 Nov 2021 07:42:04 +0000 (23:42 -0800)
Fix some length checks done before subtracting from a length value to
test whether the length value is < the full amount to be subtracted from
it, not just part of that amount.

Add some such checks where they were needed but not present.

Make some values unsigned if they're never negative.

This should fix some issues detected by undefined-behavior sanitizers.

print-802_15_4.c

index 5687d4556d891b2b780818e4a6ea030171430452..f76831b940d2f410a38abd0a48c6b437de54467f 100644 (file)
@@ -959,7 +959,7 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo,
                                         h_ie_names[element_id], ie_len);
                        }
                }
-               if (caplen < ie_len) {
+               if (caplen < 2 + ie_len) {
                        ND_PRINT("[ERROR: Truncated IE data]");
                        return -1;
                }
@@ -989,7 +989,7 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo,
                if (element_id == 0x7f) {
                        break;
                }
-       } while (caplen > 0);
+       } while (caplen != 0);
        return len;
 }
 
@@ -1282,7 +1282,7 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo,
                                 p_mlme_long_names[sub_id], sub_ie_len);
                }
 
-               if (ie_len < sub_ie_len) {
+               if (ie_len < 2 + sub_ie_len) {
                        ND_PRINT("[ERROR: Truncated IE data]");
                        return;
                }
@@ -1441,7 +1441,7 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo,
                        ND_PRINT("\n\t%s [ length = %d, ",
                                 p_ie_names[group_id], ie_len);
                }
-               if (caplen < ie_len) {
+               if (caplen < 2 + ie_len) {
                        ND_PRINT("[ERROR: Truncated IE data]");
                        return -1;
                }
@@ -1798,7 +1798,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo,
        int len, frame_version, pan_id_comp;
        int frame_type;
        int src_pan, dst_pan, src_addr_len, dst_addr_len;
-       int security_level, miclen = 0;
+       int security_level;
+       u_int miclen = 0;
        int payload_ie_present;
        uint8_t seq;
        uint32_t fcs, crc_check;
@@ -1857,14 +1858,22 @@ ieee802_15_4_std_frames(netdissect_options *ndo,
                }
                if (ndo->ndo_vflag)
                        ND_PRINT("seq suppressed ");
+               if (caplen < 2) {
+                       nd_print_trunc(ndo);
+                       return 0;
+               }
                p += 2;
                caplen -= 2;
        } else {
                seq = GET_U_1(p + 2);
-               p += 3;
-               caplen -= 3;
                if (ndo->ndo_vflag)
                        ND_PRINT("seq %02x ", seq);
+               if (caplen < 3) {
+                       nd_print_trunc(ndo);
+                       return 0;
+               }
+               p += 3;
+               caplen -= 3;
        }
 
        /* See which parts of addresses we have. */
@@ -2048,8 +2057,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo,
        }
 
        /* Remove MIC */
-       if (miclen > 0) {
-               if (caplen < (u_int) miclen) {
+       if (miclen != 0) {
+               if (caplen < miclen) {
                        ND_PRINT("[ERROR: Truncated before MIC]");
                        return 0;
                }
@@ -2086,8 +2095,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo,
        if (ndo->ndo_vflag > 2 && miclen != 0) {
                ND_PRINT("\n\tMIC ");
 
-               for(len = 0; len < miclen; len++) {
-                       ND_PRINT("%02x", GET_U_1(mic_start + len));
+               for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
+                       ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
                }
                ND_PRINT(" ");
        }
@@ -2197,7 +2206,8 @@ ieee802_15_4_mp_frame(netdissect_options *ndo,
 {
        int len, frame_version, pan_id_present;
        int src_addr_len, dst_addr_len;
-       int security_level, miclen = 0;
+       int security_level;
+       u_int miclen = 0;
        int ie_present, payload_ie_present, security_enabled;
        uint8_t seq;
        uint32_t fcs, crc_check;
@@ -2265,14 +2275,22 @@ ieee802_15_4_mp_frame(netdissect_options *ndo,
                /* Check for the sequence number suppression. */
                if (CHECK_BIT(fc, 10)) {
                        /* Sequence number is suppressed, but long version. */
+                       if (caplen < 2) {
+                               nd_print_trunc(ndo);
+                               return 0;
+                       }
                        p += 2;
                        caplen -= 2;
                } else {
                        seq = GET_U_1(p + 2);
-                       p += 3;
-                       caplen -= 3;
                        if (ndo->ndo_vflag)
                                ND_PRINT("seq %02x ", seq);
+                       if (caplen < 3) {
+                               nd_print_trunc(ndo);
+                               return 0;
+                       }
+                       p += 3;
+                       caplen -= 3;
                }
        } else {
                /* Short format of header, but with seq no */
@@ -2361,8 +2379,8 @@ ieee802_15_4_mp_frame(netdissect_options *ndo,
        }
 
        /* Remove MIC */
-       if (miclen > 0) {
-               if (caplen < (u_int) miclen) {
+       if (miclen != 0) {
+               if (caplen < miclen) {
                        ND_PRINT("[ERROR: Truncated before MIC]");
                        return 0;
                }
@@ -2400,8 +2418,8 @@ ieee802_15_4_mp_frame(netdissect_options *ndo,
        if (ndo->ndo_vflag > 2 && miclen != 0) {
                ND_PRINT("\n\tMIC ");
 
-               for(len = 0; len < miclen; len++) {
-                       ND_PRINT("%02x", GET_U_1(mic_start + len));
+               for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
+                       ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
                }
                ND_PRINT(" ");
        }