basebuilder_pel7ppc64bebuilder0
7 years ago
12 changed files with 1280 additions and 1 deletions
@ -0,0 +1,262 @@
@@ -0,0 +1,262 @@
|
||||
From 8868a04895b27d42d42e364f1a0c0196c1505b04 Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 18:17:11 +0100 |
||||
Subject: [PATCH 1/9] Security fix, CVE-2017-14491 DNS heap buffer |
||||
overflow. |
||||
|
||||
Fix heap overflow in DNS code. This is a potentially serious |
||||
security hole. It allows an attacker who can make DNS |
||||
requests to dnsmasq, and who controls the contents of |
||||
a domain, which is thereby queried, to overflow |
||||
(by 2 bytes) a heap buffer and either crash, or |
||||
even take control of, dnsmasq. |
||||
--- |
||||
src/dnsmasq.h | 2 +- |
||||
src/dnssec.c | 2 +- |
||||
src/option.c | 2 +- |
||||
src/rfc1035.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- |
||||
src/rfc2131.c | 4 ++-- |
||||
src/rfc3315.c | 4 ++-- |
||||
src/util.c | 7 ++++++- |
||||
7 files changed, 54 insertions(+), 17 deletions(-) |
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h |
||||
index 1179492..06e5579 100644 |
||||
--- a/src/dnsmasq.h |
||||
+++ b/src/dnsmasq.h |
||||
@@ -1162,7 +1162,7 @@ u32 rand32(void); |
||||
u64 rand64(void); |
||||
int legal_hostname(char *c); |
||||
char *canonicalise(char *s, int *nomem); |
||||
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval); |
||||
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit); |
||||
void *safe_malloc(size_t size); |
||||
void safe_pipe(int *fd, int read_noblock); |
||||
void *whine_malloc(size_t size); |
||||
diff --git a/src/dnssec.c b/src/dnssec.c |
||||
index 3c77c7d..f45c804 100644 |
||||
--- a/src/dnssec.c |
||||
+++ b/src/dnssec.c |
||||
@@ -2227,7 +2227,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char |
||||
|
||||
p = (unsigned char *)(header+1); |
||||
|
||||
- p = do_rfc1035_name(p, name); |
||||
+ p = do_rfc1035_name(p, name, NULL); |
||||
*p++ = 0; |
||||
PUTSHORT(type, p); |
||||
PUTSHORT(class, p); |
||||
diff --git a/src/option.c b/src/option.c |
||||
index eb78b1a..3469f53 100644 |
||||
--- a/src/option.c |
||||
+++ b/src/option.c |
||||
@@ -1378,7 +1378,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) |
||||
} |
||||
|
||||
p = newp; |
||||
- end = do_rfc1035_name(p + len, dom); |
||||
+ end = do_rfc1035_name(p + len, dom, NULL); |
||||
*end++ = 0; |
||||
len = end - p; |
||||
free(dom); |
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c |
||||
index 24d08c1..78410d6 100644 |
||||
--- a/src/rfc1035.c |
||||
+++ b/src/rfc1035.c |
||||
@@ -1049,6 +1049,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog |
||||
return 0; |
||||
} |
||||
|
||||
+ |
||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, |
||||
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...) |
||||
{ |
||||
@@ -1058,12 +1059,21 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
unsigned short usval; |
||||
long lval; |
||||
char *sval; |
||||
+#define CHECK_LIMIT(size) \ |
||||
+ if (limit && p + (size) > (unsigned char*)limit) \ |
||||
+ { \ |
||||
+ va_end(ap); \ |
||||
+ goto truncated; \ |
||||
+ } |
||||
|
||||
if (truncp && *truncp) |
||||
return 0; |
||||
- |
||||
+ |
||||
va_start(ap, format); /* make ap point to 1st unamed argument */ |
||||
- |
||||
+ |
||||
+ /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */ |
||||
+ CHECK_LIMIT(12); |
||||
+ |
||||
if (nameoffset > 0) |
||||
{ |
||||
PUTSHORT(nameoffset | 0xc000, p); |
||||
@@ -1072,7 +1082,13 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
{ |
||||
char *name = va_arg(ap, char *); |
||||
if (name) |
||||
- p = do_rfc1035_name(p, name); |
||||
+ p = do_rfc1035_name(p, name, limit); |
||||
+ if (!p) |
||||
+ { |
||||
+ va_end(ap); |
||||
+ goto truncated; |
||||
+ } |
||||
+ |
||||
if (nameoffset < 0) |
||||
{ |
||||
PUTSHORT(-nameoffset | 0xc000, p); |
||||
@@ -1093,6 +1109,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
{ |
||||
#ifdef HAVE_IPV6 |
||||
case '6': |
||||
+ CHECK_LIMIT(IN6ADDRSZ); |
||||
sval = va_arg(ap, char *); |
||||
memcpy(p, sval, IN6ADDRSZ); |
||||
p += IN6ADDRSZ; |
||||
@@ -1100,36 +1117,47 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
#endif |
||||
|
||||
case '4': |
||||
+ CHECK_LIMIT(INADDRSZ); |
||||
sval = va_arg(ap, char *); |
||||
memcpy(p, sval, INADDRSZ); |
||||
p += INADDRSZ; |
||||
break; |
||||
|
||||
case 'b': |
||||
+ CHECK_LIMIT(1); |
||||
usval = va_arg(ap, int); |
||||
*p++ = usval; |
||||
break; |
||||
|
||||
case 's': |
||||
+ CHECK_LIMIT(2); |
||||
usval = va_arg(ap, int); |
||||
PUTSHORT(usval, p); |
||||
break; |
||||
|
||||
case 'l': |
||||
+ CHECK_LIMIT(4); |
||||
lval = va_arg(ap, long); |
||||
PUTLONG(lval, p); |
||||
break; |
||||
|
||||
case 'd': |
||||
- /* get domain-name answer arg and store it in RDATA field */ |
||||
- if (offset) |
||||
- *offset = p - (unsigned char *)header; |
||||
- p = do_rfc1035_name(p, va_arg(ap, char *)); |
||||
- *p++ = 0; |
||||
+ /* get domain-name answer arg and store it in RDATA field */ |
||||
+ if (offset) |
||||
+ *offset = p - (unsigned char *)header; |
||||
+ p = do_rfc1035_name(p, va_arg(ap, char *), limit); |
||||
+ if (!p) |
||||
+ { |
||||
+ va_end(ap); |
||||
+ goto truncated; |
||||
+ } |
||||
+ CHECK_LIMIT(1); |
||||
+ *p++ = 0; |
||||
break; |
||||
|
||||
case 't': |
||||
usval = va_arg(ap, int); |
||||
+ CHECK_LIMIT(usval); |
||||
sval = va_arg(ap, char *); |
||||
if (usval != 0) |
||||
memcpy(p, sval, usval); |
||||
@@ -1141,20 +1169,24 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
usval = sval ? strlen(sval) : 0; |
||||
if (usval > 255) |
||||
usval = 255; |
||||
+ CHECK_LIMIT(usval + 1); |
||||
*p++ = (unsigned char)usval; |
||||
memcpy(p, sval, usval); |
||||
p += usval; |
||||
break; |
||||
} |
||||
|
||||
+#undef CHECK_LIMIT |
||||
va_end(ap); /* clean up variable argument pointer */ |
||||
|
||||
j = p - sav - 2; |
||||
- PUTSHORT(j, sav); /* Now, store real RDLength */ |
||||
+ /* this has already been checked against limit before */ |
||||
+ PUTSHORT(j, sav); /* Now, store real RDLength */ |
||||
|
||||
/* check for overflow of buffer */ |
||||
if (limit && ((unsigned char *)limit - p) < 0) |
||||
{ |
||||
+truncated: |
||||
if (truncp) |
||||
*truncp = 1; |
||||
return 0; |
||||
diff --git a/src/rfc2131.c b/src/rfc2131.c |
||||
index 8b99d4b..75893a6 100644 |
||||
--- a/src/rfc2131.c |
||||
+++ b/src/rfc2131.c |
||||
@@ -2420,10 +2420,10 @@ static void do_options(struct dhcp_context *context, |
||||
|
||||
if (fqdn_flags & 0x04) |
||||
{ |
||||
- p = do_rfc1035_name(p, hostname); |
||||
+ p = do_rfc1035_name(p, hostname, NULL); |
||||
if (domain) |
||||
{ |
||||
- p = do_rfc1035_name(p, domain); |
||||
+ p = do_rfc1035_name(p, domain, NULL); |
||||
*p++ = 0; |
||||
} |
||||
} |
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c |
||||
index 3f4d69c..73bdee4 100644 |
||||
--- a/src/rfc3315.c |
||||
+++ b/src/rfc3315.c |
||||
@@ -1472,10 +1472,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh) |
||||
if ((p = expand(len + 2))) |
||||
{ |
||||
*(p++) = state->fqdn_flags; |
||||
- p = do_rfc1035_name(p, state->hostname); |
||||
+ p = do_rfc1035_name(p, state->hostname, NULL); |
||||
if (state->send_domain) |
||||
{ |
||||
- p = do_rfc1035_name(p, state->send_domain); |
||||
+ p = do_rfc1035_name(p, state->send_domain, NULL); |
||||
*p = 0; |
||||
} |
||||
} |
||||
diff --git a/src/util.c b/src/util.c |
||||
index 1a9f228..be9f8a6 100644 |
||||
--- a/src/util.c |
||||
+++ b/src/util.c |
||||
@@ -218,15 +218,20 @@ char *canonicalise(char *in, int *nomem) |
||||
return ret; |
||||
} |
||||
|
||||
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval) |
||||
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit) |
||||
{ |
||||
int j; |
||||
|
||||
while (sval && *sval) |
||||
{ |
||||
+ if (limit && p + 1 > (unsigned char*)limit) |
||||
+ return p; |
||||
+ |
||||
unsigned char *cp = p++; |
||||
for (j = 0; *sval && (*sval != '.'); sval++, j++) |
||||
{ |
||||
+ if (limit && p + 1 > (unsigned char*)limit) |
||||
+ return p; |
||||
#ifdef HAVE_DNSSEC |
||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE) |
||||
*p++ = (*(++sval))-1; |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
From c14b8b511ac55f6933aebefbd6cc27c1ec74ad58 Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 18:47:15 +0100 |
||||
Subject: [PATCH 2/9] Security fix, CVE-2017-14492, DHCPv6 RA heap |
||||
overflow. |
||||
|
||||
Fix heap overflow in IPv6 router advertisement code. |
||||
This is a potentially serious security hole, as a |
||||
crafted RA request can overflow a buffer and crash or |
||||
control dnsmasq. Attacker must be on the local network. |
||||
--- |
||||
src/radv.c | 3 +++ |
||||
1 file changed, 3 insertions(+) |
||||
|
||||
diff --git a/src/radv.c b/src/radv.c |
||||
index 749b666..d09fe0e 100644 |
||||
--- a/src/radv.c |
||||
+++ b/src/radv.c |
||||
@@ -198,6 +198,9 @@ void icmp6_packet(time_t now) |
||||
/* look for link-layer address option for logging */ |
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) |
||||
{ |
||||
+ if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) { |
||||
+ return; |
||||
+ } |
||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); |
||||
mac = daemon->namebuff; |
||||
} |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
From 5086b12a4b1269d1576b5bab01f72c6fa19c55bc Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 18:52:50 +0100 |
||||
Subject: [PATCH 3/9] Security fix, CVE-2017-14493, DHCPv6 - Stack buffer |
||||
overflow. |
||||
|
||||
Fix stack overflow in DHCPv6 code. An attacker who can send |
||||
a DHCPv6 request to dnsmasq can overflow the stack frame and |
||||
crash or control dnsmasq. |
||||
--- |
||||
src/rfc3315.c | 3 +++ |
||||
1 file changed, 3 insertions(+) |
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c |
||||
index 73bdee4..8d18a28 100644 |
||||
--- a/src/rfc3315.c |
||||
+++ b/src/rfc3315.c |
||||
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, |
||||
/* RFC-6939 */ |
||||
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3))) |
||||
{ |
||||
+ if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) { |
||||
+ return 0; |
||||
+ } |
||||
state->mac_type = opt6_uint(opt, 0, 2); |
||||
state->mac_len = opt6_len(opt) - 2; |
||||
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len); |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
From 8c8fe650dc17aad0fbafc920fde719218dc4568d Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 20:05:11 +0100 |
||||
Subject: [PATCH 4/9] Security fix, CVE-2017-14494, Infoleak handling |
||||
DHCPv6 forwarded requests. |
||||
|
||||
Fix information leak in DHCPv6. A crafted DHCPv6 packet can |
||||
cause dnsmasq to forward memory from outside the packet |
||||
buffer to a DHCPv6 server when acting as a relay. |
||||
--- |
||||
src/rfc3315.c | 3 +++ |
||||
1 file changed, 3 insertions(+) |
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c |
||||
index 8d18a28..03b3f84 100644 |
||||
--- a/src/rfc3315.c |
||||
+++ b/src/rfc3315.c |
||||
@@ -216,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, |
||||
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end)) |
||||
{ |
||||
+ if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) { |
||||
+ return 0; |
||||
+ } |
||||
int o = new_opt6(opt6_type(opt)); |
||||
if (opt6_type(opt) == OPTION6_RELAY_MSG) |
||||
{ |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
From f2ad2cecb55825f7e4409222de1688b9ceebceda Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 20:16:50 +0100 |
||||
Subject: [PATCH 6/9] Security fix, CVE-2017-14495, OOM in DNS response |
||||
creation. |
||||
|
||||
Fix out-of-memory Dos vulnerability. An attacker which can |
||||
send malicious DNS queries to dnsmasq can trigger memory |
||||
allocations in the add_pseudoheader function |
||||
The allocated memory is never freed which leads to a DoS |
||||
through memory exhaustion. dnsmasq is vulnerable only |
||||
if one of the following option is specified: |
||||
--add-mac, --add-cpe-id or --add-subnet. |
||||
--- |
||||
src/edns0.c | 8 +++++++- |
||||
1 file changed, 7 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c |
||||
index eed135e..5bdc133 100644 |
||||
--- a/src/edns0.c |
||||
+++ b/src/edns0.c |
||||
@@ -192,9 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
!(p = skip_section(p, |
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), |
||||
header, plen))) |
||||
+ { |
||||
+ free(buff); |
||||
return plen; |
||||
+ } |
||||
if (p + 11 > limit) |
||||
- return plen; /* Too big */ |
||||
+ { |
||||
+ free(buff); |
||||
+ return plen; /* Too big */ |
||||
+ } |
||||
*p++ = 0; /* empty name */ |
||||
PUTSHORT(T_OPT, p); |
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */ |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
From 5ab67e936085a9e584c9b3e43f442ef5bee7f40e Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 20:11:58 +0100 |
||||
Subject: [PATCH 5/9] Security fix, CVE-2017-14496, Integer underflow in |
||||
DNS response creation. |
||||
|
||||
Fix DoS in DNS. Invalid boundary checks in the |
||||
add_pseudoheader function allows a memcpy call with negative |
||||
size An attacker which can send malicious DNS queries |
||||
to dnsmasq can trigger a DoS remotely. |
||||
dnsmasq is vulnerable only if one of the following option is |
||||
specified: --add-mac, --add-cpe-id or --add-subnet. |
||||
--- |
||||
src/edns0.c | 13 ++++++++++++- |
||||
1 file changed, 12 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c |
||||
index d2b514b..eed135e 100644 |
||||
--- a/src/edns0.c |
||||
+++ b/src/edns0.c |
||||
@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
GETSHORT(len, p); |
||||
|
||||
/* malformed option, delete the whole OPT RR and start again. */ |
||||
- if (i + len > rdlen) |
||||
+ if (i + 4 + len > rdlen) |
||||
{ |
||||
rdlen = 0; |
||||
is_last = 0; |
||||
@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), |
||||
header, plen))) |
||||
return plen; |
||||
+ if (p + 11 > limit) |
||||
+ return plen; /* Too big */ |
||||
*p++ = 0; /* empty name */ |
||||
PUTSHORT(T_OPT, p); |
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */ |
||||
@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
/* Copy back any options */ |
||||
if (buff) |
||||
{ |
||||
+ if (p + rdlen > limit) |
||||
+ { |
||||
+ free(buff); |
||||
+ return plen; /* Too big */ |
||||
+ } |
||||
memcpy(p, buff, rdlen); |
||||
free(buff); |
||||
p += rdlen; |
||||
@@ -217,8 +224,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
/* Add new option */ |
||||
if (optno != 0 && replace != 2) |
||||
{ |
||||
+ if (p + 4 > limit) |
||||
+ return plen; /* Too big */ |
||||
PUTSHORT(optno, p); |
||||
PUTSHORT(optlen, p); |
||||
+ if (p + optlen > limit) |
||||
+ return plen; /* Too big */ |
||||
memcpy(p, opt, optlen); |
||||
p += optlen; |
||||
PUTSHORT(p - datap, lenp); |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,582 @@
@@ -0,0 +1,582 @@
|
||||
From 87444dc6977b61096127dcdfe87dc6cf2c0167d6 Mon Sep 17 00:00:00 2001 |
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com> |
||||
Date: Sun, 16 Apr 2017 20:20:08 +0100 |
||||
Subject: [PATCH] Capture and log STDOUT and STDERR output from dhcp-script. |
||||
|
||||
(cherry picked from commit c77fb9d8f09d136fa71bde2469c4fd11cefa6f4a) |
||||
|
||||
Compile-time check on buffer sizes for leasefile parsing code. |
||||
|
||||
(cherry picked from commit bf4e62c19e619f7edf8d03d58d33a5752f190bfd) |
||||
|
||||
Improve error handling with shcp-script "init" mode. |
||||
|
||||
(cherry picked from commit 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705) |
||||
|
||||
Tweak logging introduced in 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705 |
||||
|
||||
(cherry picked from commit efff74c1aea14757ce074db28e02671c7f7bb5f5) |
||||
|
||||
Don't die() on failing to parse lease-script output. |
||||
|
||||
(cherry picked from commit 05f76dab89d5b879519a4f45b0cccaa1fc3d162d) |
||||
--- |
||||
man/dnsmasq.8 | 4 +- |
||||
src/dhcp-common.c | 16 +++--- |
||||
src/dhcp-protocol.h | 4 ++ |
||||
src/dnsmasq.c | 8 +++ |
||||
src/dnsmasq.h | 54 +++++++++--------- |
||||
src/helper.c | 56 +++++++++++++++++- |
||||
src/lease.c | 159 +++++++++++++++++++++++++++++++--------------------- |
||||
src/log.c | 4 +- |
||||
src/rfc3315.c | 2 +- |
||||
9 files changed, 202 insertions(+), 105 deletions(-) |
||||
|
||||
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 |
||||
index 0521534..97d0a4f 100644 |
||||
--- a/man/dnsmasq.8 |
||||
+++ b/man/dnsmasq.8 |
||||
@@ -1551,8 +1551,8 @@ database. |
||||
|
||||
|
||||
All file descriptors are |
||||
-closed except stdin, stdout and stderr which are open to /dev/null |
||||
-(except in debug mode). |
||||
+closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq. |
||||
+(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq). |
||||
|
||||
The script is not invoked concurrently: at most one instance |
||||
of the script is ever running (dnsmasq waits for an instance of script to exit |
||||
diff --git a/src/dhcp-common.c b/src/dhcp-common.c |
||||
index 08528e8..ecc752b 100644 |
||||
--- a/src/dhcp-common.c |
||||
+++ b/src/dhcp-common.c |
||||
@@ -20,11 +20,11 @@ |
||||
|
||||
void dhcp_common_init(void) |
||||
{ |
||||
- /* These each hold a DHCP option max size 255 |
||||
- and get a terminating zero added */ |
||||
- daemon->dhcp_buff = safe_malloc(256); |
||||
- daemon->dhcp_buff2 = safe_malloc(256); |
||||
- daemon->dhcp_buff3 = safe_malloc(256); |
||||
+ /* These each hold a DHCP option max size 255 |
||||
+ and get a terminating zero added */ |
||||
+ daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ); |
||||
+ daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ); |
||||
+ daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ); |
||||
|
||||
/* dhcp_packet is used by v4 and v6, outpacket only by v6 |
||||
sizeof(struct dhcp_packet) is as good an initial size as any, |
||||
@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context) |
||||
if (context->flags & CONTEXT_RA_STATELESS) |
||||
{ |
||||
if (context->flags & CONTEXT_TEMPLATE) |
||||
- strncpy(daemon->dhcp_buff, context->template_interface, 256); |
||||
+ strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ); |
||||
else |
||||
strcpy(daemon->dhcp_buff, daemon->addrbuff); |
||||
} |
||||
else |
||||
#endif |
||||
- inet_ntop(family, start, daemon->dhcp_buff, 256); |
||||
- inet_ntop(family, end, daemon->dhcp_buff3, 256); |
||||
+ inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ); |
||||
+ inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ); |
||||
my_syslog(MS_DHCP | LOG_INFO, |
||||
(context->flags & CONTEXT_RA_STATELESS) ? |
||||
_("%s stateless on %s%.0s%.0s%s") : |
||||
diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h |
||||
index a31d829..0ea449b 100644 |
||||
--- a/src/dhcp-protocol.h |
||||
+++ b/src/dhcp-protocol.h |
||||
@@ -19,6 +19,10 @@ |
||||
#define DHCP_CLIENT_ALTPORT 1068 |
||||
#define PXE_PORT 4011 |
||||
|
||||
+/* These each hold a DHCP option max size 255 |
||||
+ and get a terminating zero added */ |
||||
+#define DHCP_BUFF_SZ 256 |
||||
+ |
||||
#define BOOTREQUEST 1 |
||||
#define BOOTREPLY 2 |
||||
#define DHCP_COOKIE 0x63825363 |
||||
diff --git a/src/dnsmasq.c b/src/dnsmasq.c |
||||
index 045ec53..9cd4052 100644 |
||||
--- a/src/dnsmasq.c |
||||
+++ b/src/dnsmasq.c |
||||
@@ -1294,6 +1294,7 @@ static void async_event(int pipe, time_t now) |
||||
daemon->tcp_pids[i] = 0; |
||||
break; |
||||
|
||||
+#if defined(HAVE_SCRIPT) |
||||
case EVENT_KILLED: |
||||
my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data); |
||||
break; |
||||
@@ -1307,12 +1308,19 @@ static void async_event(int pipe, time_t now) |
||||
daemon->lease_change_command, strerror(ev.data)); |
||||
break; |
||||
|
||||
+ case EVENT_SCRIPT_LOG: |
||||
+ my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : ""); |
||||
+ free(msg); |
||||
+ msg = NULL; |
||||
+ break; |
||||
+ |
||||
/* necessary for fatal errors in helper */ |
||||
case EVENT_USER_ERR: |
||||
case EVENT_DIE: |
||||
case EVENT_LUA_ERR: |
||||
fatal_event(&ev, msg); |
||||
break; |
||||
+#endif |
||||
|
||||
case EVENT_REOPEN: |
||||
/* Note: this may leave TCP-handling processes with the old file still open. |
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h |
||||
index 1896a64..0cfd3c6 100644 |
||||
--- a/src/dnsmasq.h |
||||
+++ b/src/dnsmasq.h |
||||
@@ -145,30 +145,31 @@ struct event_desc { |
||||
int event, data, msg_sz; |
||||
}; |
||||
|
||||
-#define EVENT_RELOAD 1 |
||||
-#define EVENT_DUMP 2 |
||||
-#define EVENT_ALARM 3 |
||||
-#define EVENT_TERM 4 |
||||
-#define EVENT_CHILD 5 |
||||
-#define EVENT_REOPEN 6 |
||||
-#define EVENT_EXITED 7 |
||||
-#define EVENT_KILLED 8 |
||||
-#define EVENT_EXEC_ERR 9 |
||||
-#define EVENT_PIPE_ERR 10 |
||||
-#define EVENT_USER_ERR 11 |
||||
-#define EVENT_CAP_ERR 12 |
||||
-#define EVENT_PIDFILE 13 |
||||
-#define EVENT_HUSER_ERR 14 |
||||
-#define EVENT_GROUP_ERR 15 |
||||
-#define EVENT_DIE 16 |
||||
-#define EVENT_LOG_ERR 17 |
||||
-#define EVENT_FORK_ERR 18 |
||||
-#define EVENT_LUA_ERR 19 |
||||
-#define EVENT_TFTP_ERR 20 |
||||
-#define EVENT_INIT 21 |
||||
-#define EVENT_NEWADDR 22 |
||||
-#define EVENT_NEWROUTE 23 |
||||
-#define EVENT_TIME_ERR 24 |
||||
+#define EVENT_RELOAD 1 |
||||
+#define EVENT_DUMP 2 |
||||
+#define EVENT_ALARM 3 |
||||
+#define EVENT_TERM 4 |
||||
+#define EVENT_CHILD 5 |
||||
+#define EVENT_REOPEN 6 |
||||
+#define EVENT_EXITED 7 |
||||
+#define EVENT_KILLED 8 |
||||
+#define EVENT_EXEC_ERR 9 |
||||
+#define EVENT_PIPE_ERR 10 |
||||
+#define EVENT_USER_ERR 11 |
||||
+#define EVENT_CAP_ERR 12 |
||||
+#define EVENT_PIDFILE 13 |
||||
+#define EVENT_HUSER_ERR 14 |
||||
+#define EVENT_GROUP_ERR 15 |
||||
+#define EVENT_DIE 16 |
||||
+#define EVENT_LOG_ERR 17 |
||||
+#define EVENT_FORK_ERR 18 |
||||
+#define EVENT_LUA_ERR 19 |
||||
+#define EVENT_TFTP_ERR 20 |
||||
+#define EVENT_INIT 21 |
||||
+#define EVENT_NEWADDR 22 |
||||
+#define EVENT_NEWROUTE 23 |
||||
+#define EVENT_TIME_ERR 24 |
||||
+#define EVENT_SCRIPT_LOG 25 |
||||
|
||||
/* Exit codes. */ |
||||
#define EC_GOOD 0 |
||||
@@ -242,8 +243,9 @@ struct event_desc { |
||||
|
||||
/* extra flags for my_syslog, we use a couple of facilities since they are known |
||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */ |
||||
-#define MS_TFTP LOG_USER |
||||
-#define MS_DHCP LOG_DAEMON |
||||
+#define MS_TFTP LOG_USER |
||||
+#define MS_DHCP LOG_DAEMON |
||||
+#define MS_SCRIPT LOG_MAIL |
||||
|
||||
struct all_addr { |
||||
union { |
||||
diff --git a/src/helper.c b/src/helper.c |
||||
index 9c37e37..de31383 100644 |
||||
--- a/src/helper.c |
||||
+++ b/src/helper.c |
||||
@@ -14,6 +14,7 @@ |
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
+#include <stdio.h> |
||||
#include "dnsmasq.h" |
||||
|
||||
#ifdef HAVE_SCRIPT |
||||
@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) |
||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] && |
||||
max_fd != event_fd && max_fd != err_fd) |
||||
close(max_fd); |
||||
- |
||||
+ |
||||
#ifdef HAVE_LUASCRIPT |
||||
if (daemon->luascript) |
||||
{ |
||||
@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) |
||||
unsigned char *buf = (unsigned char *)daemon->namebuff; |
||||
unsigned char *end, *extradata, *alloc_buff = NULL; |
||||
int is6, err = 0; |
||||
+ int pipeout[2]; |
||||
|
||||
free(alloc_buff); |
||||
|
||||
@@ -472,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) |
||||
if (!daemon->lease_change_command) |
||||
continue; |
||||
|
||||
+ /* Pipe to capture stdout and stderr from script */ |
||||
+ if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1) |
||||
+ continue; |
||||
+ |
||||
/* possible fork errors are all temporary resource problems */ |
||||
while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM)) |
||||
sleep(2); |
||||
|
||||
if (pid == -1) |
||||
- continue; |
||||
+ { |
||||
+ if (!option_bool(OPT_DEBUG)) |
||||
+ { |
||||
+ close(pipeout[0]); |
||||
+ close(pipeout[1]); |
||||
+ } |
||||
+ continue; |
||||
+ } |
||||
|
||||
/* wait for child to complete */ |
||||
if (pid != 0) |
||||
{ |
||||
+ if (!option_bool(OPT_DEBUG)) |
||||
+ { |
||||
+ FILE *fp; |
||||
+ |
||||
+ close(pipeout[1]); |
||||
+ |
||||
+ /* Read lines sent to stdout/err by the script and pass them back to be logged */ |
||||
+ if (!(fp = fdopen(pipeout[0], "r"))) |
||||
+ close(pipeout[0]); |
||||
+ else |
||||
+ { |
||||
+ while (fgets(daemon->packet, daemon->packet_buff_sz, fp)) |
||||
+ { |
||||
+ /* do not include new lines, log will append them */ |
||||
+ size_t len = strlen(daemon->packet); |
||||
+ if (len > 0) |
||||
+ { |
||||
+ --len; |
||||
+ if (daemon->packet[len] == '\n') |
||||
+ daemon->packet[len] = 0; |
||||
+ } |
||||
+ send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet); |
||||
+ } |
||||
+ fclose(fp); |
||||
+ } |
||||
+ } |
||||
+ |
||||
/* reap our children's children, if necessary */ |
||||
while (1) |
||||
{ |
||||
@@ -504,6 +544,15 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) |
||||
|
||||
continue; |
||||
} |
||||
+ |
||||
+ if (!option_bool(OPT_DEBUG)) |
||||
+ { |
||||
+ /* map stdout/stderr of script to pipeout */ |
||||
+ close(pipeout[0]); |
||||
+ dup2(pipeout[1], STDOUT_FILENO); |
||||
+ dup2(pipeout[1], STDERR_FILENO); |
||||
+ close(pipeout[1]); |
||||
+ } |
||||
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP) |
||||
{ |
||||
@@ -579,7 +628,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) |
||||
hostname = NULL; |
||||
|
||||
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err); |
||||
- } |
||||
+ } |
||||
+ |
||||
/* we need to have the event_fd around if exec fails */ |
||||
if ((i = fcntl(event_fd, F_GETFD)) != -1) |
||||
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC); |
||||
diff --git a/src/lease.c b/src/lease.c |
||||
index 20cac90..64047f9 100644 |
||||
--- a/src/lease.c |
||||
+++ b/src/lease.c |
||||
@@ -21,94 +21,62 @@ |
||||
static struct dhcp_lease *leases = NULL, *old_leases = NULL; |
||||
static int dns_dirty, file_dirty, leases_left; |
||||
|
||||
-void lease_init(time_t now) |
||||
+static int read_leases(time_t now, FILE *leasestream) |
||||
{ |
||||
unsigned long ei; |
||||
struct all_addr addr; |
||||
struct dhcp_lease *lease; |
||||
int clid_len, hw_len, hw_type; |
||||
- FILE *leasestream; |
||||
- |
||||
- leases_left = daemon->dhcp_max; |
||||
- |
||||
- if (option_bool(OPT_LEASE_RO)) |
||||
- { |
||||
- /* run "<lease_change_script> init" once to get the |
||||
- initial state of the database. If leasefile-ro is |
||||
- set without a script, we just do without any |
||||
- lease database. */ |
||||
-#ifdef HAVE_SCRIPT |
||||
- if (daemon->lease_change_command) |
||||
- { |
||||
- strcpy(daemon->dhcp_buff, daemon->lease_change_command); |
||||
- strcat(daemon->dhcp_buff, " init"); |
||||
- leasestream = popen(daemon->dhcp_buff, "r"); |
||||
- } |
||||
- else |
||||
+ int items; |
||||
+ char *domain = NULL; |
||||
+ |
||||
+ *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0'; |
||||
+ |
||||
+ /* client-id max length is 255 which is 255*2 digits + 254 colons |
||||
+ borrow DNS packet buffer which is always larger than 1000 bytes |
||||
+ |
||||
+ Check various buffers are big enough for the code below */ |
||||
+ |
||||
+#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ < 764) |
||||
+# error Buffer size breakage in leasefile parsing. |
||||
#endif |
||||
- { |
||||
- file_dirty = dns_dirty = 0; |
||||
- return; |
||||
- } |
||||
|
||||
- } |
||||
- else |
||||
- { |
||||
- /* NOTE: need a+ mode to create file if it doesn't exist */ |
||||
- leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); |
||||
- |
||||
- if (!leasestream) |
||||
- die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); |
||||
- |
||||
- /* a+ mode leaves pointer at end. */ |
||||
- rewind(leasestream); |
||||
- } |
||||
- |
||||
- /* client-id max length is 255 which is 255*2 digits + 254 colons |
||||
- borrow DNS packet buffer which is always larger than 1000 bytes */ |
||||
- if (leasestream) |
||||
- while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2) |
||||
+ while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2) |
||||
{ |
||||
+ *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0'; |
||||
+ hw_len = hw_type = clid_len = 0; |
||||
+ |
||||
#ifdef HAVE_DHCP6 |
||||
if (strcmp(daemon->dhcp_buff3, "duid") == 0) |
||||
{ |
||||
daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL); |
||||
+ if (daemon->duid_len < 0) |
||||
+ return 0; |
||||
daemon->duid = safe_malloc(daemon->duid_len); |
||||
memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len); |
||||
continue; |
||||
} |
||||
#endif |
||||
- |
||||
- ei = atol(daemon->dhcp_buff3); |
||||
|
||||
if (fscanf(leasestream, " %64s %255s %764s", |
||||
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3) |
||||
- break; |
||||
+ return 0; |
||||
|
||||
- clid_len = 0; |
||||
- if (strcmp(daemon->packet, "*") != 0) |
||||
- clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); |
||||
- |
||||
- if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) && |
||||
- (lease = lease4_allocate(addr.addr.addr4))) |
||||
+ if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4)) |
||||
{ |
||||
+ if ((lease = lease4_allocate(addr.addr.addr4))) |
||||
+ domain = get_domain(lease->addr); |
||||
+ |
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type); |
||||
/* For backwards compatibility, no explict MAC address type means ether. */ |
||||
if (hw_type == 0 && hw_len != 0) |
||||
hw_type = ARPHRD_ETHER; |
||||
- |
||||
- lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, |
||||
- hw_len, hw_type, clid_len, now, 0); |
||||
- |
||||
- if (strcmp(daemon->dhcp_buff, "*") != 0) |
||||
- lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL); |
||||
} |
||||
#ifdef HAVE_DHCP6 |
||||
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6)) |
||||
{ |
||||
char *s = daemon->dhcp_buff2; |
||||
int lease_type = LEASE_NA; |
||||
- int iaid; |
||||
|
||||
if (s[0] == 'T') |
||||
{ |
||||
@@ -116,23 +84,30 @@ void lease_init(time_t now) |
||||
s++; |
||||
} |
||||
|
||||
- iaid = strtoul(s, NULL, 10); |
||||
- |
||||
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type))) |
||||
{ |
||||
- lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0); |
||||
- lease_set_iaid(lease, iaid); |
||||
- if (strcmp(daemon->dhcp_buff, "*") != 0) |
||||
- lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL); |
||||
+ lease_set_iaid(lease, strtoul(s, NULL, 10)); |
||||
+ domain = get_domain6((struct in6_addr *)lease->hwaddr); |
||||
} |
||||
} |
||||
#endif |
||||
else |
||||
- break; |
||||
+ return 0; |
||||
|
||||
if (!lease) |
||||
die (_("too many stored leases"), NULL, EC_MISC); |
||||
- |
||||
+ |
||||
+ if (strcmp(daemon->packet, "*") != 0) |
||||
+ clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL); |
||||
+ |
||||
+ lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, |
||||
+ hw_len, hw_type, clid_len, now, 0); |
||||
+ |
||||
+ if (strcmp(daemon->dhcp_buff, "*") != 0) |
||||
+ lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL); |
||||
+ |
||||
+ ei = atol(daemon->dhcp_buff3); |
||||
+ |
||||
#ifdef HAVE_BROKEN_RTC |
||||
if (ei != 0) |
||||
lease->expires = (time_t)ei + now; |
||||
@@ -148,7 +123,62 @@ void lease_init(time_t now) |
||||
/* set these correctly: the "old" events are generated later from |
||||
the startup synthesised SIGHUP. */ |
||||
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED); |
||||
+ |
||||
+ *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0'; |
||||
} |
||||
+ |
||||
+ return (items == 0 || items == EOF); |
||||
+} |
||||
+ |
||||
+void lease_init(time_t now) |
||||
+{ |
||||
+ FILE *leasestream; |
||||
+ |
||||
+ leases_left = daemon->dhcp_max; |
||||
+ |
||||
+ if (option_bool(OPT_LEASE_RO)) |
||||
+ { |
||||
+ /* run "<lease_change_script> init" once to get the |
||||
+ initial state of the database. If leasefile-ro is |
||||
+ set without a script, we just do without any |
||||
+ lease database. */ |
||||
+#ifdef HAVE_SCRIPT |
||||
+ if (daemon->lease_change_command) |
||||
+ { |
||||
+ strcpy(daemon->dhcp_buff, daemon->lease_change_command); |
||||
+ strcat(daemon->dhcp_buff, " init"); |
||||
+ leasestream = popen(daemon->dhcp_buff, "r"); |
||||
+ } |
||||
+ else |
||||
+#endif |
||||
+ { |
||||
+ file_dirty = dns_dirty = 0; |
||||
+ return; |
||||
+ } |
||||
+ |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ /* NOTE: need a+ mode to create file if it doesn't exist */ |
||||
+ leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+"); |
||||
+ |
||||
+ if (!leasestream) |
||||
+ die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE); |
||||
+ |
||||
+ /* a+ mode leaves pointer at end. */ |
||||
+ rewind(leasestream); |
||||
+ } |
||||
+ |
||||
+ if (leasestream) |
||||
+ { |
||||
+ if (!read_leases(now, leasestream)) |
||||
+ my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."), |
||||
+ daemon->dhcp_buff3, daemon->dhcp_buff2, |
||||
+ daemon->namebuff, daemon->dhcp_buff); |
||||
+ |
||||
+ if (ferror(leasestream)) |
||||
+ die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE); |
||||
+ } |
||||
|
||||
#ifdef HAVE_SCRIPT |
||||
if (!daemon->lease_stream) |
||||
@@ -162,6 +192,7 @@ void lease_init(time_t now) |
||||
errno = ENOENT; |
||||
else if (WEXITSTATUS(rc) == 126) |
||||
errno = EACCES; |
||||
+ |
||||
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE); |
||||
} |
||||
|
||||
diff --git a/src/log.c b/src/log.c |
||||
index 8e66629..5fc860b 100644 |
||||
--- a/src/log.c |
||||
+++ b/src/log.c |
||||
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...) |
||||
func = "-tftp"; |
||||
else if ((LOG_FACMASK & priority) == MS_DHCP) |
||||
func = "-dhcp"; |
||||
- |
||||
+ else if ((LOG_FACMASK & priority) == MS_SCRIPT) |
||||
+ func = "-script"; |
||||
+ |
||||
#ifdef LOG_PRI |
||||
priority = LOG_PRI(priority); |
||||
#else |
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c |
||||
index 3f4d69c..a3715cd 100644 |
||||
--- a/src/rfc3315.c |
||||
+++ b/src/rfc3315.c |
||||
@@ -1975,7 +1975,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr, |
||||
|
||||
if (addr) |
||||
{ |
||||
- inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255); |
||||
+ inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1); |
||||
strcat(daemon->dhcp_buff2, " "); |
||||
} |
||||
else |
||||
-- |
||||
2.9.3 |
||||
|
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
diff --git a/src/helper.c b/src/helper.c |
||||
index de31383..a843b41 100644 |
||||
--- a/src/helper.c |
||||
+++ b/src/helper.c |
||||
@@ -14,7 +14,6 @@ |
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
-#include <stdio.h> |
||||
#include "dnsmasq.h" |
||||
|
||||
#ifdef HAVE_SCRIPT |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
From 2c1aec1e979a209eb2f2b035314a8c973b4ac269 Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Thu, 7 Sep 2017 20:45:00 +0100 |
||||
Subject: [PATCH 7/9] Don't return arcount=1 if EDNS0 RR won't fit in the |
||||
packet. |
||||
|
||||
Omitting the EDNS0 RR but setting arcount gives a malformed packet. |
||||
Also, don't accept UDP packet size less than 512 in recieved EDNS0. |
||||
--- |
||||
src/edns0.c | 5 ++++- |
||||
src/forward.c | 2 ++ |
||||
2 files changed, 6 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c |
||||
index 5bdc133..a8d0167 100644 |
||||
--- a/src/edns0.c |
||||
+++ b/src/edns0.c |
||||
@@ -221,7 +221,10 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
free(buff); |
||||
p += rdlen; |
||||
} |
||||
- header->arcount = htons(ntohs(header->arcount) + 1); |
||||
+ |
||||
+ /* Only bump arcount if RR is going to fit */ |
||||
+ if (((ssize_t)optlen) <= (limit - (p + 4))) |
||||
+ header->arcount = htons(ntohs(header->arcount) + 1); |
||||
} |
||||
|
||||
if (((ssize_t)optlen) > (limit - (p + 4))) |
||||
diff --git a/src/forward.c b/src/forward.c |
||||
index 9b464d3..0f8f462 100644 |
||||
--- a/src/forward.c |
||||
+++ b/src/forward.c |
||||
@@ -1408,6 +1408,8 @@ void receive_query(struct listener *listen, time_t now) |
||||
defaults to 512 */ |
||||
if (udp_size > daemon->edns_pktsz) |
||||
udp_size = daemon->edns_pktsz; |
||||
+ else if (udp_size < PACKETSZ) |
||||
+ udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */ |
||||
} |
||||
|
||||
#ifdef HAVE_AUTH |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
From 3947ab0069e443e72debe26379b8517fac8f6e41 Mon Sep 17 00:00:00 2001 |
||||
From: Simon Kelley <simon@thekelleys.org.uk> |
||||
Date: Mon, 25 Sep 2017 20:19:55 +0100 |
||||
Subject: [PATCH 8/9] Misc code cleanups arising from Google analysis. |
||||
No security impleications or CVEs. |
||||
|
||||
--- |
||||
src/edns0.c | 2 +- |
||||
src/rfc1035.c | 4 +++- |
||||
src/rfc2131.c | 2 +- |
||||
3 files changed, 5 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c |
||||
index a8d0167..0552d38 100644 |
||||
--- a/src/edns0.c |
||||
+++ b/src/edns0.c |
||||
@@ -159,7 +159,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
/* delete option if we're to replace it. */ |
||||
p -= 4; |
||||
rdlen -= len + 4; |
||||
- memcpy(p, p+len+4, rdlen - i); |
||||
+ memmove(p, p+len+4, rdlen - i); |
||||
PUTSHORT(rdlen, lenp); |
||||
lenp -= 2; |
||||
} |
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c |
||||
index 78410d6..917bac2 100644 |
||||
--- a/src/rfc1035.c |
||||
+++ b/src/rfc1035.c |
||||
@@ -37,7 +37,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, |
||||
/* end marker */ |
||||
{ |
||||
/* check that there are the correct no of bytes after the name */ |
||||
- if (!CHECK_LEN(header, p, plen, extrabytes)) |
||||
+ if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes)) |
||||
return 0; |
||||
|
||||
if (isExtract) |
||||
@@ -485,6 +485,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header * |
||||
{ |
||||
unsigned int i, len = *p1; |
||||
unsigned char *p2 = p1; |
||||
+ if ((p1 + len - p) >= rdlen) |
||||
+ return 0; /* bad packet */ |
||||
/* make counted string zero-term and sanitise */ |
||||
for (i = 0; i < len; i++) |
||||
{ |
||||
diff --git a/src/rfc2131.c b/src/rfc2131.c |
||||
index 75893a6..71d5846 100644 |
||||
--- a/src/rfc2131.c |
||||
+++ b/src/rfc2131.c |
||||
@@ -155,7 +155,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, |
||||
for (offset = 0; offset < (len - 5); offset += elen + 5) |
||||
{ |
||||
elen = option_uint(opt, offset + 4 , 1); |
||||
- if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA) |
||||
+ if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len) |
||||
{ |
||||
unsigned char *x = option_ptr(opt, offset + 5); |
||||
unsigned char *y = option_ptr(opt, offset + elen + 5); |
||||
-- |
||||
2.9.5 |
||||
|
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
From d4f2e0b8d8f0b5daa0d468f62a0d5f1df58ac325 Mon Sep 17 00:00:00 2001 |
||||
From: Doran Moppert <dmoppert@redhat.com> |
||||
Date: Tue, 26 Sep 2017 14:48:20 +0930 |
||||
Subject: [PATCH 9/9] google patch hand-applied |
||||
|
||||
--- |
||||
src/edns0.c | 10 +++++----- |
||||
src/forward.c | 4 ++++ |
||||
src/rfc1035.c | 6 ++++-- |
||||
3 files changed, 13 insertions(+), 7 deletions(-) |
||||
|
||||
diff --git a/src/edns0.c b/src/edns0.c |
||||
index 0552d38..bec4a36 100644 |
||||
--- a/src/edns0.c |
||||
+++ b/src/edns0.c |
||||
@@ -212,11 +212,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l |
||||
/* Copy back any options */ |
||||
if (buff) |
||||
{ |
||||
- if (p + rdlen > limit) |
||||
- { |
||||
- free(buff); |
||||
- return plen; /* Too big */ |
||||
- } |
||||
+ if (p + rdlen > limit) |
||||
+ { |
||||
+ free(buff); |
||||
+ return plen; /* Too big */ |
||||
+ } |
||||
memcpy(p, buff, rdlen); |
||||
free(buff); |
||||
p += rdlen; |
||||
diff --git a/src/forward.c b/src/forward.c |
||||
index 0f8f462..a729c06 100644 |
||||
--- a/src/forward.c |
||||
+++ b/src/forward.c |
||||
@@ -1412,6 +1412,10 @@ void receive_query(struct listener *listen, time_t now) |
||||
udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */ |
||||
} |
||||
|
||||
+ // Make sure the udp size is not smaller than the incoming message so that we |
||||
+ // do not underflow |
||||
+ if (udp_size < n) udp_size = n; |
||||
+ |
||||
#ifdef HAVE_AUTH |
||||
if (auth_dns) |
||||
{ |
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c |
||||
index 917bac2..ae65702 100644 |
||||
--- a/src/rfc1035.c |
||||
+++ b/src/rfc1035.c |
||||
@@ -1182,8 +1182,8 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int |
||||
va_end(ap); /* clean up variable argument pointer */ |
||||
|
||||
j = p - sav - 2; |
||||
- /* this has already been checked against limit before */ |
||||
- PUTSHORT(j, sav); /* Now, store real RDLength */ |
||||
+ /* this has already been checked against limit before */ |
||||
+ PUTSHORT(j, sav); /* Now, store real RDLength */ |
||||
|
||||
/* check for overflow of buffer */ |
||||
if (limit && ((unsigned char *)limit - p) < 0) |
||||
@@ -1243,6 +1243,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, |
||||
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1; |
||||
struct mx_srv_record *rec; |
||||
size_t len; |
||||
+ // Make sure we do not underflow here too. |
||||
+ if (qlen > (limit - ((char *)header))) return 0; |
||||
|
||||
if (ntohs(header->ancount) != 0 || |
||||
ntohs(header->nscount) != 0 || |
||||
-- |
||||
2.9.5 |
||||
|
Loading…
Reference in new issue