LG G4 – lgdrmserver Binder Service Multiple Race Conditions

  • 作者: Google Security Research
    日期: 2017-02-14
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/41351/
  • Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=986
    
    The lgdrmserver binder service (/system/bin/lgdrmserver) implements a handle
    system to store pointers to objects allocated by the drm implementation 
    (/system/lib/liblgdrm.so).
    
    In several places, these handles are retrieved from a received binder Parcel, looked up in a SortedVector under a global lock, the lock is
    then released and the handle is passed to one of the DRM_xyz functions in 
    liblgdrm.so which then uses the handle without holding any locks.
    
    The attached PoC simply creates a number of process instances using the function
    DRM_ProcessInit (lgdrm binder ordinal 2), then triggers the race condition by
    trying to cause a double free on one of these instances using DRM_ProcessEnd 
    (lgdrm binder ordinal 8). The race window looks something like the following:
    
    ILGDrmService::ProcessEnd(void* handle) {
    lock(gLock); // <-- second thread takes this lock
    void* process = gProcesses.find(handle); // <-- handle is still valid
    unlock(gLock);
    
    DRM_ProcessEnd(process);
    
    lock(gLock); // <-- before first thread takes this lock
    gProcesses.remove(handle);
    unlock(gLock);
    }
    
    This will result in heap corruption during the second call to DRM_ProcessEnd 
    with the (now invalid) process object, which will eventually crash the 
    lgdrmserver process (usually during a subsequent call to malloc).
    
    Several other functions in lgdrmserver follow a similar pattern, and require 
    additional locking to be safe.
    
    The PoC has been tested on an LG G4 running build-id MRA58K
    
    Build fingerprint: 'lge/p1_global_com/p1:6.0/MRA58K/1624210305d45:user/release-keys'
    Revision: '11'
    ABI: 'arm'
    pid: 32314, tid: 32314, name: lgdrmserver>>> /system/bin/lgdrmserver <<<
    signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xf6e801d8
    r0 00000003r1 f6b4012cr2 00000008r3 00000001
    r4 0000001fr5 f6b4012cr6 f6e40140r7 f6b40134
    r8 f6b40000r9 000d0027sl 00000005fp 00000000
    ip f700f10csp ffd0c2c8lr f6b4013cpc f6fd46c2cpsr 000f0030
    
    backtrace:
    #00 pc 0004b6c2/system/lib/libc.so (arena_dalloc_bin_locked_impl.isra.27+365)
    #01 pc 0005c85f/system/lib/libc.so (je_tcache_bin_flush_small+206)
    #02 pc 00055917/system/lib/libc.so (ifree+290)
    #03 pc 000587a3/system/lib/libc.so (je_free+374)
    #04 pc 000241c9/system/lib/liblgdrm.so (DRMPart_ProcessEnd+340)
    #05 pc 00018331/system/lib/liblgdrm.so (DRM_ProcessEnd+72)
    #06 pc 000056a5/system/bin/lgdrmserver
    #07 pc 00005fbd/system/bin/lgdrmserver
    #08 pc 00019931/system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+60)
    #09 pc 0001eccb/system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+550)
    #10 pc 0001ee35/system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+64)
    #11 pc 0001ee99/system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+48)
    #12 pc 00004661/system/bin/lgdrmserver
    #13 pc 000174a9/system/lib/libc.so (__libc_init+44)
    #14 pc 00004784/system/bin/lgdrmserver
    
    
    Proof of Concept:
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41351.zip