File diff_release_1_8_2..44ee01c7.patch of Package radvd

diff --git a/CHANGES b/CHANGES
index 07ad3a5..7a4501e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+08/10/2011	More careful checking of iface name
+
+06/10/2011	Updating buffer usage tracking in send_ra to track buffer usage BEFORE
+		the buffer is used rather than after in order to prevent buffer overflow
+
 06/10/2011	1.8.2 release
 
 04/10/2011	1) A privilege escalation flaw was found in radvd, due to a buffer overflow
diff --git a/VERSION b/VERSION
index b60874f..db3aa84 100644
--- a/VERSION
+++ b/VERSION
@@ -3,4 +3,4 @@
 #
 # this file is automatically processed by configure
 #
-1.8.2
+1.8.3rc1
diff --git a/defaults.h b/defaults.h
index 55f44d5..72809d2 100644
--- a/defaults.h
+++ b/defaults.h
@@ -200,7 +200,7 @@ struct nd_opt_dnssl_info_local
 	uint8_t   			nd_opt_dnssli_len;
 	uint16_t   			nd_opt_dnssli_reserved;
 	uint32_t			nd_opt_dnssli_lifetime;
-	char				nd_opt_dnssli_suffixes[];
+	unsigned char			nd_opt_dnssli_suffixes[];
 };
 
 /* Flags */
diff --git a/device-linux.c b/device-linux.c
index c836f93..9187b4e 100644
--- a/device-linux.c
+++ b/device-linux.c
@@ -244,7 +244,7 @@ set_interface_var(const char *iface,
 		return -1;
 
 	/* No path traversal */
-	if (strstr(name, "..") || strchr(name, '/'))
+	if (!iface[0] || !strcmp(iface, ".") || !strcmp(iface, "..") || strchr(iface, '/'))
 		return -1;
 
 	if (access(spath, F_OK) != 0)
diff --git a/process.c b/process.c
index 581905e..6b99103 100644
--- a/process.c
+++ b/process.c
@@ -423,7 +423,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
 
 			suffix[0] = '\0';
 			for (offset = 0; offset < (dnsslinfo->nd_opt_dnssli_len-1)*8;) {
-				if (&dnsslinfo->nd_opt_dnssli_suffixes[offset] - (char*)opt_str >= len)
+				if (&dnsslinfo->nd_opt_dnssli_suffixes[offset] - opt_str >= len)
 					return;
 				label_len = dnsslinfo->nd_opt_dnssli_suffixes[offset++];
 
@@ -450,7 +450,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
 				 */
 				if ((sizeof(suffix) - strlen(suffix)) < (label_len + 2) ||
 				    label_len > label_len + 2 ||
-				    &dnsslinfo->nd_opt_dnssli_suffixes[offset+label_len] - (char*)opt_str >= len ||
+				    &dnsslinfo->nd_opt_dnssli_suffixes[offset+label_len] - opt_str >= len ||
 				    offset + label_len < offset) {
 					flog(LOG_ERR, "oversized suffix in DNSSL option on %s from %s",
 							iface->Name, addr_str);
@@ -459,7 +459,7 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
 
 				if (suffix[0] != '\0')
 					strcat(suffix, ".");
-				strncat(suffix, &dnsslinfo->nd_opt_dnssli_suffixes[offset], label_len);
+				strncat(suffix, (char*)&dnsslinfo->nd_opt_dnssli_suffixes[offset], label_len);
 				offset += label_len;
 			}
 			break;
diff --git a/radvdump.c b/radvdump.c
index 46ad609..07025f4 100644
--- a/radvdump.c
+++ b/radvdump.c
@@ -463,7 +463,7 @@ print_ff(unsigned char *msg, int len, struct sockaddr_in6 *addr, int hoplimit, u
 
 				if (suffix[0] != '\0')
 					strcat(suffix, ".");
-				strncat(suffix, &dnssl_info->nd_opt_dnssli_suffixes[offset], label_len);
+				strncat(suffix, (char*)&dnssl_info->nd_opt_dnssli_suffixes[offset], label_len);
 				offset += label_len;
 			}
 
diff --git a/send.c b/send.c
index b5ac52d..acdcfd6 100644
--- a/send.c
+++ b/send.c
@@ -72,7 +72,7 @@ send_ra_inc_len(size_t *len, int add)
 	*len += add;
 	if(*len >= MSG_SIZE_SEND)
 	{
-		flog(LOG_ERR, "Too many prefixes or routes. Exiting.");
+		flog(LOG_ERR, "Too many prefixes, routes, rdnss or dnssl to fit in buffer.  Exiting.");
 		exit(1);
 	}
 }
@@ -187,6 +187,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 	memset(buff, 0, sizeof(buff));
 	radvert = (struct nd_router_advert *) buff;
 
+	send_ra_inc_len(&len, sizeof(struct nd_router_advert));
+
 	radvert->nd_ra_type  = ND_ROUTER_ADVERT;
 	radvert->nd_ra_code  = 0;
 	radvert->nd_ra_cksum = 0;
@@ -212,8 +214,6 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 	radvert->nd_ra_reachable  = htonl(iface->AdvReachableTime);
 	radvert->nd_ra_retransmit = htonl(iface->AdvRetransTimer);
 
-	len = sizeof(struct nd_router_advert);
-
 	prefix = iface->AdvPrefixList;
 
 	/*
@@ -228,6 +228,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 
 			pinfo = (struct nd_opt_prefix_info *) (buff + len);
 
+			send_ra_inc_len(&len, sizeof(*pinfo));
+
 			pinfo->nd_opt_pi_type	     = ND_OPT_PREFIX_INFORMATION;
 			pinfo->nd_opt_pi_len	     = 4;
 			pinfo->nd_opt_pi_prefix_len  = prefix->PrefixLen;
@@ -260,8 +262,6 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 			}
 			pinfo->nd_opt_pi_reserved2	= 0;
 
-			send_ra_inc_len(&len, sizeof(*pinfo));
-
 			memcpy(&pinfo->nd_opt_pi_prefix, &prefix->Prefix,
 			       sizeof(struct in6_addr));
 		}
@@ -281,6 +281,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 
 		rinfo = (struct nd_opt_route_info_local *) (buff + len);
 
+		send_ra_inc_len(&len, sizeof(*rinfo));
+
 		rinfo->nd_opt_ri_type	     = ND_OPT_ROUTE_INFORMATION;
 		/* XXX: the prefixes are allowed to be sent in smaller chunks as well */
 		rinfo->nd_opt_ri_len	     = 3;
@@ -294,8 +296,6 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 			rinfo->nd_opt_ri_lifetime	= htonl(route->AdvRouteLifetime);
 		}
 
-		send_ra_inc_len(&len, sizeof(*rinfo));
-
 		memcpy(&rinfo->nd_opt_ri_prefix, &route->Prefix,
 		       sizeof(struct in6_addr));
 
@@ -314,6 +314,8 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 
 		rdnssinfo = (struct nd_opt_rdnss_info_local *) (buff + len);
 
+		send_ra_inc_len(&len, sizeof(*rdnssinfo) - (3-rdnss->AdvRDNSSNumber)*sizeof(struct in6_addr));
+
 		rdnssinfo->nd_opt_rdnssi_type	     = ND_OPT_RDNSS_INFORMATION;
 		rdnssinfo->nd_opt_rdnssi_len	     = 1 + 2*rdnss->AdvRDNSSNumber;
 		rdnssinfo->nd_opt_rdnssi_pref_flag_reserved = 0;
@@ -330,7 +332,6 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 		       sizeof(struct in6_addr));
 		memcpy(&rdnssinfo->nd_opt_rdnssi_addr3, &rdnss->AdvRDNSSAddr3,
 		       sizeof(struct in6_addr));
-		send_ra_inc_len(&len, sizeof(*rdnssinfo) - (3-rdnss->AdvRDNSSNumber)*sizeof(struct in6_addr));
 
 		rdnss = rdnss->next;
 	}
@@ -344,13 +345,18 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 	while(dnssl)
 	{
 		struct nd_opt_dnssl_info_local *dnsslinfo;
+		int const start_len = len;
 		int i;
-		char *buff_ptr;
 
 		dnsslinfo = (struct nd_opt_dnssl_info_local *) (buff + len);
 
+		send_ra_inc_len(&len, sizeof(dnsslinfo->nd_opt_dnssli_type) + 
+			sizeof(dnsslinfo->nd_opt_dnssli_len) +
+			sizeof(dnsslinfo->nd_opt_dnssli_reserved) +
+			sizeof(dnsslinfo->nd_opt_dnssli_lifetime)
+		);
+
 		dnsslinfo->nd_opt_dnssli_type		= ND_OPT_DNSSL_INFORMATION;
-		dnsslinfo->nd_opt_dnssli_len 		= 1; /* more further down */
 		dnsslinfo->nd_opt_dnssli_reserved	= 0;
 
 		if (iface->cease_adv && dnssl->FlushDNSSLFlag) {
@@ -359,7 +365,6 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 			dnsslinfo->nd_opt_dnssli_lifetime	= htonl(dnssl->AdvDNSSLLifetime);
 		}
 
-		buff_ptr = dnsslinfo->nd_opt_dnssli_suffixes;
 		for (i = 0; i < dnssl->AdvDNSSLNumber; i++) {
 			char *label;
 			int label_len;
@@ -372,24 +377,32 @@ send_ra(struct Interface *iface, struct in6_addr *dest)
 				else
 					label_len = strchr(label, '.') - label;
 
-				*buff_ptr++ = label_len;
+				buff_dest = len;
+				send_ra_inc_len(&len, 1);
+				buff[buff_dest] = label_len;
 
-				memcpy(buff_ptr, label, label_len);
-				buff_ptr += label_len;
+				buff_dest = len;
+				send_ra_inc_len(&len, label_len);
+				memcpy(buff + buff_dest, label, label_len);
 
 				label += label_len;
 
 				if (label[0] == '.')
 					label++;
-				else
-					*buff_ptr++ = 0;
+				else {
+					buff_dest = len;
+					send_ra_inc_len(&len, 1);
+					buff[buff_dest] = 0;
+				}
 			}
 		}
 
-		dnsslinfo->nd_opt_dnssli_len		+= ((buff_ptr-dnsslinfo->nd_opt_dnssli_suffixes)+7)/8;
+		dnsslinfo->nd_opt_dnssli_len = (len - start_len) / 8;
 
-		/* TODO: If buff will overflow, it's already happened.  This needs to be checked BEFORE the overflow. */
-		send_ra_inc_len(&len, dnsslinfo->nd_opt_dnssli_len * 8);
+		if ( (len - start_len) % 8 != 0 ) {
+			send_ra_inc_len(&len, 8 - (len - start_len) % 8);
+			++dnsslinfo->nd_opt_dnssli_len;
+		}
 
 		dnssl = dnssl->next;
 	}
openSUSE Build Service is sponsored by