[Dnsmasq-discuss] crash on double free

Simon Kelley simon at thekelleys.org.uk
Sun Sep 19 21:25:36 BST 2010


On 15/09/10 12:07, Ferenc Wagner wrote:
> Simon Kelley<simon at thekelleys.org.uk>  writes:
>
>> Ferenc Wagner wrote:
>>
>>> ElectricFence Aborting: free(b7215f8c): address not from malloc().
>>> Illegal instruction (core dumped)
>>>
>>> and the backtrace is:
>>>
>>> #0  0xb7782416 in __kernel_vsyscall ()
>>> #1  0xb75dc956 in kill () from /lib/i686/cmov/libc.so.6
>>> #2  0xb770edd5 in EF_Abort () from /usr/lib/libefence.so.0
>>> #3  0xb770e159 in free () from /usr/lib/libefence.so.0
>>> #4  0x080623aa in add_extradata_data (lease=0xb71c7fac,
>>>      data=0xb720fb68 "Linux ipconfigÿ\001þ\006\004\nú\001þ\017\talma.grid\f\02152-54-00-12-34-56\021\020/var/lib/nfsrootÿ", len=14, delim=0) at rfc2131.c:1525
>>> #5  0x0806242c in add_extradata_opt (lease=0xb71c7fac, opt=<value optimized out>) at rfc2131.c:1555
>>> #6  0x08067040 in dhcp_reply (context=0xb7549fc4, iface_name=0xbfdb6854 "br-alma-g", int_index=10,
>>>      sz=283, now=1284475079, unicast_dest=0, is_inform=0xbfdb68d4, pxe=0) at rfc2131.c:1240
>>> #7  0x0805fb3e in dhcp_packet (now=1284475079, pxe_fd=0) at dhcp.c:301
>>> #8  0x0805d7de in main (argc=Cannot access memory at address 0x4
>>> ) at dnsmasq.c:688
>>>
>>> which points at
>>>
>>> static void add_extradata_data(struct dhcp_lease *lease, unsigned char *data, size_t len, int delim)
>>> {
>>>    if ((lease->extradata_size - lease->extradata_len)<  (len + 1))
>>>      {
>>>        size_t newsz = lease->extradata_len + len + 100;
>>>        unsigned char *new = whine_malloc(newsz);
>>>
>>>        if (!new)
>>>          return;
>>>
>>>        if (lease->extradata)
>>>          {
>>>            memcpy(new, lease->extradata, lease->extradata_len);
>>> HERE ==>   free(lease->extradata);
>>>          }
>>>
>>>        lease->extradata = new;
>>>        lease->extradata_size = newsz;
>>>      }
>>>
>>>    if (len != 0)
>>>      memcpy(lease->extradata + lease->extradata_len, data, len);
>>>    lease->extradata[lease->extradata_len + len] = delim;
>>>    lease->extradata_len += len + 1;
>>> }
>>>
>>> So I seems lease->extradata isn't a pointer returned by malloc(), thus
>>> you should try to free it.  I've got to leave now, hope it gives you
>>> enough info to actually pinpoint the problem.  I'm keeping the core
>>> files for further investigation (and also send them if needed).
>>
>> Many thanks for taking the time to get this, I think I see the problem.
>> Could you try the following?
>>
>> at src/rfc2131.c line 1237 which is
>>
>> free(lease->extradata);
>>
>> add an extra line
>>
>> lease->extradata = NULL;
>>
>> and see if that fixes the crashes.
>
> Looks like that's a good move, I haven't got a crash since inserting
> that extra line!
>
> However, I also got a different crash with the original binary.  I hope
> it's a different realisation of the same problem, can you confirm?
>
> (gdb) bt
> #0  0xb7599d5a in memcpy () from /lib/i686/cmov/libc.so.6
> #1  0x080623d0 in add_extradata_data (lease=0xb74f6fac,
>      data=0xb7182b68 "Linux ipconfigÿ\001þ\006\004\nú\001þ\017\talma.grid\f\02152-54-00-12-34-56\021\020/var/lib/nfsrootÿ", len=3071814504, delim=0) at rfc2131.c:1533
> #2  0x0806242c in add_extradata_opt (lease=0xb74f6fac, opt=<value optimized out>) at rfc2131.c:1555
> #3  0x08067040 in dhcp_reply (context=0xb74bafc4, iface_name=0xbfda1124 "br-alma-g", int_index=10,
>      sz=283, now=1284499746, unicast_dest=0, is_inform=0xbfda11a4, pxe=0) at rfc2131.c:1240
> #4  0x0805fb3e in dhcp_packet (now=1284499746, pxe_fd=0) at dhcp.c:301
> #5  0x0805d7de in main (argc=Cannot access memory at address 0x3
> ) at dnsmasq.c:688
> (gdb) up
> #1  0x080623d0 in add_extradata_data (lease=0xb74f6fac,
>      data=0xb7182b68 "Linux ipconfigÿ\001þ\006\004\nú\001þ\017\talma.grid\f\02152-54-00-12-34-56\021\020/var/lib/nfsrootÿ", len=3071814504, delim=0) at rfc2131.c:1533
> 1533	    memcpy(lease->extradata + lease->extradata_len, data, len);
>
> The passed-in value of "len" is obviously bogus here.
>
> (gdb) p lease->extradata
> $1 = (unsigned char *) 0xb7184f8c "Linux ipconfig"
> (gdb) p lease->extradata_len
> $2 = 0
> (gdb) p data
> $3 = (
>      unsigned char *) 0xb7182b68 "Linux ipconfigÿ\001þ\006\004\nú\001þ\017\talma.grid\f\02152-54-00-12-34-56\021\020/var/lib/nfsrootÿ"

I can't see any other reason for this problem, I'm pretty sure it's down 
to heap corruption from an earlier double-free.
>
> I'm continuing testing the fix.  It usually took me tens of minutes to
> reproduce the crash, but with the change it already survived more than
> an hour.  Unfortunately, it isn't fully automatic (because of other bugs
> in other software).

To trigger this bug, there needs to be a dhcp-script, obviously. But 
also the rate of DHCP transactions needs to be fast enough and/or the 
script needs to be slow enough so that a second DHCP transaction happens 
on a lease before the first one has been sent to the DHCP-script. This 
is pretty rare, hence no-one has seen this bug, as far as I know, even 
though it has been lurking for some time (years).

Cheers,

Simon.





More information about the Dnsmasq-discuss mailing list