Blame SOURCES/dnsmasq-2.76-fix-dhcp-option-arrangements.patch

e20e41
From 591ed1e90503817938ccf5f127e677a8dd48b6d8 Mon Sep 17 00:00:00 2001
e20e41
From: Simon Kelley <simon@thekelleys.org.uk>
e20e41
Date: Mon, 11 Jul 2016 18:18:42 +0100
e20e41
Subject: [PATCH] Fix bad behaviour with some DHCP option arrangements.
e20e41
e20e41
The check that there's enough space to store the DHCP agent-id
e20e41
at the end of the packet could succeed when it should fail
e20e41
if the END option is in either of the oprion-overload areas.
e20e41
That could overwrite legit options in the request and cause
e20e41
bad behaviour. It's highly unlikely that any sane DHCP client
e20e41
would trigger this bug, and it's never been seen, but this
e20e41
fixes the problem.
e20e41
e20e41
Also fix off-by-one in bounds checking of option processing.
e20e41
Worst case scenario on that is a read one byte beyond the
e20e41
end off a buffer with a crafted packet, and maybe therefore
e20e41
a SIGV crash if the memory after the buffer is not mapped.
e20e41
e20e41
Thanks to Timothy Becker for spotting these.
e20e41
---
e20e41
 src/rfc2131.c | 5 +++--
e20e41
 1 file changed, 3 insertions(+), 2 deletions(-)
e20e41
e20e41
diff --git a/src/rfc2131.c b/src/rfc2131.c
e20e41
index b7c167e..8b99d4b 100644
e20e41
--- a/src/rfc2131.c
e20e41
+++ b/src/rfc2131.c
e20e41
@@ -186,7 +186,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
e20e41
 	     be enough free space at the end of the packet to copy the option. */
e20e41
 	  unsigned char *sopt;
e20e41
 	  unsigned int total = option_len(opt) + 2;
e20e41
-	  unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
e20e41
+	  unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
e20e41
+						 OPTION_END, 0);
e20e41
 	  if (last_opt && last_opt < end - total)
e20e41
 	    {
e20e41
 	      end -= total;
e20e41
@@ -1606,7 +1607,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
e20e41
 {
e20e41
   while (1) 
e20e41
     {
e20e41
-      if (p > end)
e20e41
+      if (p >= end)
e20e41
 	return NULL;
e20e41
       else if (*p == OPTION_END)
e20e41
 	return opt == OPTION_END ? p : NULL;
e20e41
-- 
e20e41
2.9.3
e20e41