The function pr_pack does not properly check boundaries before
accessing packet data. This could happen on short network reads or
when we receive packets that are addressed for another running ping6
instance (see pr_pack comment for more information).

Index: ping6.c
===================================================================
RCS file: /cvs/src/sbin/ping6/ping6.c,v
retrieving revision 1.112
diff -u -p -r1.112 ping6.c
--- ping6.c     1 Sep 2015 19:53:23 -0000       1.112
+++ ping6.c     8 Sep 2015 19:29:29 -0000
@@ -1222,6 +1222,11 @@ pr_pack(u_char *buf, int cc, struct msgh
                        SIPHASH_CTX ctx;
                        u_int8_t mac[SIPHASH_DIGEST_LENGTH];
 
+                       if (cc - sizeof(*cp) < sizeof(payload)) {
+                               (void)printf("signature missing!\n");
+                               return;
+                       }
+
                        memcpy(&payload, icp + 1, sizeof(payload));
                        tv64 = &payload.tv64;
 
@@ -1306,7 +1311,8 @@ pr_pack(u_char *buf, int cc, struct msgh
                                }
                        }
                }
-       } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {
+       } else if (icp->icmp6_type == ICMP6_NI_REPLY &&
+           cc >= sizeof(*ni) && mynireply(ni)) {
                seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce);
                ++nreceived;
                if (TST(seq % mx_dup_ck)) {
@@ -1351,7 +1357,7 @@ pr_pack(u_char *buf, int cc, struct msgh
                case NI_QTYPE_FQDN:
                default:        /* XXX: for backward compatibility */
                        cp = (u_char *)ni + ICMP6_NIRLEN;
-                       if (buf[off + ICMP6_NIRLEN] ==
+                       if (off + ICMP6_NIRLEN < cc && buf[off + ICMP6_NIRLEN] 
==
                            cc - off - ICMP6_NIRLEN - 1)
                                oldfqdn = 1;
                        else
@@ -1438,7 +1444,8 @@ pr_pack(u_char *buf, int cc, struct msgh
                                        }
                                }
 
-                               if (buf[off + ICMP6_NIRLEN] !=
+                               if (off + ICMP6_NIRLEN < cc &&
+                                   buf[off + ICMP6_NIRLEN] !=
                                    cc - off - ICMP6_NIRLEN - 1 && oldfqdn) {
                                        if (comma)
                                                printf(",");

Reply via email to