Die Risiken beim Laden nativer Bibliotheken auf Android

1_wwcfXXOuWXtCdIso2xit1Q.png

  • 原标题: Die Gefahren des Ladens nativer Bibliotheken auf Android
  • Ursprüngliche Adresse:  medium.com/keepsafe-en…
  • Ursprünglicher Autor: Hilal Alsibai
  • Zeitpunkt der Erstveröffentlichung: 7. November 2015

Der Autor stieß letztes Jahr auf ein Problem: Nachdem das Projekt in eine apkDatei gepackt wurde, verlief die Installation normal. Nachdem das Projekt in eine Datei gepackt wurde, stürzte es nach aabdem bundleToolParsen in eine apkDatei ab, aber nach dem Hochladen der Datei wurde es geparst eine Datei und normal heruntergeladen und installiert.MMKVaabgooglePlayapk

Wenn Sie diesen Artikel lesen, können Sie verstehen, warum dieses Problem auftritt und wie Sie dieses Problem lösen können.

Übersetzung

In den Anfangsjahren 2012von KeepSafe haben wir versucht, ein Verschlüsselungsschema für unsere AndroidAnwendung zu implementieren. Durch viele Iterationen und Prototypen haben wir einen idealen Punkt gefunden, indem wir die Leistungsfähigkeit von JNI (Java Native Interface) genutzt haben. JavaWir haben uns entschieden, die Schnittstelle in die Verschlüsselungsbibliothek zu schreiben, die wir in verwenden, indem wir JNIdie Bibliothek nur für Verschlüsselungs- und Entschlüsselungszwecke aufrufen. Wir haben uns für eine sofortige Lösung mit möglichst geringen Auswirkungen auf die Benutzererfahrung entschieden. Nachdem wir mit unserer Lösung zufrieden waren, entschieden wir uns, sie in unserer Produktionsanwendung bereitzustellen. Wir haben unseren Code rigoros getestet und glaubten, dass alles glatt gehen würde, aber die Dinge endeten außerhalb unserer Kontrolle.

UnsatisfiedLinkErrorEntstehung

Als wir den Absturzbericht nach dem Start ängstlich aktualisierten, bemerkten wir einen wiederkehrenden Fehler. Der Benutzer ist darauf gestoßen UnsatisfiedLinkError, was bedeutet, dass es zwei Möglichkeiten gibt: (1) die native Bibliothek, die wir aufrufen, existiert nicht; (2) die native Methode, die wir aufrufen, existiert nicht. Da die zweite fast immer durch das Kompilieren und grundlegende Testen abgefangen wird, sind wir im Moment verwirrt darüber, dass die Installation des Benutzers nicht über APKdie native Bibliothek verfügt, die wir in .so

Hier sind einige Protokolldateien:

java.lang.UnsatisfiedLinkError: Couldn’t load stlport_shared from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.kii.safe-1.apk,libraryPath=/data/app-lib/com.kii.safe-1]: findLibrary returned null\
at java.lang.Runtime.loadLibrary(Runtime.java:365)\
at java.lang.System.loadLibrary(System.java:535)\
at com.kii.safe.Native.<clinit>(Native.java:16)\
… 63 more

Caused by: java.lang.UnsatisfiedLinkError: Library stlport_shared not found\
at java.lang.Runtime.loadLibrary(Runtime.java:461)\
at java.lang.System.loadLibrary(System.java:557)\
at com.kii.safe.Native.<clinit>(Native.java:16)\
… 5 more

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: get_lib_extents[760]: 1305 — /mnt/asec/com.kii.safe-1/lib/libstlport_shared.so is not a valid ELF object\
at java.lang.Runtime.loadLibrary(Runtime.java:434)\
at java.lang.System.loadLibrary(System.java:554)\
at com.kii.safe.Native.<clinit>(Native.java:15)

Caused by: java.lang.UnsatisfiedLinkError: Library cryptopp not found\
at java.lang.Runtime.loadLibrary(Runtime.java:461)\
at java.lang.System.loadLibrary(System.java:557)\
at com.kii.safe.Native.<clinit>(Native.java:17)
复制代码

sehr ärgerlich das

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: 1748 cannot locate ‘쯰ҷЦf1Ϙ˗˞ք᣼0Ⱉض夘Ϛ.͏闑㥁ج뭫ර⓻в^ӎ3c`+W#Ҽ?-Bַˌ֕꼠’…\
at java.lang.Runtime.loadLibrary(Runtime.java:370)\
at java.lang.System.loadLibrary(System.java:535)\
at com.kii.safe.Native.<clinit>(Native.java:17)

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1312]: 1327 cannot locate ‘Pܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭXߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭXߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#׶ʭX Ϛߐܝ#\
at java.lang.Runtime.loadLibrary(Runtime.java:434)\
at java.lang.System.loadLibrary(System.java:554)\
at com.kii.safe.Native.<clinit>(Native.java:17)
复制代码

Es gibt kein klares Muster, an dem die Bibliothek schuld ist, da anscheinend alle soBibliotheken Ausnahmen auslösen. Es Androidist nicht versionsspezifisch , es passiert nicht nur auf bestimmten Geräten. Außerdem werden in einigen Fällen einige native Bibliotheken korrekt geladen, aber nicht alle. An diesem Punkt suchen wir fieberhaft im Internet nach Antworten oder Hilfe, nur um mit leeren Händen zurückzukommen. Wir haben damit begonnen, Fixes zu veröffentlichen, hauptsächlich spekulative Fixes, zusätzliche Trace-Daten, damit wir die genaue Umgebung besser verstehen konnten, als der Absturz auftrat, und einen Code, der speziell nach nativen Bibliotheken am erwarteten Installationsort sucht.

Außerdem werden in einigen Fällen einige native Bibliotheken korrekt geladen, aber nicht alle.

Die von uns gesammelten Informationen zeigen, dass die native Bibliothek nicht existiert. Ein Systemklassen- oder Dateisystemfehler ist kein seltsamer Zufall, aber das Gerät dieses Benutzers scheint in Ordnung zu sein. Wir haben folgende Ideen:

(1) Unzureichender Platz auf der Benutzerausrüstung

Als wir über die möglichen Gründe für diese Ausnahme nachdachten, begannen wir zu denken, dass die Leute vielleicht einfach nicht den Platz hatten, um die native Bibliothek richtig zu installieren, also wurde sie nie installiert. Eine schnelle Diagnoseprüfung vor dem Versuch, die Bibliothek zu laden, hat diese Idee schnell als falsch erwiesen. Benutzer haben genügend Speicherplatz auf ihren Geräten für die Bibliothek, die wir versenden.

(2) soDie Bibliothek ist nicht im Update enthalten

造成我们问题的第二个可能原因是Google Play在向用户设备提供APK时破坏了我们的APK。在阅读了诸如此类的报告后,我们对这个想法有了一些支持,详细说明Google Play应该向所有受问题影响的应用程序开发人员发出通知,该问题导致用户在更新后无法启动他们的应用程序,因为本地库安装不正确。唯一的问题是这份报告是在8月发布的,而我们在几个月后才开始处理这个问题。我们也从未收到来自Google Play的通知,提到他们有任何错误。当然,这是很难验证的。

(3)直接与真实用户一起调试问题

由于我们无法在手头的10多种不同设备上重现该问题,因此我们决定联系遇到问题的用户。一位用户慷慨地决定帮助我们,并指出该应用程序在最新更新之前运行良好。这里的问题是,用户注意到的应用程序版本是一个包含我们的加密代码和本机库的版本,这只是为了增加我们的困惑和总体难题。我们决定直接向用户提供一个APK文件,我们在其中验证了所有本机库都存在于APK文件中。用户安装了APK,启动了应用程序,然后又直接遇到了同样的UnsatisfiedLinkError异常。这证实了不是Google Play的问题,问题在于AndroidPackageManager安装过程

找到解决方案

由于我们发现问题出在安装过程中,因此我们决定复制安装过程中提取应用程序代码中的本机库的部分。幸运的是,您可以通过以下方式轻松获取设备上应用程序APK文件的引用

Context.getApplicationInfo().sourceDir;
复制代码

Wir werden dies dann verwenden, um die native Bibliothek an einen internen Speicherort zu extrahieren. Da APKDateien nur ZIPDateien sind, schreiben Sie einfach einen ZIPExtraktionscode. Wir konnten den Code abrufen und schnell versenden, was zu einem enormen Rückgang der Anzahl der Abstürze führte! Die Gesamtzahl der jeden Tag ausgelösten UnsatisfiedLinkErrorAusnahmen in der Abbildung dargestellt:

1_QDcE8GYO_YVJrzrjBUg94A.png

Um unsere APKGröße zu reduzieren und sicherzustellen, dass unsere Anwendung auf allen möglichen Geräten ausgeführt werden kann, haben wir unsere Anwendung für x86, , undArmv7 entwickelt. ArmJede Variante enthält nur die native Bibliothek, die ihrer jeweiligen Architektur entspricht, sodass es durchaus möglich ist, dass jemand etwas installiert, das nicht für seine Gerätearchitektur entwickelt wurde APK.

Wir begannen, Installationspaketnamen bei Abstürzen zu protokollieren und stellten schnell fest, dass Benutzer Apps aus verschiedenen Quellen installierten und jede neue UnsatisfiedLinkErrorvon einer manuell installierten App stammte, die der Benutzer versehentlich für die falsche abiArchitektur seines Geräts installiert hatte. Dies ist der letzte „Fallfang“, und wir sind erleichtert, dass es eine sehr einfache Erklärung gibt.

einführenReLinker

Wir haben uns entschieden, den Extraktionscode in eine kleine Bibliothek zu packen, die jeder verwenden kann. Niemand sollte jemals den Debugging-Prozess durchlaufen, den wir durchlaufen, insbesondere wenn es sich um eine sehr grundlegende AndroidFunktion handelt, die außerhalb der AppKontrolle des Entwicklers liegt.

Die Verwendung ReLinkerist so einfach wie das Ersetzen des Standards

System.loadLibrary(“mylibrary”);
复制代码

Rückruf nutzen

ReLinker.loadLibrary(context, “mylibrary”)
复制代码

ReLinker-Quellcode

Epilog

Zum Zeitpunkt der Veröffentlichung des Fixes erreichte die Zahl der Personen, die diesen Absturz erlebten, weiterhin ca. 100,000. Wir hoffen, dass Sie ReLinkeres nützlich finden und ihm nie wieder zufällig begegnen werden UnsatisfiedLinkerError.

Supongo que te gusta

Origin juejin.im/post/7078905989591728158
Recomendado
Clasificación