It's from the current master branch:
commit 5dc14b6e05f39a5ab0dc02e376b1d7da2fda5bc1 (HEAD -> master, tag: v2.89)

On Mon, 2023-03-06 at 16:11 +0000, Simon Kelley wrote:
> 
> Thanks for the comprehensive analysis.
> 
> You don't mention what version of dnsmasq you were testing.
> 
> 
> I think that this was fixed in release 2.88, the commit is:
> 
> https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=2fc904111d9b6ec45fc1e4ec9f1f8b43c1e67b9b
> 
> If you were testing 2.88 or 2.89 then we'll need to look again.
> 
> 
> 
> Cheers,
> 
> Simon.
> 
> On 01/03/2023 15:58, Daniel Danzberger wrote:
> > Hi,
> > 
> > the segfault occurs when a custom 'server=/domain.test/#' entry is defined 
> > in the config,
> > but no upstream dns server is available yet.
> > 
> > The full valgrind crash log and config to reproduce the issue are below:
> > 
> > root@lappi:[dnsmasq]:# valgrind --track-origins=yes ./src/dnsmasq 
> > --conf-file=/tmp/dnsmasq.conf -k
> > ==683879== Memcheck, a memory error detector
> > ==683879== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
> > ==683879== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright 
> > info
> > ==683879== Command: ./src/dnsmasq --conf-file=/tmp/dnsmasq.conf -k
> > ==683879==
> > ==683879== Warning: invalid file descriptor 1024 in syscall close()
> > ==683879== Warning: invalid file descriptor 1025 in syscall close()
> > ==683879== Warning: invalid file descriptor 1026 in syscall close()
> > ==683879== Warning: invalid file descriptor 1027 in syscall close()
> > ==683879==    Use --log-fd=<number> to select an alternative log fd.
> > ==683879== Warning: invalid file descriptor 1028 in syscall close()
> > ==683879== Warning: invalid file descriptor 1029 in syscall close()
> > ==683879== Warning: invalid file descriptor 1030 in syscall close()
> > ==683879== Invalid read of size 4
> > ==683879==    at 0x129BED: forward_query (forward.c:353)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x4a60560 is 16 bytes before a block of size 11 alloc'd
> > ==683879==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
> > ==683879==    by 0x11AD60: safe_malloc (util.c:302)
> > ==683879==    by 0x11C3CC: opt_malloc (option.c:633)
> > ==683879==    by 0x11C3CC: opt_string_alloc (option.c:645)
> > ==683879==    by 0x11F03B: one_opt (option.c:2346)
> > ==683879==    by 0x125578: read_file (option.c:5381)
> > ==683879==    by 0x125A0B: one_file (option.c:5487)
> > ==683879==    by 0x126608: read_opts (option.c:5854)
> > ==683879==    by 0x10FA0C: main (dnsmasq.c:104)
> > ==683879==
> > ==683879== Invalid write of size 4
> > ==683879==    at 0x129BF7: forward_query (forward.c:353)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x4a60560 is 16 bytes before a block of size 11 alloc'd
> > ==683879==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
> > ==683879==    by 0x11AD60: safe_malloc (util.c:302)
> > ==683879==    by 0x11C3CC: opt_malloc (option.c:633)
> > ==683879==    by 0x11C3CC: opt_string_alloc (option.c:645)
> > ==683879==    by 0x11F03B: one_opt (option.c:2346)
> > ==683879==    by 0x125578: read_file (option.c:5381)
> > ==683879==    by 0x125A0B: one_file (option.c:5487)
> > ==683879==    by 0x126608: read_opts (option.c:5854)
> > ==683879==    by 0x10FA0C: main (dnsmasq.c:104)
> > ==683879==
> > ==683879== Invalid read of size 8
> > ==683879==    at 0x129C07: forward_query (forward.c:354)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x4a60558 is 24 bytes before a block of size 11 alloc'd
> > ==683879==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
> > ==683879==    by 0x11AD60: safe_malloc (util.c:302)
> > ==683879==    by 0x11C3CC: opt_malloc (option.c:633)
> > ==683879==    by 0x11C3CC: opt_string_alloc (option.c:645)
> > ==683879==    by 0x11F03B: one_opt (option.c:2346)
> > ==683879==    by 0x125578: read_file (option.c:5381)
> > ==683879==    by 0x125A0B: one_file (option.c:5487)
> > ==683879==    by 0x126608: read_opts (option.c:5854)
> > ==683879==    by 0x10FA0C: main (dnsmasq.c:104)
> > ==683879==
> > ==683879== Invalid write of size 4
> > ==683879==    at 0x129502: forward_query (forward.c:358)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x4a60560 is 16 bytes before a block of size 11 alloc'd
> > ==683879==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
> > ==683879==    by 0x11AD60: safe_malloc (util.c:302)
> > ==683879==    by 0x11C3CC: opt_malloc (option.c:633)
> > ==683879==    by 0x11C3CC: opt_string_alloc (option.c:645)
> > ==683879==    by 0x11F03B: one_opt (option.c:2346)
> > ==683879==    by 0x125578: read_file (option.c:5381)
> > ==683879==    by 0x125A0B: one_file (option.c:5487)
> > ==683879==    by 0x126608: read_opts (option.c:5854)
> > ==683879==    by 0x10FA0C: main (dnsmasq.c:104)
> > ==683879==
> > ==683879== Invalid write of size 8
> > ==683879==    at 0x12950C: forward_query (forward.c:357)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x4a60558 is 24 bytes before a block of size 11 alloc'd
> > ==683879==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
> > ==683879==    by 0x11AD60: safe_malloc (util.c:302)
> > ==683879==    by 0x11C3CC: opt_malloc (option.c:633)
> > ==683879==    by 0x11C3CC: opt_string_alloc (option.c:645)
> > ==683879==    by 0x11F03B: one_opt (option.c:2346)
> > ==683879==    by 0x125578: read_file (option.c:5381)
> > ==683879==    by 0x125A0B: one_file (option.c:5487)
> > ==683879==    by 0x126608: read_opts (option.c:5854)
> > ==683879==    by 0x10FA0C: main (dnsmasq.c:104)
> > ==683879==
> > ==683879== Invalid read of size 4
> > ==683879==    at 0x1289B5: allocate_rfd (forward.c:2563)
> > ==683879==    by 0x1291BE: forward_query (forward.c:498)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  Address 0x3 is not stack'd, malloc'd or (recently) free'd
> > ==683879==
> > ==683879==
> > ==683879== Process terminating with default action of signal 11 (SIGSEGV)
> > ==683879==  Access not within mapped region at address 0x3
> > ==683879==    at 0x1289B5: allocate_rfd (forward.c:2563)
> > ==683879==    by 0x1291BE: forward_query (forward.c:498)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> > ==683879==    by 0x110B38: main (dnsmasq.c:1264)
> > ==683879==  If you believe this happened as a result of a stack
> > ==683879==  overflow in your program's main thread (unlikely but
> > ==683879==  possible), you can try to increase the size of the
> > ==683879==  main thread stack using the --main-stacksize= flag.
> > ==683879==  The main thread stack size used in this run was 8388608.
> > ==683879==
> > ==683879== HEAP SUMMARY:
> > ==683879==     in use at exit: 42,261 bytes in 187 blocks
> > ==683879==   total heap usage: 243 allocs, 56 frees, 138,085 bytes allocated
> > ==683879==
> > ==683879== LEAK SUMMARY:
> > ==683879==    definitely lost: 0 bytes in 0 blocks
> > ==683879==    indirectly lost: 0 bytes in 0 blocks
> > ==683879==      possibly lost: 36 bytes in 1 blocks
> > ==683879==    still reachable: 42,225 bytes in 186 blocks
> > ==683879==         suppressed: 0 bytes in 0 blocks
> > ==683879== Rerun with --leak-check=full to see details of leaked memory
> > ==683879==
> > ==683879== For lists of detected and suppressed errors, rerun with: -s
> > ==683879== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
> > ==683879== could not unlink 
> > /tmp/vgdb-pipe-from-vgdb-to-683879-by-daniel-on-???
> > ==683879== could not unlink 
> > /tmp/vgdb-pipe-to-vgdb-from-683879-by-daniel-on-???
> > ==683879== could not unlink 
> > /tmp/vgdb-pipe-shared-mem-vgdb-683879-by-daniel-on-???
> > Segmentation fault
> > 
> > 
> > /tmp/dnsmasq.conf:
> > --
> > domain-needed
> > localise-queries
> > read-ethers
> > expand-hosts
> > bind-dynamic
> > local-service
> > edns-packet-max=1232
> > domain=lan
> > local=/lan/
> > server=/sub.domain.test/#
> > server=/domain.test/8.8.8.8
> > addn-hosts=/tmp/hosts
> > resolv-file=/tmp/resolv.conf.d/resolv.conf.auto
> > stop-dns-rebind
> > rebind-localhost-ok
> > conf-dir=/tmp/dnsmasq.d
> > bogus-priv
> > --
> > 
> > To trigger the issue, pass a simple dns request to the running dnsmasq 
> > instance.
> > I.e. with: # dig sub.domain.test @localhost
> > 
> > 
> > The first invalid memory access happens, when the 'struct server' of the 
> > matching domain is accessed here:
> > --
> > ==683879== Invalid read of size 4
> > ==683879==    at 0x129BED: forward_query (forward.c:353)
> > ==683879==    by 0x12A756: receive_query (forward.c:1869)
> > ==683879==    by 0x12ECEA: check_dns_listeners (dnsmasq.c:1843)
> >        if (!option_bool(OPT_ORDER))
> >         
> > {https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=2fc904111d9b6ec45fc1e4ec9f1f8b43c1e67b9b
> >           if (master->forwardcount++ > FORWARD_TEST ||
> >               difftime(now, master->forwardtime) > FORWARD_TIME ||
> >               master->last_server == -1)
> >             {
> >               master->forwardtime = now;
> >               master->forwardcount = 0;
> >               forward->forwardall = 1;
> >             }
> >           else
> >             start = master->last_server;
> >         }
> > --
> > 
> > The server struct has been allocated here with only 'size' bytes and not 
> > the full length of the server struct.
> > Which causes the member access beyond 'size' to read/write into unwanted 
> > memory.
> > src/domain-match.c:565
> > --
> >        if (flags & SERV_6ADDR)
> >         size = sizeof(struct serv_addr6);
> >        else if (flags & SERV_4ADDR)
> >         size = sizeof(struct serv_addr4);
> >        else
> >         size = sizeof(struct serv_local);
> > 
> >        if (!(serv = whine_malloc(size)))
> >         {
> >           free(alloc_domain);
> >           return 0;
> >         }
> > --
> > 
> 
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss@lists.thekelleys.org.uk
> https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
> 


-- 
Regards

Daniel Danzberger
embeDD GmbH, Alter Postplatz 2, CH-6370 Stans

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to