mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Handle integer overflow in uid counter. Fixes rare crashes in cache code.
This commit is contained in:
27
src/cache.c
27
src/cache.c
@@ -24,7 +24,6 @@ static struct crec *new_chain = NULL;
|
||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||
static union bigname *big_free = NULL;
|
||||
static int bignames_left, hash_size;
|
||||
static int uid = 1;
|
||||
|
||||
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||
static const struct {
|
||||
@@ -73,6 +72,17 @@ static void cache_link(struct crec *crecp);
|
||||
static void rehash(int size);
|
||||
static void cache_hash(struct crec *crecp);
|
||||
|
||||
static unsigned int next_uid(void)
|
||||
{
|
||||
static unsigned int uid = 1;
|
||||
|
||||
/* uid == 0 used to indicate CNAME to interface name. */
|
||||
if (uid == 0)
|
||||
uid++;
|
||||
|
||||
return uid++;
|
||||
}
|
||||
|
||||
void cache_init(void)
|
||||
{
|
||||
struct crec *crecp;
|
||||
@@ -88,7 +98,7 @@ void cache_init(void)
|
||||
{
|
||||
cache_link(crecp);
|
||||
crecp->flags = 0;
|
||||
crecp->uid = uid++;
|
||||
crecp->uid = next_uid();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,10 +202,7 @@ static void cache_free(struct crec *crecp)
|
||||
{
|
||||
crecp->flags &= ~F_FORWARD;
|
||||
crecp->flags &= ~F_REVERSE;
|
||||
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
|
||||
|
||||
if (uid == -1)
|
||||
uid++;
|
||||
crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
|
||||
|
||||
if (cache_tail)
|
||||
cache_tail->next = crecp;
|
||||
@@ -256,7 +263,7 @@ char *cache_get_name(struct crec *crecp)
|
||||
|
||||
char *cache_get_cname_target(struct crec *crecp)
|
||||
{
|
||||
if (crecp->addr.cname.uid != -1)
|
||||
if (crecp->addr.cname.uid != 0)
|
||||
return cache_get_name(crecp->addr.cname.target.cache);
|
||||
|
||||
return crecp->addr.cname.target.int_name->name;
|
||||
@@ -289,7 +296,7 @@ struct crec *cache_enumerate(int init)
|
||||
|
||||
static int is_outdated_cname_pointer(struct crec *crecp)
|
||||
{
|
||||
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
|
||||
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == 0)
|
||||
return 0;
|
||||
|
||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||
@@ -1034,7 +1041,7 @@ void cache_reload(void)
|
||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||
cache->name.namep = a->alias;
|
||||
cache->addr.cname.target.int_name = intr;
|
||||
cache->addr.cname.uid = -1;
|
||||
cache->addr.cname.uid = 0;
|
||||
cache_hash(cache);
|
||||
add_hosts_cname(cache); /* handle chains */
|
||||
}
|
||||
@@ -1242,7 +1249,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
crec->ttd = ttd;
|
||||
crec->addr.addr = *host_address;
|
||||
crec->name.namep = host_name;
|
||||
crec->uid = uid++;
|
||||
crec->uid = next_uid();
|
||||
cache_hash(crec);
|
||||
|
||||
add_dhcp_cname(crec, ttd);
|
||||
|
||||
@@ -367,7 +367,7 @@ struct crec {
|
||||
struct crec *cache;
|
||||
struct interface_name *int_name;
|
||||
} target;
|
||||
int uid; /* -1 if union is interface-name */
|
||||
unsigned int uid; /* 0 if union is interface-name */
|
||||
} cname;
|
||||
struct {
|
||||
struct blockdata *keydata;
|
||||
@@ -388,7 +388,7 @@ struct crec {
|
||||
} addr;
|
||||
time_t ttd; /* time to die */
|
||||
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
||||
int uid;
|
||||
unsigned int uid;
|
||||
unsigned short flags;
|
||||
union {
|
||||
char sname[SMALLDNAME];
|
||||
|
||||
@@ -827,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
||||
for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
|
||||
if (crecp->addr.key.algo == algo &&
|
||||
crecp->addr.key.keytag == key_tag &&
|
||||
crecp->uid == class &&
|
||||
crecp->uid == (unsigned int)class &&
|
||||
verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
|
||||
return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
|
||||
}
|
||||
@@ -932,7 +932,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
||||
|
||||
if (recp1->addr.ds.algo == algo &&
|
||||
recp1->addr.ds.keytag == keytag &&
|
||||
recp1->uid == class &&
|
||||
recp1->uid == (unsigned int)class &&
|
||||
(hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
|
||||
hash_init(hash, &ctx, &digest))
|
||||
|
||||
|
||||
@@ -1456,7 +1456,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
{
|
||||
char *name = daemon->namebuff;
|
||||
unsigned char *p, *ansp, *pheader;
|
||||
int qtype, qclass;
|
||||
unsigned int qtype, qclass;
|
||||
struct all_addr addr;
|
||||
int nameoffset;
|
||||
unsigned short flag;
|
||||
@@ -2016,7 +2016,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
|
||||
strcpy(name, cname_target);
|
||||
/* check if target interface_name */
|
||||
if (crecp->addr.cname.uid == -1)
|
||||
if (crecp->addr.cname.uid == 0)
|
||||
goto intname_restart;
|
||||
else
|
||||
goto cname_restart;
|
||||
|
||||
Reference in New Issue
Block a user