[ $ret -eq 0 ] || echo "I:failed"
status=`expr $status + $ret`
+# stomp on the file header
+echo "I:checking corrupt map files fail to load (bad file header)"
+ret=0
+./named-compilezone -D -f text -F map -o map.5 example.nil baseline.txt > /dev/null
+cp map.5 badmap
+stomp badmap 0 32 99
+./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null
+[ $? = 1 ] || ret=1
+[ $ret -eq 0 ] || echo "I:failed"
+status=`expr $status + $ret`
# stomp on the file data so it hashes differently.
# these are small and subtle changes, so that the resulting file
# would appear to be a legitimate map file and would not trigger an
# load because of a SHA1 hash mismatch.
echo "I:checking corrupt map files fail to load (bad node header)"
ret=0
-./named-compilezone -D -f text -F map -o map.5 example.nil baseline.txt > /dev/null
cp map.5 badmap
stomp badmap 2754 2 99
./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null
#include <isc/file.h>
#include <isc/hex.h>
#include <isc/mem.h>
+#include <isc/once.h>
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/refcount.h>
write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
isc_uint64_t crc);
+static isc_boolean_t
+match_header_version(file_header_t *header);
+
static isc_result_t
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
uintptr_t right, uintptr_t down, uintptr_t parent,
return (ISC_R_SUCCESS);
}
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+init_file_version(void) {
+ int n;
+
+ memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
+ n = snprintf(FILE_VERSION, sizeof(FILE_VERSION),
+ "RBT Image %s %s", dns_major, dns_mapapi);
+ INSIST(n > 0 && (unsigned int)n < sizeof(FILE_VERSION));
+}
+
/*
* Write out the real header, including NodeDump version information
* and the offset of the first node.
isc_result_t result;
off_t location;
- if (FILE_VERSION[0] == '\0') {
- memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
- snprintf(FILE_VERSION, sizeof(FILE_VERSION),
- "RBT Image %s %s", dns_major, dns_mapapi);
- }
+ RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
memset(&header, 0, sizeof(file_header_t));
memmove(header.version1, FILE_VERSION, sizeof(header.version1));
return (result);
}
+static isc_boolean_t
+match_header_version(file_header_t *header) {
+ RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
+
+ if (memcmp(header->version1, FILE_VERSION,
+ sizeof(header->version1)) != 0 ||
+ memcmp(header->version2, FILE_VERSION,
+ sizeof(header->version1)) != 0)
+ {
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
+
static isc_result_t
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
uintptr_t right, uintptr_t down, uintptr_t parent,
#endif
isc_crc64_update(crc, (const isc_uint8_t *) &temp_node,
- sizeof(dns_rbtnode_t));
+ sizeof(dns_rbtnode_t));
isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize);
cleanup:
rbt->mmap_location = base_address;
header = (file_header_t *)((char *)base_address + header_offset);
+ if (!match_header_version(header)) {
+ result = ISC_R_INVALIDFILE;
+ goto cleanup;
+ }
#ifdef DNS_RDATASET_FIXED
if (header->rdataset_fixed != 1) {
static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version);
static void setownercase(rdatasetheader_t *header, const dns_name_t *name);
+static isc_boolean_t match_header_version(rbtdb_file_header_t *header);
+
/* Pad to 32 bytes */
static char FILE_VERSION[32] = "\0";
#endif
base = isc_file_mmap(NULL, filesize, protect, flags, fd, 0);
- if (base == NULL || base == MAP_FAILED)
+ if (base == NULL || base == MAP_FAILED) {
return (ISC_R_FAILURE);
+ }
header = (rbtdb_file_header_t *)(base + offset);
+ if (!match_header_version(header)) {
+ return (ISC_R_FAILURE);
+ }
if (header->tree != 0) {
result = dns_rbt_deserialize_tree(base, filesize,
return (result);
}
+static isc_boolean_t
+match_header_version(rbtdb_file_header_t *header) {
+ RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
+
+ if (memcmp(header->version1, FILE_VERSION,
+ sizeof(header->version1)) != 0 ||
+ memcmp(header->version2, FILE_VERSION,
+ sizeof(header->version1)) != 0)
+ {
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
+
static isc_result_t
serialize(dns_db_t *db, dns_dbversion_t *ver, FILE *rbtfile) {
rbtdb_version_t *version = (rbtdb_version_t *) ver;