merge dhcpd's packet.c revision 1.7:
authortobias <tobias@openbsd.org>
Mon, 28 Jul 2014 16:40:32 +0000 (16:40 +0000)
committertobias <tobias@openbsd.org>
Mon, 28 Jul 2014 16:40:32 +0000 (16:40 +0000)
Fix very hard to reach DoS attack vector, which would involve more than
8 billion network packets.  Mixture of many many malformed and proper
packets could result in a division by zero.

ok krw@

sbin/dhclient/packet.c
usr.sbin/dhcrelay/packet.c

index 415c767..1feafa8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: packet.c,v 1.26 2014/04/17 09:59:30 krw Exp $ */
+/*     $OpenBSD: packet.c,v 1.27 2014/07/28 16:40:32 tobias Exp $      */
 
 /* Packet assembly code, originally contributed by Archie Cobbs. */
 
@@ -126,7 +126,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
        ip_packets_seen++;
        if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) {
                ip_packets_bad_checksum++;
-               if (ip_packets_seen > 4 &&
+               if (ip_packets_seen > 4 && ip_packets_bad_checksum != 0 &&
                    (ip_packets_seen / ip_packets_bad_checksum) < 2) {
                        note("%d bad IP checksums seen in %d packets",
                            ip_packets_bad_checksum, ip_packets_seen);
@@ -154,6 +154,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
        if ((len < 0) || (len + data > buf + bufix + buflen)) {
                udp_packets_length_overflow++;
                if (udp_packets_length_checked > 4 &&
+                   udp_packets_length_overflow != 0 &&
                    (udp_packets_length_checked /
                    udp_packets_length_overflow) < 2) {
                        note("%d udp packets in %d too long - dropped",
@@ -180,7 +181,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
        udp_packets_seen++;
        if (usum && usum != sum) {
                udp_packets_bad_checksum++;
-               if (udp_packets_seen > 4 &&
+               if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 &&
                    (udp_packets_seen / udp_packets_bad_checksum) < 2) {
                        note("%d bad udp checksums in %d packets",
                            udp_packets_bad_checksum, udp_packets_seen);
index 3c1a62f..809f7c8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: packet.c,v 1.3 2009/09/03 11:56:49 reyk Exp $ */
+/*     $OpenBSD: packet.c,v 1.4 2014/07/28 16:40:32 tobias Exp $       */
 
 /* Packet assembly code, originally contributed by Archie Cobbs. */
 
@@ -200,7 +200,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
        ip_packets_seen++;
        if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) {
                ip_packets_bad_checksum++;
-               if (ip_packets_seen > 4 &&
+               if (ip_packets_seen > 4 && ip_packets_bad_checksum != 0 &&
                    (ip_packets_seen / ip_packets_bad_checksum) < 2) {
                        note("%d bad IP checksums seen in %d packets",
                            ip_packets_bad_checksum, ip_packets_seen);
@@ -227,6 +227,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
                if (len + data > buf + bufix + buflen) {
                        udp_packets_length_overflow++;
                        if (udp_packets_length_checked > 4 &&
+                           udp_packets_length_overflow != 0 &&
                            (udp_packets_length_checked /
                            udp_packets_length_overflow) < 2) {
                                note("%d udp packets in %d too long - dropped",
@@ -252,7 +253,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
        udp_packets_seen++;
        if (usum && usum != sum) {
                udp_packets_bad_checksum++;
-               if (udp_packets_seen > 4 &&
+               if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 &&
                    (udp_packets_seen / udp_packets_bad_checksum) < 2) {
                        note("%d bad udp checksums in %d packets",
                            udp_packets_bad_checksum, udp_packets_seen);