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
-
Download
libfacenet.so
from Open-GApps [Direct link to the binary I used]. -
Follow the instructions from here and download dywersant's
magisk-remount.zip
module from here. -
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
.
-
Go into the
lib64
folder (/system/lib64
) -
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!
- Mount the specific file as
RW
I don't know how or why, but Lenovo seems to have made every lib file a differentro
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!)
- 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!
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:
- The app that crashes is
com.android.facelock
- One related
.so
lib islibfacenet.so
- 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:
- Replace
libprotobuf-cpp-lite.so
with a version that contains_ZN6google8protobuf5Arena15AllocateAlignedEPKSt9type_infom
- 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!