View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004349 | unreal | ircd | public | 2015-05-11 17:29 | 2015-05-19 02:58 |
Reporter | dg | Assigned To | tmcarthur | ||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | resolved | Resolution | open | ||
Product Version | 3.2.10.4 | ||||
Fixed in Version | 3.2.10.5 | ||||
Summary | 0004349: ircd crashes with OOB read in cidr.c | ||||
Description | When running UnrealIRCd 3.2.10.4 compiled with AddressSanitizer, the ircd crashes after linking to a server with ziplinks. AddressSanitizer is a tool to detect memory errors in C and C++ programs. I am encountering this bug every time my autoconnect fires (within seconds of ircd starting). Could this be a security issue, and if so, is it limited to servers or could a client potentially exploit it? AddressSanitizer information containing relevant lines below: ==3791==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000134cf at pc 0x55555566ec3a bp 0x7fffffffd680 sp 0x7fffffffd67 8 READ of size 1 at 0x6020000134cf thread T0 #0 0x55555566ec39 in parse_v4_netmask /home/irc/Unreal3.2.10.4/src/cidr.c:204 #1 0x55555566f25d in parse_netmask /home/irc/Unreal3.2.10.4/src/cidr.c:286 #2 0x7ffff30a3a39 in _tkl_add_line /home/irc/Unreal3.2.10.4/src/modules/m_tkl.c:1001 #3 0x7ffff30adefe in _m_tkl /home/irc/Unreal3.2.10.4/src/modules/m_tkl.c:2064 #4 0x5555555e1ced in parse /home/irc/Unreal3.2.10.4/src/parse.c:451 #5 0x5555555ddd21 in dopacket /home/irc/Unreal3.2.10.4/src/packet.c:138 #6 0x5555555a439c in read_packet /home/irc/Unreal3.2.10.4/src/s_bsd.c:1562 #7 0x5555555a7381 in read_message /home/irc/Unreal3.2.10.4/src/s_bsd.c:2152 0000008 0x5555555cc951 in main /home/irc/Unreal3.2.10.4/src/ircd.c:1867 #9 0x7ffff6107b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44) #10 0x555555597b19 (/home/irc/Unreal3.2.10.4/src/ircd+0x43b19) 0x6020000134cf is located 1 bytes to the left of 2-byte region [0x6020000134d0,0x6020000134d2) allocated by thread T0 here: #0 0x7ffff6f378a7 in __interceptor_strdup (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x328a7) #1 0x7ffff30a348c in _tkl_add_line /home/irc/Unreal3.2.10.4/src/modules/m_tkl.c:974 #2 0x7ffff30adefe in _m_tkl /home/irc/Unreal3.2.10.4/src/modules/m_tkl.c:2064 #3 0x5555555e1ced in parse /home/irc/Unreal3.2.10.4/src/parse.c:451 #4 0x5555555ddd21 in dopacket /home/irc/Unreal3.2.10.4/src/packet.c:138 #5 0x5555555a439c in read_packet /home/irc/Unreal3.2.10.4/src/s_bsd.c:1562 #6 0x5555555a7381 in read_message /home/irc/Unreal3.2.10.4/src/s_bsd.c:2152 #7 0x5555555cc951 in main /home/irc/Unreal3.2.10.4/src/ircd.c:1867 0000008 0x7ffff6107b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44) SUMMARY: AddressSanitizer: heap-buffer-overflow /home/irc/Unreal3.2.10.4/src/cidr.c:204 parse_v4_netmask Shadow bytes around the buggy address: 0x0c047fffa640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffa650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffa660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffa670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fffa680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c047fffa690: fa fa fa fa fa fa 00 02 fa[fa]02 fa fa fa 00 fa 0x0c047fffa6a0: fa fa 00 fa fa fa 00 00 fa fa 00 04 fa fa 00 00 0x0c047fffa6b0: fa fa 00 03 fa fa 00 00 fa fa 00 03 fa fa 00 00 0x0c047fffa6c0: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 07 0x0c047fffa6d0: fa fa 00 00 fa fa 00 05 fa fa 00 00 fa fa 03 fa 0x0c047fffa6e0: fa fa 00 00 fa fa 00 00 fa fa 00 fa fa fa 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Contiguous container OOB:fc ASan internal: fe ==3791==ABORTING | ||||
Steps To Reproduce | export ASAN_OPTIONS="abort_on_error=1" export CFLAGS="-fsanitize=address -ggdb" export CXXFLAGS="-fsanitize=address -ggdb" ./Config make src/ircd -t | ||||
Tags | No tags attached. | ||||
3rd party modules | |||||
|
You may wish to add "-fno-omit-frame-pointer" to CFLAGS for a better output. |
|
Having a look now - thanks! |
|
Just glancing at the source just now. Error is at: if (*(p + 1) || n == 0 || *(p - 1) != '.') /* Error: * is not at the end * or not its own section */ and the description is: 0x6020000134cf is located 1 bytes to the left of 2-byte region [0x6020000134d0,0x6020000134d2) Possibly the *(p - 1) is the problem, it's reading 1 byte before 'p' so if 'p' points to the very 1st byte then it's reading the byte BEFORE the actual string. It had a 'n == 0' check, probably to prevent this, but a number of lines up it does 'digits[n++] = text;' so n would be 1 and not 0 at the start of the string. Perhaps change: if (*(p + 1) || n == 0 || *(p - 1) != '.') /* Error: * is not at the end * or not its own section */ To: if (*(p + 1) || n == 1 || *(p - 1) != '.') /* Error: * is not at the end * or not its own section */ Well.. probably should take a bit more in-depth look :D I would theorise that a string to trigger this would be just "*" (EDIT: removed statement regarding "not a netmask") |
|
Do you want me to try changing n == 0 to n == 1 and see if it fixes it? It's possible some more errors might come up in separate places. ASAN holds no prisoners and dies when it finds the first error, so there may more laying dormant to fix after this one is resolved. I'm happy to change, report back, and so on. Thanks for your speedy replies, guys! Let me know if I can be of any more assistance. |
|
Fixed in 5d42ac844fe79dcad001972a6f34014955775332 - just verifying security impact, but it doesn't look like a big problem. |
|
Moving to has patch until security verification finished |
|
Confirmed that 5d42ac844fe79dcad001972a6f34014955775332 fixes the crash. Let us know if it is a security concern. I'll continue to test Unreal against various tools and keep you guys abreast of any reports. I may at some point try the alpha, but I currently run stable on my network. Thanks again for being so friendly and quick to fix. |
|
After having a chance to read the function a bit more I decided to change the fix a bit, see https://github.com/unrealircd/unrealircd/commit/af0e823116fbaa5b9d58826027bcf33cf597dbdd I basically made an explicit (p == text) check rather than using 'n'. And note that I did the same fix in the parse...v6 function as well. This fixes the OOB read (what this issue is all about) but to be honest I'm not entirely sure if it fixed the entire function to do what the comments in the function actually said. In any case, I don't think I broke it more and it seems to have worked for so many years so it's probably OK :D. It mostly falls through to NM_HOST anyway. Just be sure to make it a QA item for (whatever) next release. Travis: you may want to port it to 3.4.x also. As for the security impact: it's an out of bounds read of 1 byte before the actual string. It is unlikely that it would ever try to access invalid memory regions (and crash) as if it's on the stack.. all is okay.. if it's on the heap then even if it's at the very beginning of a malloc()'d region then you still have some malloc internals before that (probably at least 8 bytes). It's also just a 1 byte read, so no write or anything that can be used to gain privileges. Thanks for the report dg! Bugs like this should always be fixed anyway. |
|
I'm marking this bug as resolved and changing view status from private to public now that there's no risk. (and it's called from config- and *LINE routines anyway) Oh and I did re-indent the function a bit in 3.2.x as it was damn confusing.. a whole block of code was indented the same as the for () statement itself even though it belonged WITHIN that statement. Both with tab size 4 and tab 8. That's just confusing :D Travis: well, see previous comment ;) |
|
Thanks! Will have a look. |
Date Modified | Username | Field | Change |
---|---|---|---|
2015-05-11 17:29 | dg | New Issue | |
2015-05-11 17:32 | dg | Note Added: 0018294 | |
2015-05-14 07:03 | tmcarthur | Assigned To | => tmcarthur |
2015-05-14 07:03 | tmcarthur | Status | new => assigned |
2015-05-14 07:04 | tmcarthur | Note Added: 0018297 | |
2015-05-16 15:23 | syzop | Note Added: 0018299 | |
2015-05-16 15:54 | syzop | Note Edited: 0018299 | |
2015-05-16 15:55 | syzop | Summary | ircd crashes with a heap-buffer-overflow in cidr.c => ircd crashes with OOB read in cidr.c |
2015-05-17 15:34 | dg | Note Added: 0018300 | |
2015-05-17 18:24 | tmcarthur | Note Added: 0018301 | |
2015-05-17 18:26 | tmcarthur | Note Added: 0018302 | |
2015-05-17 18:26 | tmcarthur | Status | assigned => has patch |
2015-05-17 23:27 | dg | Note Added: 0018303 | |
2015-05-18 11:52 | syzop | Note Added: 0018304 | |
2015-05-18 11:54 | syzop | Note Added: 0018305 | |
2015-05-18 11:54 | syzop | Status | has patch => resolved |
2015-05-18 11:54 | syzop | Fixed in Version | => 3.2.10.5 |
2015-05-18 11:54 | syzop | View Status | private => public |
2015-05-19 02:58 | tmcarthur | Note Added: 0018318 |