View Issue Details

IDProjectCategoryView StatusLast Update
0001976unrealircdpublic2004-07-24 14:43
Reportersh0 Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
Status closedResolutionopen 
Product Version3.2.1 
Summary0001976: Rehashes may cause crashes if there are outstanding dns lookups
DescriptionOutstanding asynchronous DNS lookups when a rehash is executed are likely to lead to problems; this may ultimately lead to ircd crashes. The typical less extreme reactions by the ircd usually look somewhat like this:

[22:31:33] *** Resolving hostname 'HOSTNAME1'...
[22:31:34] *** Notice -- $OPER is rehashing server config file
[22:31:34] *** Notice -- Loading IRCd configuration ..
[22:31:34] *** Notice -- oldcloak: WARNING: The 'oldcloak' module should *ONLY* be used temporarily for upgrading purposes since it is considered INSECURE, upgrade to 'cloak' AS SOON AS YOU CAN.
[22:31:34] *** Notice -- Configuration loaded without any problems ..
[22:31:35] *** Notice -- Hostname $HOSTNAME2 is unknown for server $SERVER2 (!?).
[22:31:35] *** Notice -- Connecting to $SERVER2[$HOSTNAME2].
[22:31:36] *** LocOps -- ERROR :from $SERVER2 -- Server $SERVER0 already exists from $SERVER0
[22:31:36] *** LocOps -- ERROR :from $SERVER2 -- Closing Link: [$IP0] (Server Exists)
[22:31:36] *** LocOps -- Server $SERVER2 closed the connection

$SERVER0 is the server this happens on, $HOSTNAME0 its host, $IP0 its ip.
$*1 refer to the server we are connecting to (and which has a host that has to be looked up before this can happen!)
$*2 refer to an unrelated server that also has a linkblock on the server we are on, and is already linked.
I.e. we trigger a connection, causing a DNS lookup (which has been artifically delayed), and then rehash the server before the lookup has been completed.
When it is completed, the server attempts to connect to a completely unrelated third server - or coredumps instantly.
Following an earlier suggestion by syzop, I've compiled the ircd with mpatrol and reproduced the bug to give you some more infos. mpatrol.log follows:
"""
@(#) mpatrol 1.4.8 (02/01/08)
Copyright (C) 1997-2002 Graeme S. Roy

This is free software, and you are welcome to redistribute it under certain
conditions; see the GNU Library General Public License for details.

For the latest mpatrol release and documentation,
visit http://www.cbmamiga.demon.co.uk/mpatrol.

operating system: UNIX
system variant: Linux
processor architecture: Intel 80x86
processor word size: 32-bit
object file format: ELF32
dynamic linker type: SVR4

Log file generated on Sun Jul 18 01:31:52 2004

read 321 symbols from /usr/lib/i686/cmov/libssl.so.0.9.7
read 2444 symbols from /usr/lib/i686/cmov/libcrypto.so.0.9.7
read 7 symbols from /lib/libcrypt.so.1
read 121 symbols from /lib/libnsl.so.1
read 62 symbols from /usr/lib/libz.so.1
read 9 symbols from /lib/libdl.so.2
read 303 symbols from /usr/lib/libmpatrol.so
read 113 symbols from /usr/lib/libelf.so.0
read 577 symbols from /usr/lib/libbfd-2.14.90.0.7.so
read 2013 symbols from /lib/libc.so.6
read 33 symbols from /lib/ld-linux.so.2
read 1122 symbols from /usr/lib/libstdc++-libc6.2-2.so.3
read 321 symbols from /lib/libm.so.6
read 850 symbols from ./ircd

system page size: 4096 bytes
default alignment: 4 bytes
overflow size: 0 bytes
overflow byte: 0xAA
allocation byte: 0xFF
free byte: 0x55
allocation stop: 0
reallocation stop: 0
free stop: 0
unfreed abort: 0
small boundary: 32 bytes
medium boundary: 256 bytes
large boundary: 2048 bytes
lower check range: 0
upper check range: 0
check frequency: 1
failure frequency: 0
failure seed: 1090107112
prologue function: <unset>
epilogue function: <unset>
handler function: <unset>
log file: mpatrol.log
profiling file: mpatrol.out
tracing file: mpatrol.trace
program filename: ./ircd
symbols read: 8296
autosave count: 0
freed queue size: 0
allocation count: 9330
allocation peak: 6347 (183449 bytes)
allocation limit: 0 bytes
allocated blocks: 5353 (122824 bytes)
marked blocks: 0 (0 bytes)
freed blocks: 0 (0 bytes)
free blocks: 1187 (69688 bytes)
internal blocks: 136 (2228224 bytes)
total heap usage: 2420736 bytes
total compared: 0 bytes
total located: 78 bytes
total copied: 17409 bytes
total set: 695571 bytes
total warnings: 0
total errors: 0
system page size: 4096 bytes
default alignment: 4 bytes
overflow size: 0 bytes
overflow byte: 0xAA
allocation byte: 0xFF
free byte: 0x55
allocation stop: 0
reallocation stop: 0
free stop: 0
unfreed abort: 0
small boundary: 32 bytes
medium boundary: 256 bytes
large boundary: 2048 bytes
lower check range: 0
upper check range: 0
check frequency: 1
failure frequency: 0
failure seed: 1090107112
prologue function: <unset>
epilogue function: <unset>
handler function: <unset>
log file: mpatrol.log
profiling file: mpatrol.out
tracing file: mpatrol.trace
program filename: ./ircd
symbols read: 8296
autosave count: 0
freed queue size: 0
allocation count: 24064
allocation peak: 9781 (299120 bytes)
allocation limit: 0 bytes
allocated blocks: 6476 (170025 bytes)
marked blocks: 0 (0 bytes)
freed blocks: 0 (0 bytes)
free blocks: 1331 (137175 bytes)
internal blocks: 201 (3293184 bytes)
total heap usage: 3600384 bytes
total compared: 16 bytes
total located: 78 bytes
total copied: 37020 bytes
total set: 936020 bytes
total warnings: 0
total errors: 0

ERROR: [ILLMEM]: illegal memory access at address 0x00000000
    0x00000000 not in heap

    call stack
        0x08072331 connect_server+129
        0x08072B65 do_dns_async+357
        0x080720FA read_message+2282
        0x080652BE main+2894
        0x40295DC6 __libc_start_main+198
        0x08053D21 _start+33
"""

And for good measure, here is the output of gdb:

"""
ircd@support-unit-001:~/Unreal3.2_dev$ gdb bin/ircd core
GNU gdb 6.1-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-linux"...Using host libthread_db library "/lib/libthread_db.so.1".

Core was generated by `./ircd'.
Program terminated with signal 6, Aborted.
Reading symbols from /usr/lib/i686/cmov/libssl.so.0.9.7...done.
Loaded symbols for /usr/lib/i686/cmov/libssl.so.0.9.7
Reading symbols from /usr/lib/i686/cmov/libcrypto.so.0.9.7...done.
Loaded symbols for /usr/lib/i686/cmov/libcrypto.so.0.9.7
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/libnsl.so.1...done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /usr/lib/libz.so.1...done.
Loaded symbols for /usr/lib/libz.so.1
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /usr/lib/libmpatrol.so...done.
Loaded symbols for /usr/lib/libmpatrol.so
Reading symbols from /usr/lib/libelf.so.0...done.
Loaded symbols for /usr/lib/libelf.so.0
Reading symbols from /usr/lib/libbfd-2.14.90.0.7.so...done.
Loaded symbols for /usr/lib/libbfd-2.14.90.0.7.so
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /usr/lib/libstdc++-libc6.2-2.so.3...done.
Loaded symbols for /usr/lib/libstdc++-libc6.2-2.so.3
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from tmp/9D5CC727.commands.so...done.
Loaded symbols for tmp/9D5CC727.commands.so
Reading symbols from tmp/E7D9308D.cloak.so...done.
Loaded symbols for tmp/E7D9308D.cloak.so
#0 0x402a9721 in kill () from /lib/libc.so.6
(gdb)
(gdb) bt
#0 0x402a9721 in kill () from /lib/libc.so.6
#1 0x402a94c5 in raise () from /lib/libc.so.6
#2 0x402aa9e8 in abort () from /lib/libc.so.6
#3 0x401b0022 in __mp_abort () from /usr/lib/libmpatrol.so
#4 0x401aff24 in __mp_findsource () from /usr/lib/libmpatrol.so
#5 <signal handler called>
#6 0x402f5e60 in strncpy () from /lib/libc.so.6
#7 0x08072331 in connect_server (aconf=0x819311c, by=0x0, hp=0x81a5940) at s_bsd.c:2400
0000008 0x08072b65 in do_dns_async () at s_bsd.c:2617
#9 0x080720fa in read_message (delay=2, listp=0x8161340) at s_bsd.c:1757
#10 0x080652be in main (argc=0, argv=0x0) at ircd.c:1548
"""
Steps To ReproduceBasically three steps:
1.Create a linkblock for an unlinked server, and specify the hostname as hostname, not as ip.
2.Make sure that the hostname resolving will be delayed sufficiently for you to get a rehash in before it is completely, but not more than about 2-3 seconds (otherwise, unrealircd will abort the resolve attempt).
3.Connect the server, and immediatley afterwards, before the hostname has been resolved, rehash it.
If you are an oper, the following commandsequence will do it:
"
DNS c
REHASH
CONNECT $SERVER1
REHASH
"
This should trigger the bug. If there are several linkblocks, and the unrealircd binary is not linked to mpatrol, this might cause the ircd to attempt to connect to an already linked server; if you do it sufficiently often, it ultimately will crash.
If the unrealircd binary is linked to mpatrol, it will (apparently) always crash instantly.

As a matter of fact, for unrealircd binaries linked to mpatrol you may not have to artifically delay the replies to dns lookups if you send the whole command-sequence at once (e.g. by pasting it into a netcat instance); it was possible to reproduce it here without delaying the dns requests made by those binaries.
Additional InformationThe way to reproduce this bug was discovered after another netadmin looked over the unrealircd 3.2 code and wondered what would happen in this situation. His description of the problem and suggestions to fix it follow:
If unreal needs to asynchronously resolve a servername when connecting to another server, it saves a pointer to the corresponding link block along with the request.
On rehash, this link block is deleted.
If and when a reply to the dns request arrives (before the timeout), the pointer to the deleted link block will then cause an access to an invalid memory address, leading to undefined behaviour (usually connection attempts to an arbitrary server, or crashes).
Suggestions for approaches to fix it:
1.Delete all ASYNC_CONNECT requests on rehash.
2.Use the reference counter.
3rd party modules

Activities

syzop

2004-07-18 18:58

administrator   ~0007148

Thank you. I'll certainly take a look at this when I got some time (about a few days) :).

aquanight

2004-07-18 19:04

reporter   ~0007149

Last edited: 2004-07-18 19:05

I'd have to go for #1 (cancel+restart all pending DNS requests on rehash) because there are other reasons a rehash might have occured:
/etc/resolv.conf was changed (though IIRC this needs a restart)
link::hostname was changed (but the linkblock wasn't deleted), thus Unreal will still try to connect to the old host, which may have gone down (permanently?) or be a whole different machine (and what if this machine ran a different IRCd? Especially one that has a wierd protocol - could cause Unreal to crash since server-server stuff doesn't have a lot of checks on it (IIRC)! Uh oh...)!

Pending /connect or link::options::autoconnect attempts waiting for a DNS reply may need to be canceled and restarted as well...

I would probably say that even pending DNS requests for incoming connections need to be cancelled and restarted as well, though I can't see any major reason this would be necessary.

*edit* Syzop beat me :/ */edit

edited on: 2004-07-18 19:05

syzop

2004-07-22 18:19

administrator   ~0007224

Should be fixed in CVS [.112] (using tactic 1).
Can you confirm that it no longer crashes?

sh0

2004-07-24 12:55

reporter   ~0007244

Ack, afaict it has been fixed. Good work on that.

syzop

2004-07-24 14:43

administrator   ~0007245

Good.

Issue History

Date Modified Username Field Change
2004-07-17 19:59 sh0 New Issue
2004-07-18 18:58 syzop Note Added: 0007148
2004-07-18 19:04 aquanight Note Added: 0007149
2004-07-18 19:05 aquanight Note Edited: 0007149
2004-07-22 18:19 syzop Note Added: 0007224
2004-07-22 18:20 syzop Status new => confirmed
2004-07-24 12:55 sh0 Note Added: 0007244
2004-07-24 14:43 syzop Status confirmed => closed
2004-07-24 14:43 syzop Note Added: 0007245