ramosian-glider / sanitizer-issues

test
0 stars 0 forks source link

CFRelease(kCFAllocatorSystemDefault) fails within __asan_init() #87

Closed ramosian-glider closed 9 years ago

ramosian-glider commented 9 years ago

Originally reported on Google Code with ID 87

To reproduce, build Chromium base_unittests with the current ASan on OS X 10.6

$ gdb out/Release/base_unittests
(gdb) r

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000010
0x91dfa9f9 in objc_selopt::objc_selopt_t::get ()
(gdb) bt
#0  0x91dfa9f9 in objc_selopt::objc_selopt_t::get ()
#1  0x91de73ef in _objc_search_builtins ()
#2  0x91de71ee in __sel_registerName ()
#3  0x95f3df0c in CFRelease ()
#4  0x96013a10 in CFAllocatorSetDefault ()
#5  0x01704b61 in __asan_unregister_globals ()
#6  0x8fe0ed69 in __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE
()
#7  0x8fe0d31a in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
()
#8  0x8fe0d2be in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
()
#9  0x8fe0d3cd in __dyld__ZN11ImageLoader15runInitializersERKNS_11LinkContextE ()
#10 0x8fe024a9 in __dyld__ZN4dyld24initializeMainExecutableEv ()
#11 0x8fe0794e in __dyld__ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ ()
#12 0x8fe018b1 in __dyld__ZN13dyldbootstrap5startEPK12macho_headeriPPKcl ()
#13 0x8fe01057 in __dyld__dyld_start ()

(gdb) br _objc_search_builtins
Breakpoint 2 at 0x91de72dc
(gdb) r

Breakpoint 2, 0x91de72dc in _objc_search_builtins ()
(gdb) i r
eax            0x960716b8   -1777920328
ecx            0x1  1
edx            0x1  1
ebx            0x91de72db   -1847692581
esp            0xbfffd350   0xbfffd350
ebp            0xbfffd388   0xbfffd388
esi            0x0  0
edi            0x960716b8   -1777920328
eip            0x91de72dc   0x91de72dc <_objc_search_builtins+15>
eflags         0x286    646
cs             0x1b 27
ss             0x23 35
ds             0x23 35
es             0x23 35
fs             0x0  0
gs             0xf  15

(gdb) x/s $eax
0x960716b8 <__PRETTY_FUNCTION__.28290+422>:  "release"

Reported by ramosian.glider on 2012-07-04 17:05:56

ramosian-glider commented 9 years ago
The problem is reproducible only when Chromium Framework is build with component=shared_library
(opposed to component=static_library)

Looks like in this case __CFAllocatorInitialize isn't called before __asan_init(),
and __kCFAllocatorSystemDefault._context.info isn't initialized, which leads to a NULL
deref.
Because it's hard to call __CFAllocatorInitialize directly, the fix should probably
just initialize __kCFAllocatorSystemDefault._context.info with the return value malloc_zone_default()
before it has been replaced by ASan.

Reported by ramosian.glider on 2012-07-05 10:16:19

ramosian-glider commented 9 years ago
Looks like it's insufficient to re-implement parts of __CFAllocatorInitialize in the
runtime, so I've ended up trying to call some existing initialization routine.

__CFAllocatorInitialize can't be called solely: it's a private symbol, moreover, CF
relies on the fact it's called after
         __kCFNotATypeTypeID = _CFRuntimeRegisterClass(&__CFNotATypeClass);
        __kCFTypeTypeID = _CFRuntimeRegisterClass(&__CFTypeClass);
, which also initialize private symbols (see http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c)
Thus, one needs to call at least __CFInitialize in order to initialize properly.

Doing so has caused many assertions to fire (__CFInitialize() uses calloc(), malloc(),
strdup(), strchr() etc.) and finally caused error reports about unallocated memory
being passed to free().

My current idea is to intercept __CFInitialize and replace the default CFAllocator
right after the exit from it: until then neither of the CFAllocators can be used reliably,
so this should be safe.

Reported by ramosian.glider on 2012-07-05 13:40:33

ramosian-glider commented 9 years ago
r159749 should fix the issue.

Reported by ramosian.glider on 2012-07-05 14:47:26

ramosian-glider commented 9 years ago
Because __CFRuntimeClassTableSize is unavailable on 10.7, I've landed r159819, which
unconditionally calls CFAllocatorSetDefault() from __asan_init() on Lion.

This means the described bug may (possibly) re-appear on Lion, and in order to prevent
this we'll need to check some bits in __kCFAllocatorSystemDefault.
However I couldn't reproduce the problem with Chromium tests in both component=shared_library
and component=static_library, so this is a minor problem now.

Reported by ramosian.glider on 2012-07-06 12:17:37

ramosian-glider commented 9 years ago
I've got rid of the __CFRuntimeClassTableSize (checking for kCFAllocatorSystemDefault._base._cfisa
instead), but it turns out that CFAllocatorCreate() depends on __CFInitialize() on
Lion, so it should be moved to the __CFInitialize() wrapper as well.

Reported by ramosian.glider on 2012-07-06 13:08:26

ramosian-glider commented 9 years ago
Ok, now CFAllocatorReplace() is called from __asan_init() or CFInitialize() depending
on which is called later. I've checked that ASan tests pass and Chromium base_unittests
run when built in both modes on both Lion and Snow Leopard.

Reported by ramosian.glider on 2012-07-06 14:14:58

ramosian-glider commented 9 years ago
Adding Project:AddressSanitizer as part of GitHub migration.

Reported by ramosian.glider on 2015-07-30 09:12:59