summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2014-03-14 16:01:57 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2014-03-14 16:01:57 +0000
commit484d8522231c1b7bacc638b0b84d502e4231886a (patch)
tree9ef06b5e7ac887a9a14c095744236d7082b2ed61
parent6ad247cd626ea34f6cb942bf33053b788613b984 (diff)
Update to NSD 4.0.3, main change is to improve/fix nsd.db database
corruption checks and avoid some causes of corruption. More details at http://article.gmane.org/gmane.network.dns.nsd.general/1687
-rw-r--r--usr.sbin/nsd/dbaccess.c1
-rw-r--r--usr.sbin/nsd/nsd-control.8.in2
-rw-r--r--usr.sbin/nsd/udb.c32
-rw-r--r--usr.sbin/nsd/udb.h5
4 files changed, 34 insertions, 6 deletions
diff --git a/usr.sbin/nsd/dbaccess.c b/usr.sbin/nsd/dbaccess.c
index 70366b058e9..4ecbf7a990b 100644
--- a/usr.sbin/nsd/dbaccess.c
+++ b/usr.sbin/nsd/dbaccess.c
@@ -42,6 +42,7 @@ namedb_close(struct namedb* db)
if(db->udb) {
udb_base_close(db->udb);
udb_base_free(db->udb);
+ db->udb = NULL;
}
zonec_desetup_parser();
region_destroy(db->region);
diff --git a/usr.sbin/nsd/nsd-control.8.in b/usr.sbin/nsd/nsd-control.8.in
index 6e176e1665c..b8a8701bea5 100644
--- a/usr.sbin/nsd/nsd-control.8.in
+++ b/usr.sbin/nsd/nsd-control.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "Mar 12, 2014" "NLnet Labs" "nsd 4.0.2"
+.TH "nsd\-control" "8" "Mar 14, 2014" "NLnet Labs" "nsd 4.0.3"
.\" Copyright (c) 2011, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/udb.c b/usr.sbin/nsd/udb.c
index 02c81973942..c3b1de0347c 100644
--- a/usr.sbin/nsd/udb.c
+++ b/usr.sbin/nsd/udb.c
@@ -70,7 +70,7 @@ udb_base*
udb_base_create_fd(const char* fname, int fd, udb_walk_relptr_func walkfunc,
void* arg)
{
- uint64_t m;
+ uint64_t m, fsz;
udb_glob_d g;
ssize_t r;
udb_base* udb = (udb_base*)xalloc_zero(sizeof(*udb));
@@ -136,7 +136,7 @@ udb_base_create_fd(const char* fname, int fd, udb_walk_relptr_func walkfunc,
(int)g.hsize);
goto fail;
}
- if(g.clean_close != 0) {
+ if(g.clean_close != 1) {
log_msg(LOG_WARNING, "%s: not cleanly closed %d", fname,
(int)g.clean_close);
goto fail;
@@ -146,13 +146,27 @@ udb_base_create_fd(const char* fname, int fd, udb_walk_relptr_func walkfunc,
(int)g.dirty_alloc);
goto fail;
}
- /* TODO check if too large (>4g on 32bit); mmap-usage would fail */
-
+
+ /* check file size correctly written, for 4.0.2 nsd.db failure */
+ fsz = (uint64_t)lseek(fd, (off_t)0, SEEK_END);
+ (void)lseek(fd, (off_t)0, SEEK_SET);
+ if(g.fsize != fsz) {
+ log_msg(LOG_WARNING, "%s: file size %llu but mmap header "
+ "has size %llu", fname, (unsigned long long)fsz,
+ (unsigned long long)g.fsize);
+ goto fail;
+ }
+
/* mmap it */
if(g.fsize < UDB_HEADER_SIZE || g.fsize < g.hsize) {
log_msg(LOG_ERR, "%s: file too short", fname);
goto fail;
}
+ if(g.fsize > (uint64_t)400*1024*1024*1024*1024) /* 400 Tb */ {
+ log_msg(LOG_WARNING, "%s: file size too large %llu",
+ fname, (unsigned long long)g.fsize);
+ goto fail;
+ }
udb->base_size = (size_t)g.fsize;
/* note the size_t casts must be there for portability, on some
* systems the layout of memory is otherwise broken. */
@@ -189,6 +203,7 @@ udb_base_create_fd(const char* fname, int fd, udb_walk_relptr_func walkfunc,
udb_alloc_compact(udb, udb->alloc);
udb_base_sync(udb, 1);
}
+ udb->glob_data->clean_close = 0;
return udb;
}
@@ -245,6 +260,7 @@ udb_base* udb_base_create_new(const char* fname, udb_walk_relptr_func walkfunc,
m = UDB_MAGIC;
udb_glob_init_new(&g);
udb_alloc_init_new(&a);
+ g.clean_close = 1;
/* write new data to file (closes fd on error) */
if(!write_fdata(fname, fd, &m, sizeof(m)))
@@ -263,6 +279,13 @@ udb_base* udb_base_create_new(const char* fname, udb_walk_relptr_func walkfunc,
close(fd);
return NULL;
}
+ /* truncate to the right size */
+ if(ftruncate(fd, (off_t)g.fsize) < 0) {
+ log_msg(LOG_ERR, "%s: ftruncate(%d): %s", fname,
+ (int)g.fsize, strerror(errno));
+ close(fd);
+ return NULL;
+ }
return udb_base_create_fd(fname, fd, walkfunc, arg);
}
@@ -292,6 +315,7 @@ void udb_base_close(udb_base* udb)
udb_base_shrink(udb, nsize);
}
if(udb->fd != -1) {
+ udb->glob_data->clean_close = 1;
close(udb->fd);
udb->fd = -1;
}
diff --git a/usr.sbin/nsd/udb.h b/usr.sbin/nsd/udb.h
index de7985275c2..691b78c817f 100644
--- a/usr.sbin/nsd/udb.h
+++ b/usr.sbin/nsd/udb.h
@@ -40,10 +40,13 @@
typedef struct udb_base udb_base;
typedef struct udb_alloc udb_alloc;
+/** these checks are very slow, disabled by default */
+#if 0
/** perform extra checks (when --enable-checking is used) */
#ifndef NDEBUG
#define UDB_CHECK 1
#endif
+#endif
/** pointers are stored like this */
typedef uint64_t udb_void;
@@ -141,7 +144,7 @@ struct udb_glob_d {
uint64_t hsize;
/** version number of this file */
uint8_t version;
- /** was the file not cleanly closed, 0 is ok */
+ /** was the file cleanly closed, 0 is not clean, 1 is clean */
uint8_t clean_close;
/** an allocation operation was in progress, file needs to be salvaged
* type enum udb_dirty_alloc */