]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-rx.c
(for 4.9.3) CVE-2018-14880/OSPFv3: Fix a bounds check
[tcpdump] / print-rx.c
index 322e0c0c56823af38b2fd501dab2b53092650185..bf2af0cb7657b834a0328c34dfca2135fc645a56 100644 (file)
@@ -20,6 +20,9 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
+
+/* \summary: AFS RX printer */
+
 /*
  * This code unmangles RX packets.  RX is the mutant form of RPC that AFS
  * uses to communicate between clients and servers.
 #define        PRSFS_ADMINISTER        64 /* Change ACL's */
 
 struct rx_header {
-       uint32_t epoch;
-       uint32_t cid;
-       uint32_t callNumber;
-       uint32_t seq;
-       uint32_t serial;
-       uint8_t type;
+       nd_uint32_t epoch;
+       nd_uint32_t cid;
+       nd_uint32_t callNumber;
+       nd_uint32_t seq;
+       nd_uint32_t serial;
+       nd_uint8_t type;
 #define RX_PACKET_TYPE_DATA            1
 #define RX_PACKET_TYPE_ACK             2
 #define RX_PACKET_TYPE_BUSY            3
@@ -88,7 +91,7 @@ struct rx_header {
 #define RX_PACKET_TYPE_DEBUG           8
 #define RX_PACKET_TYPE_PARAMS          9
 #define RX_PACKET_TYPE_VERSION         13
-       uint8_t flags;
+       nd_uint8_t flags;
 #define RX_CLIENT_INITIATED    1
 #define RX_REQUEST_ACK         2
 #define RX_LAST_PACKET         4
@@ -96,10 +99,10 @@ struct rx_header {
 #define RX_FREE_PACKET         16
 #define RX_SLOW_START_OK       32
 #define RX_JUMBO_PACKET                32
-       uint8_t userStatus;
-       uint8_t securityIndex;
-       uint16_t spare;         /* How clever: even though the AFS */
-       uint16_t serviceId;             /* header files indicate that the */
+       nd_uint8_t userStatus;
+       nd_uint8_t securityIndex;
+       nd_uint16_t spare;              /* How clever: even though the AFS */
+       nd_uint16_t serviceId;          /* header files indicate that the */
 };                                     /* serviceId is first, it's really */
                                        /* encoded _after_ the spare field */
                                        /* I wasted a day figuring that out! */
@@ -687,11 +690,11 @@ rx_cache_insert(netdissect_options *ndo,
        if (++rx_cache_next >= RX_CACHE_SIZE)
                rx_cache_next = 0;
 
-       rxent->callnum = rxh->callNumber;
-       rxent->client = ip->ip_src;
-       rxent->server = ip->ip_dst;
+       rxent->callnum = EXTRACT_32BITS(&rxh->callNumber);
+       UNALIGNED_MEMCPY(&rxent->client, &ip->ip_src, sizeof(uint32_t));
+       UNALIGNED_MEMCPY(&rxent->server, &ip->ip_dst, sizeof(uint32_t));
        rxent->dport = dport;
-       rxent->serviceId = rxh->serviceId;
+       rxent->serviceId = EXTRACT_16BITS(&rxh->serviceId);
        rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header));
 }
 
@@ -708,18 +711,21 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
 {
        int i;
        struct rx_cache_entry *rxent;
-       uint32_t clip = ip->ip_dst.s_addr;
-       uint32_t sip = ip->ip_src.s_addr;
+       uint32_t clip;
+       uint32_t sip;
+
+       UNALIGNED_MEMCPY(&clip, &ip->ip_dst, sizeof(uint32_t));
+       UNALIGNED_MEMCPY(&sip, &ip->ip_src, sizeof(uint32_t));
 
        /* Start the search where we last left off */
 
        i = rx_cache_hint;
        do {
                rxent = &rx_cache[i];
-               if (rxent->callnum == rxh->callNumber &&
+               if (rxent->callnum == EXTRACT_32BITS(&rxh->callNumber) &&
                    rxent->client.s_addr == clip &&
                    rxent->server.s_addr == sip &&
-                   rxent->serviceId == rxh->serviceId &&
+                   rxent->serviceId == EXTRACT_16BITS(&rxh->serviceId) &&
                    rxent->dport == sport) {
 
                        /* We got a match! */
@@ -1013,6 +1019,7 @@ fs_print(netdissect_options *ndo,
                        }
                        if (j == 0)
                                ND_PRINT((ndo, " <none!>"));
+                       break;
                }
                case 65537:     /* Fetch data 64 */
                        FIDOUT();
@@ -1256,6 +1263,7 @@ cb_print(netdissect_options *ndo,
                        if (j == 0)
                                ND_PRINT((ndo, " <none!>"));
 
+                       ND_TCHECK_32BITS(bp);
                        j = EXTRACT_32BITS(bp);
                        bp += sizeof(int32_t);
 
@@ -1272,6 +1280,7 @@ cb_print(netdissect_options *ndo,
                                bp += sizeof(int32_t);
                                tok2str(cb_types, "type %d", t);
                        }
+                       break;
                }
                case 214: {
                        ND_PRINT((ndo, " afsuuid"));
@@ -1733,6 +1742,7 @@ vldb_reply_print(netdissect_options *ndo,
                        INTOUT();
                        ND_PRINT((ndo, " nextindex"));
                        INTOUT();
+                       /*FALLTHROUGH*/
                case 503:       /* Get entry by id */
                case 504:       /* Get entry by name */
                {       unsigned long nservers, j;
@@ -1782,6 +1792,7 @@ vldb_reply_print(netdissect_options *ndo,
                        INTOUT();
                        ND_PRINT((ndo, " nextindex"));
                        INTOUT();
+                       /*FALLTHROUGH*/
                case 518:       /* Get entry by ID N */
                case 519:       /* Get entry by name N */
                {       unsigned long nservers, j;
@@ -1918,7 +1929,7 @@ kauth_print(netdissect_options *ndo,
        bp += sizeof(struct rx_header) + 4;
 
        switch (kauth_op) {
-               case 1:         /* Authenticate old */;
+               case 1:         /* Authenticate old */
                case 21:        /* Authenticate */
                case 22:        /* Authenticate-V2 */
                case 2:         /* Change PW */
@@ -2527,6 +2538,10 @@ ubik_print(netdissect_options *ndo,
         * gleaned from ubik/ubik_int.xg
         */
 
+       /* Every function that calls this function first makes a bounds check
+        * for (sizeof(rx_header) + 4) bytes, so long as it remains this way
+        * the line below will not over-read.
+        */
        ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header));
 
        ND_PRINT((ndo, " ubik call %s", tok2str(ubik_req, "op#%d", ubik_op)));
@@ -2571,6 +2586,7 @@ ubik_print(netdissect_options *ndo,
                        INTOUT();
                        ND_PRINT((ndo, " length"));
                        INTOUT();
+                       ND_TCHECK_32BITS(bp);
                        temp = EXTRACT_32BITS(bp);
                        bp += sizeof(int32_t);
                        tok2str(ubik_lock_types, "type %d", temp);