[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