LG G4 - lgdrmserver Binder Service Multiple Race Conditions

EDB-ID:

41351

CVE:





Platform:

Android

Date:

2017-02-14


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 00000003  r1 f6b4012c  r2 00000008  r3 00000001
    r4 0000001f  r5 f6b4012c  r6 f6e40140  r7 f6b40134
    r8 f6b40000  r9 000d0027  sl 00000005  fp 00000000
    ip f700f10c  sp ffd0c2c8  lr f6b4013c  pc f6fd46c2  cpsr 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