[BIND-BUGS #4082] [823] forwarder setting with NetBSD/sparc

Mark.Andrews at nominum.com Mark.Andrews at nominum.com
Tue Feb 6 06:53:57 UTC 2001


	While this was a problem it would not have caused a problem with
	a config where the forwarders were not changed as the reference
	count would never get to zero.  

	Mark

Index: CHANGES
RCS file: /proj/cvs/isc/bind8/src/CHANGES,v
retrieving revision 8.756
diff -u -r8.756 CHANGES
--- CHANGES	2001/02/04 13:10:44	8.756
+++ CHANGES	2001/02/06 06:41:24
@@ -1,3 +1,5 @@
+1150.	[bug]		forwarders: it was possible to use freed memory.
+
 1149.	[support]	zone rejected message to error level.
 
 1148.	[bug]		non-glue now logged to category load.
Index: bin/named/db_dump.c
===================================================================
RCS file: /proj/cvs/isc/bind8/src/bin/named/db_dump.c,v
retrieving revision 8.48
diff -u -r8.48 db_dump.c
--- db_dump.c	2000/12/23 08:14:34	8.48
+++ db_dump.c	2001/02/06 06:41:27
@@ -217,11 +217,13 @@
 static int
 fwd_dump(FILE *fp) {
 	int i;
+
 	fprintf(fp, ";; ++forwarders table++\n");
-	for (i=0;i<fwddata_count;i++) {
-		fprintf(fp,"; %s rtt=%d\n",
-			inet_ntoa(fwddata[i]->fwdaddr.sin_addr),
-			fwddata[i]->nsdata->d_nstime);
+	for (i = 0; i < fwddata_count; i++) {
+		if (fwddata[i] != NULL)
+			fprintf(fp,"; %s rtt=%d\n",
+				inet_ntoa(fwddata[i]->fwdaddr.sin_addr),
+				fwddata[i]->nsdata->d_nstime);
 	}
 	fprintf(fp, ";; --forwarders table--\n");
 	return (0);
Index: bin/named/ns_config.c
===================================================================
RCS file: /proj/cvs/isc/bind8/src/bin/named/ns_config.c,v
retrieving revision 8.119
diff -u -r8.119 ns_config.c
--- ns_config.c	2001/01/29 04:50:34	8.119
+++ ns_config.c	2001/02/06 06:41:36
@@ -1529,7 +1529,6 @@
 static int interface_interval = 0;
 static int stats_interval = 0;
 static int heartbeat_interval = 0;
-static int active_interval = 0;
 
 static void
 set_interval_timer(int which_timer, int interval) {
@@ -2279,41 +2278,59 @@
 find_forwarder(struct in_addr address)
 {
 	struct fwddata *fdp;
+	struct fwddata **fdpp = NULL;
 	struct databuf *ns, *nsdata;
 	register int i;
 
-	for (i=0;i<fwddata_count; i++) {
-		fdp=fwddata[i];
-		if (memcmp(&fdp->fwdaddr.sin_addr,&address,sizeof(address))==0) {
+	for (i = 0; i < fwddata_count; i++) {
+		fdp = fwddata[i];
+		if (fdp == NULL) {
+			if (fdpp == NULL)
+				fdpp = &fwddata[i];
+			continue;
+		}
+		if (memcmp(&fdp->fwdaddr.sin_addr, &address,
+			   sizeof(address)) == 0) {
 			fdp->ref_count++;
-			return fdp;
+			return (fdp);
 		}
 	}
 
 	fdp = (struct fwddata *)memget(sizeof(struct fwddata));
 	if (!fdp)
 		panic("memget failed in find_forwarder", NULL);
+
 	fdp->fwdaddr.sin_family = AF_INET;
 	fdp->fwdaddr.sin_addr = address;
 	fdp->fwdaddr.sin_port = ns_port;
+
 	ns = fdp->ns = (struct databuf *)memget(sizeof(*ns));
 	if (!ns)
 		panic("memget failed in find_forwarder", NULL);
-	memset(ns,0,sizeof(*ns));
+	memset(ns, 0, sizeof(*ns));
+
 	nsdata = fdp->nsdata = (struct databuf *)memget(sizeof(*nsdata));
 	if (!nsdata)
 		panic("memget failed in find_forwarder", NULL);
-	memset(nsdata,0,sizeof(*nsdata));
+	memset(nsdata, 0, sizeof(*nsdata));
+
 	ns->d_type = T_NS; 
 	ns->d_class = C_IN;
-	ns->d_rcnt=1;
+	ns->d_rcnt = 1;
+
 	nsdata->d_type = T_A;
 	nsdata->d_class = C_IN;
 	nsdata->d_nstime = 1 + (int)(25.0*rand()/(RAND_MAX + 1.0));
-	nsdata->d_rcnt=1;
-	fdp->ref_count=1;
+	nsdata->d_rcnt = 1;
+
+	fdp->ref_count = 1;
+
+	if (fdpp != NULL) {
+		*fdpp = fdp;
+		return (fdp);
+	}
 	
-	i=0;
+	i = 0;
 	if (fwddata == NULL) {
 		fwddata = memget(sizeof *fwddata);
 		if (fwddata == NULL)
@@ -2321,6 +2338,7 @@
 	} else {
 		register size_t size;
 		register struct fwddata **an_tmp;
+
 		size = fwddata_count * sizeof *fwddata;
 		an_tmp = memget(size + sizeof *fwddata);
 		if (an_tmp == NULL) {
@@ -2336,13 +2354,13 @@
 		fwddata[fwddata_count] = fdp;
 		fwddata_count++;
 	} else {
-		ns_warning(ns_log_config,
-		     "forwarder add failed (memget) [%s]",
-			inet_ntoa(address));
+		ns_warning(ns_log_config, "forwarder add failed (memget) [%s]",
+			   inet_ntoa(address));
 	}
 
-	return fdp;
+	return (fdp);
 }
+
 /*
  * Forwarder glue
  *
@@ -2480,14 +2498,20 @@
 void
 free_forwarders(struct fwdinfo *fwdtab) {
 	struct fwdinfo *ftp, *fnext;
+	int i;
 
 	for (ftp = fwdtab; ftp != NULL; ftp = fnext) {
 		fnext = ftp->next;
-		if (!--ftp->fwddata->ref_count) {
+		if (--ftp->fwddata->ref_count == 0) {
+			for (i = 0 ; i < fwddata_count; i++)
+				if (fwddata[i] == ftp->fwddata) {
+					fwddata[i] = NULL;
+					break;
+				}
 			memput(ftp->fwddata->ns, sizeof *ftp->fwddata->ns);
 			memput(ftp->fwddata->nsdata,
 					sizeof *ftp->fwddata->nsdata);
-			memput(ftp->fwddata,sizeof *ftp->fwddata);
+			memput(ftp->fwddata, sizeof *ftp->fwddata);
 		}
 		memput(ftp, sizeof *ftp);
 	}
> 	with BIND823 on on NetBSD/sparc, there are problem reports like this:
> 	http://www.NetBSD.org/cgi-bin/query-pr-single.pl?number=12128
> 	to sumamrize, if we set multiple forwarders into named.conf, named
> 	will coredump. (there's some report that it does not happen on i386).
> 
> 	i looked at the code briefly, and found a possible source of problem.
> 	it would be good if you can check if my reasoning is correct.
> 
> 
> 	global variable fwddata[] keeps the all list forwarder data,
> 	created in find_forwarder().  fwddata->ref_count (in struct fwddata)
> 	does not count the pointer from fwddata.
> 
> 	when ftp->fwddata->ref_count reaches 0, we free ftp->fwddata
> 	(ns_config.c near line 2400).  we do not cleanup pointers from
> 	fwddata[] for this particular item, therefore, we leave a dangling
> 	pointer in fwddata[].
> 
> 	next time we visit find_forwarder(), we have possibility to touch
> 	dangling pointer in fwddata[].  the pointer would be returned to
> 	the caller of find_forwarder if we are (un)lucky, and the pointer
> 	will be kept into ftp->fwddata.  when the region gets reused, we will
> 	see coredump.
> 
> 
> 	solution would be to cleanup pointer from fwddata[], when a fwddata
> 	item goes away.
> 
> itojun
> 
--
Mark Andrews, Nominum Inc.
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742                 INTERNET: Mark.Andrews at nominum.com


More information about the bind-workers mailing list