There is a heap overflow in "read_file". It can be triggered if the file it 
wants to read is not a valid conf file and it has very long name. Notice that 
it can also be trigger through function "clear_cache_and_reload" which is 
called in some event handlers. So it might be able to be triggered remotely(do 
not have a poc).

poc(target: git://thekelleys.org.uk/dnsmasq.git 
(https://link.getmailspring.com/link/fc759e02-cf53-4055-abfc-17b291078...@getmailspring.com/0?redirect=git%3A%2F%2Fthekelleys.org.uk%2Fdnsmasq.git&recipient=ZG5zbWFzcS1kaXNjdXNzQGxpc3RzLnRoZWtlbGxleXMub3JnLnVr),
 commit: e24abf28a29574069717af78c1d3e0ede64388ff, compilation command: 
CC="clang -fsanitize=address" make):
folder=$(python -c "print(('B'*100+'/')*10)"); mkdir -p $folder && echo "111" > 
$folder/config && ./dnsmasq -p 8333 -C $folder/config -d

The bug is in line 4586 of options.c.
Here is the snippet :
-------
oops:
if (errmess)
strcpy(daemon->namebuff, errmess);

if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt 
== LOPT_REV_SERV))
{
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), 
lineno, file);
if (hard_opt != 0)
my_syslog(LOG_ERR, "%s", daemon->namebuff);
else
die("%s", daemon->namebuff, EC_BADCONF);
}
--------
Analysis:
If oops is triggered, an error message will be copied into the 
daemon->namebuff. And then a sprintf will be triggered to append a detailed 
error message.
However, the namebuff is of length MAXDNAME and file is also of length 
MAXDNAME. So, overflow happens.

Suggested fix:
------
diff --git a/src/option.c b/src/option.c
index 83d57a6..24e77e4 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4583,7 +4583,8 @@ static void read_file(char *file, FILE *f, int hard_opt)

if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt 
== LOPT_REV_SERV))
{
- sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), 
lineno, file);
+ size_t buf_len = strlen(daemon->namebuff);
+ snprintf(daemon->namebuff + buf_len, MAXDNAME-buf_len, _(" at line %d of 
%s"), lineno, file);
if (hard_opt != 0)
my_syslog(LOG_ERR, "%s", daemon->namebuff);
else
------

Yihui Zeng
_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to