Androidにネイティブsoライブラリをロードするリスク

1_wwcfXXOuWXtCdIso2xit1Q.png

  • 原✓题:Androidにネイティブライブラリをロードすることの危険性
  • 元のアドレス:  medium.com/keepsafe-en…
  • 原作者:Hilal Alsibai
  • 初版発行時間:2015年11月7日

作者は昨年問題に遭遇しました:プロジェクトがapkファイルにパッケージ化された後、インストールは正常でした。プロジェクトがファイルにパッケージ化された後、ファイルaabbundleTool解析された後にクラッシュしましたが、ファイルをアップロードした後ファイルをダウンロードし、通常どおりにインストールしますapkMMKVaabgooglePlayapk

この記事を読むことで、この問題が発生する理由とこの問題を解決する方法を理解できます。

翻訳

KeepSafeの初期2012Android、私たちはアプリケーションに暗号化スキームを実装しようとしました。多くの反復とプロトタイプを通じて、 JNI(Java Native Interface)のパワーを活用することでスイートスポットを見つけました。暗号化と復号化の目的でのみライブラリを呼び出すことJavaにより、で使用する暗号化ライブラリにインターフェイスを書き込むことにしました。JNIユーザーエクスペリエンスへの影響を最小限に抑えた即時ソリューションを選択しました。ソリューションに満足したら、それを本番アプリケーションにデプロイすることにしました。私たちはコードを厳密にテストし、すべてがスムーズに進むと信じていましたが、結局は制御できなくなりました。

UnsatisfiedLinkError創発

起動後にクラッシュレポートを心配そうに更新していたので、繰り返し発生するバグに気づき始めました。ユーザーがこれに遭遇しましたUnsatisfiedLinkError。これは、2つの可能性があることを意味します。(1)呼び出しているネイティブライブラリが存在しない、(2)呼び出しているネイティブメソッドが存在しない。2つ目は、ほとんどの場合、コンパイルと基本的なテストによって検出されるため、現時点では、ユーザーのインストールAPKに、で提供するネイティブライブラリがないsoという事実に混乱しています。

ここにいくつかのログファイルがあります:

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)
复制代码

非常に腹立たしい

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)
复制代码

soすべてのライブラリが例外をスローしているように見えるため、ライブラリに障害がある明確なパターンはありません。これAndroidはバージョン固有ではなく、特定のデバイスで発生するだけではありません。また、場合によっては、一部のネイティブライブラリが正しくロードされますが、すべてではありません。この時点で、私たちは必死にインターネットで答えや助けを探しますが、手ぶらで戻ってきます。修正、主に投機的な修正、クラッシュが発生したときの正確な環境をよりよく理解できるようにする追加のトレースデータ、および予想されるインストール場所にあるネイティブライブラリを具体的にチェックするコードのリリースを開始しました。

また、場合によっては、一部のネイティブライブラリが正しくロードされますが、すべてではありません。

収集した情報は、ネイティブライブラリが存在しないことを示しています。システムクラスまたはファイルシステムエラーは奇妙なまぐれではありませんが、このユーザーのデバイスは問題ないようです。私たちは次のアイデアを持っています:

(1)ユーザー機器のスペースが不足している

この例外の考えられる理由を考えたとき、おそらく人々はネイティブライブラリを適切にインストールするスペースがなかったので、インストールされなかったのではないかと考え始めました。ライブラリをロードする前の簡単な診断チェックにより、このアイデアが間違っていることがすぐにわかりました。ユーザーは、出荷するライブラリ用にデバイスに十分なスペースがあります。

(2)soライブラリはアップデートに含まれていません

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

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

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

找到解决方案

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

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

次に、これを使用してネイティブライブラリを内部ストレージの場所に抽出します。APKファイルは単なるファイルなので、抽出コードZIPを書くだけです。ZIPコードをプルして迅速に出荷することができたため、クラッシュの数が大幅に減少しました。毎日スローされるUnsatisfiedLinkError例外に示します。

1_QDcE8GYO_YVJrzrjBUg94A.png

サイズを縮小APKし、アプリケーションをすべての可能なデバイスで実行できるようにするために、、、、およびのアプリケーションを設計しましx86Armv7 Arm各フレーバーには、それぞれのアーキテクチャに対応するネイティブライブラリのみが含まれているため、デバイスアーキテクチャ用に作成されていないものを誰かがインストールする可能性は十分にありAPKます。

クラッシュ時にインストーラーパッケージ名のログ記録を開始しましたが、ユーザーはさまざまなソースからアプリをインストールしており、新しいアプリはすべて、ユーザーがデバイスのアーキテクチャUnsatisfiedLinkErrorが間違っているために誤ってインストールした手動でインストールされたアプリからのものであることがすぐにわかりました。abiこれが最後の「落とし穴」で、とても簡単な説明で安心です。

導入ReLinker

抽出コードを、誰もが使用できる小さなライブラリにパッケージ化することにしました。特に、開発者が制御できない非常に基本的なAndroid機能が含まれている場合は、デバッグプロセスを実行する必要はありません。App

ReLinker標準を置き換えるのと同じくらい簡単に使用できます

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

コールバックを使用する

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

ReLinkerのソースコード

エピローグ

修正がリリースされた時点で、このクラッシュを経験している人の数は約に達し続けました100,000皆様のおReLinker役に立てば幸いです。また、ランダムに遭遇することはありませんUnsatisfiedLinkerError

おすすめ

転載: juejin.im/post/7078905989591728158
おすすめ