Commit 5b69d3da authored by Evan Hunt's avatar Evan Hunt
Browse files

[master] check file and tree headers when loading map files

4792.	[bug]		Fix map file header correctness check. [RT #38418]
parent 89d17775
4792. [bug] Fix map file header correctness check. [RT #38418]
4791. [doc] Fixed outdated documentation about export libraries.
[RT #46341]
 
......
......@@ -238,6 +238,16 @@ done
[ $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
......@@ -245,7 +255,6 @@ status=`expr $status + $ret`
# 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
......
......@@ -21,6 +21,7 @@
#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>
......@@ -138,6 +139,9 @@ static isc_result_t
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,
......@@ -483,6 +487,18 @@ dns_rbt_zero_header(FILE *file) {
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.
......@@ -498,11 +514,7 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
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));
......@@ -534,6 +546,21 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
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,
......@@ -608,7 +635,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
#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:
......@@ -880,6 +907,10 @@ dns_rbt_deserialize_tree(void *base_address, size_t filesize,
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) {
......
......@@ -900,6 +900,8 @@ static void overmem(dns_db_t *db, isc_boolean_t over);
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";
......@@ -7479,10 +7481,14 @@ deserialize32(void *arg, FILE *f, off_t offset) {
#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,
......@@ -7786,6 +7792,21 @@ rbtdb_write_header(FILE *rbtfile, off_t tree_location, off_t nsec_location,
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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment