Skip to content

Instantly share code, notes, and snippets.

@KreAch3R
Last active January 3, 2020 02:17
Show Gist options
  • Save KreAch3R/734b1086c928ab8ceeafaf3e4dbd8c33 to your computer and use it in GitHub Desktop.
Save KreAch3R/734b1086c928ab8ceeafaf3e4dbd8c33 to your computer and use it in GitHub Desktop.
Lenovo Tab 4 8 (tb-8504x) fix facelock crash

Lenovo Tab 4 8 - Fix facelock crash

I noticed that a Lenovo tab 4 8 (tb-8504x) on the latest stock image as of today didn't have a working face unlock ("facelock"). When it was time to add a new face, it crashed with the following log:

08-16 17:39:34.379  6600  6600 D AndroidRuntime: Shutting down VM
08-16 17:39:34.380  6600  6600 E AndroidRuntime: FATAL EXCEPTION: main
08-16 17:39:34.380  6600  6600 E AndroidRuntime: Process: com.android.facelock, PID: 6600
08-16 17:39:34.380  6600  6600 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom" referenced by "/system/lib64/libfacenet.so"...
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at java.lang.Runtime.loadLibrary0(Runtime.java:989)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at java.lang.System.loadLibrary(System.java:1530)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.google.android.libraries.vision.facenet.FaceNet.<clinit>(FaceNet.java:67)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.google.android.libraries.vision.facenet.FaceNet.createFromAssets(FaceNet.java:118)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.android.facelock.FaceLockUtil.initialize(FaceLockUtil.java:148)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.android.facelock.SetupEnrollmentScreen.onCreate(SetupEnrollmentScreen.java:517)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.Activity.performCreate(Activity.java:6720)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.ActivityThread.-wrap12(ActivityThread.java)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:102)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:154)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6119)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
08-16 17:39:34.380  6600  6600 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
08-16 17:39:34.383  1428  2305 W ActivityManager:   Force finishing activity com.android.facelock/.SetupEnrollmentScreen

The FIX

  1. Download libfacenet.so from Open-GApps [Direct link to the binary I used].

  2. Follow the instructions from here and download dywersant's magisk-remount.zip module from here.

  3. Boot into Android with a RW /system using the module. You can confirm with:

su
cd /system
touch testfile.txt

If the command succeeds, you have a writable /system.

  1. Go into the lib64 folder (/system/lib64)

  2. Make a backup of the original libfacenet.so file:

cp /system/lib64/libfacenet.so /sdcard/libfacenet.so.orig

BE CAREFUL: Don't make the backup inside the /system partition, as it can be lost after reboot!

  1. Mount the specific file as RW
    I don't know how or why, but Lenovo seems to have made every lib file a different ro mount point/partition. So:
mount -o rw,remount /system/lib64/libfacenet.so

is needed, otherwise you end up with read only file system error (even when the whole /system is RW!)

  1. Push to /sdcard and replace the file
cp /sdcard/libfacenet.so /system/lib64/libfacenet.so

Now, try to add a new face again. It should work!


Debugging

If anyone is interested to know how. You always start from the log. Let's disect this line:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom" referenced by "/system/lib64/libfacenet.so"

This tells us that the app com.android.facelock launched and called the library libfacenet.so which referenced a method/symbol/whatever named _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom but that method doesn't exist inside whatever should include it, so dlopen failed and we got ourselves the java.lang.UnsatisfiedLinkError error. Let's sum up:

  1. The app that crashes is com.android.facelock
  2. One related .so lib is libfacenet.so
  3. There is another one, unnamed, that should contain _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom but it doesn't.

Googling about _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom brings up some libprotobuf related results. This is good enough. Grepping through /system/lib64 shows up that there are two .so there:

libprotobuf-cpp-full.so
libprotobuf-cpp-lite.so

Doing the same in a working pixel image produces the same files. But obviously Facelock works on the Pixel but not on this tablet. We need a way to differentiate them (remember, pixel is on a Oreo base while this is Nougat). Reading this StackExchange post, we find out about the readelf -a -W elffile command. Give this a try and you should see that a lot comes up. Next step, grepping through this file dump.

Lenovo libprotobuf-cpp-lite.so:

$ readelf -a -W libprotobuf-cpp-lite.so | grep _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom
$

Pixel libprotobuf-cpp-lite.so:

$ readelf -a -W libprotobuf-cpp-lite.so | grep _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom
000000000004fb10  0000005700000402 R_AARCH64_JUMP_SLOT    0000000000022254 _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom + 0
    87: 0000000000022254   216 FUNC    GLOBAL DEFAULT   12 _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom

Bingo! So we confirm that the libfacenet.so is trying to call an upstream method (probably), one that isn't bundled inside the libprotobuf-cpp-lite.so of the Lenovo stock image.

So now we know, it's a problem of version incompatibility. There are two things to try:

  1. Replace libprotobuf-cpp-lite.so with a version that contains _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom
  2. Replace libfacenet.so with a version that doesn't contain _ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom

Method No. 1 didn't work, while it got rid of the java.lang.UnsatisfiedLinkError error (confirming the diagnosis), it produced more .so related crashes, so I assume there were a lot more code that was incompatible. But Method No.2 worked as a charm!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment