Blob Blame History Raw
From 73934da8f9d6934a823f59995e132c4758403183 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 25 Mar 2015 16:38:38 +0100
Subject: [PATCH 1/4] Fix for CVE-2015-0261

(cherry picked from commit 089ec2bd856dd17f6db62150b92ab7bb723bb31f)

See: http://www.ca.tcpdump.org/cve/0003-test-case-for-cve2015-0261-corrupted-IPv6-mobility-h.patch
---
 print-mobility.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/print-mobility.c b/print-mobility.c
index 1490b72..535f04b 100644
--- a/print-mobility.c
+++ b/print-mobility.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2002 WIDE Project.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -13,7 +13,7 @@
  * 3. Neither the name of the project nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -74,6 +74,18 @@ struct ip6_mobility {
 #define IP6M_BINDING_UPDATE	5	/* Binding Update */
 #define IP6M_BINDING_ACK	6	/* Binding Acknowledgement */
 #define IP6M_BINDING_ERROR	7	/* Binding Error */
+#define IP6M_MAX		7
+
+static const unsigned ip6m_hdrlen[IP6M_MAX + 1] = {
+	IP6M_MINLEN,      /* IP6M_BINDING_REQUEST  */
+	IP6M_MINLEN + 8,  /* IP6M_HOME_TEST_INIT   */
+	IP6M_MINLEN + 8,  /* IP6M_CAREOF_TEST_INIT */
+	IP6M_MINLEN + 16, /* IP6M_HOME_TEST        */
+	IP6M_MINLEN + 16, /* IP6M_CAREOF_TEST      */
+	IP6M_MINLEN + 4,  /* IP6M_BINDING_UPDATE   */
+	IP6M_MINLEN + 4,  /* IP6M_BINDING_ACK      */
+	IP6M_MINLEN + 16, /* IP6M_BINDING_ERROR    */
+};
 
 /* Mobility Header Options */
 #define IP6MOPT_MINLEN		2
@@ -95,16 +107,20 @@ mobility_opt_print(const u_char *bp, int len)
 	int optlen;
 
 	for (i = 0; i < len; i += optlen) {
+		TCHECK(bp[i]);
 		if (bp[i] == IP6MOPT_PAD1)
 			optlen = 1;
 		else {
-			if (i + 1 < len)
+			if (i + 1 < len) {
+				TCHECK(bp[i + 1]);
 				optlen = bp[i + 1] + 2;
+			}
 			else
 				goto trunc;
 		}
 		if (i + optlen > len)
 			goto trunc;
+		TCHECK(bp[i + optlen]);
 
 		switch (bp[i]) {
 		case IP6MOPT_PAD1:
@@ -201,6 +217,10 @@ mobility_print(const u_char *bp, const u_char *bp2 _U_)
 
 	TCHECK(mh->ip6m_type);
 	type = mh->ip6m_type;
+	if (type <= IP6M_MAX && mhlen < ip6m_hdrlen[type]) {
+                printf("(header length %u is too small for type %u)", mhlen, type);
+		goto trunc;
+	}
 	switch (type) {
 	case IP6M_BINDING_REQUEST:
 		printf("mobility: BRR");
-- 
2.3.4