summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-01-14 00:01:06 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-01-14 00:01:06 +0000
commit22aa740106d6669c581408df8c09222df40e0f46 (patch)
treeda155f024bdb70b1c4a82e99bfbcc9f366866477
parent7b753522c0b9fbf9f60fcf2648ffb6a5e5742c88 (diff)
parent6e5dfb83fd803babad8092062bdccace7c3298d2 (diff)
downloaddnsmasq-android11-mainline-captiveportallogin-release.tar.gz
Snap for 7080740 from 6e5dfb83fd803babad8092062bdccace7c3298d2 to mainline-captiveportallogin-releaseandroid-mainline-11.0.0_r36android-mainline-11.0.0_r30android-mainline-11.0.0_r12android11-mainline-captiveportallogin-release
Change-Id: I748dd1a38fa8050998042d3c6a0439e4fe5aecb2
-rw-r--r--src/dnsmasq.h2
-rw-r--r--src/rfc1035.c28
-rw-r--r--src/rfc2131.c4
-rw-r--r--src/util.c11
4 files changed, 37 insertions, 8 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 2c5f964..9af3a2c 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -684,7 +684,7 @@ void rand_init(void);
unsigned short rand16(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/rfc1035.c b/src/rfc1035.c
index 0f883e1..47479ab 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -847,9 +847,19 @@ static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigne
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);
+
PUTSHORT(nameoffset | 0xc000, p);
PUTSHORT(type, p);
PUTSHORT(class, p);
@@ -858,11 +868,10 @@ static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigne
sav = p; /* Save pointer to RDLength field */
PUTSHORT(0, p); /* Placeholder RDLength */
- va_start(ap, format); /* make ap point to 1st unamed argument */
-
for (; *format; format++) switch (*format) {
#ifdef HAVE_IPV6
case '6':
+ CHECK_LIMIT(IN6ADDRSZ);
sval = va_arg(ap, char*);
memcpy(p, sval, IN6ADDRSZ);
p += IN6ADDRSZ;
@@ -870,17 +879,20 @@ static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigne
#endif
case '4':
+ CHECK_LIMIT(INADDRSZ);
sval = va_arg(ap, char*);
memcpy(p, sval, INADDRSZ);
p += INADDRSZ;
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;
@@ -888,12 +900,18 @@ static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigne
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 = 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*);
memcpy(p, sval, usval);
p += usval;
@@ -903,19 +921,23 @@ static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigne
sval = va_arg(ap, char*);
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;
+ /* 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 f74ecb9..c0f649a 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -1889,8 +1889,8 @@ static void do_options(struct dhcp_context* context, struct dhcp_packet* mess, u
*(p++) = 255;
if (fqdn_flags & 0x04) {
- p = do_rfc1035_name(p, hostname);
- if (domain) p = do_rfc1035_name(p, domain);
+ p = do_rfc1035_name(p, hostname, NULL);
+ if (domain) p = do_rfc1035_name(p, domain, NULL);
*p++ = 0;
} else {
memcpy(p, hostname, strlen(hostname));
diff --git a/src/util.c b/src/util.c
index 53e3137..11b43a0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -190,12 +190,19 @@ 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++) *p++ = *sval;
+ for (j = 0; *sval && (*sval != '.'); sval++, j++) {
+ if (limit && p + 1 > (unsigned char*)limit)
+ return p;
+ *p++ = *sval;
+ }
*cp = j;
if (*sval) sval++;
}