sqlcipher / android-database-sqlcipher

Android SQLite API based on SQLCipher
https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
Other
2.77k stars 566 forks source link

java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlcipher.so" not found #587

Open iadcialim opened 2 years ago

iadcialim commented 2 years ago

Using android-database-sqlcipher:4.4.3 crashes on Samsung Galaxy A32 5G Android 11

Fatal Exception: java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlcipher.so" not found
       at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
       at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
       at java.lang.System.loadLibrary(System.java:1664)
       at net.sqlcipher.database.SQLiteDatabase$1.loadLibraries(SQLiteDatabase.java:227)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:244)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:223)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:216)
       at net.sqlcipher.database.SupportHelper.<init>(SupportHelper.java:31)
       at net.sqlcipher.database.SupportFactory.create(SupportFactory.java:43)
developernotes commented 2 years ago

Hi @iadcialim,

What were your results from running the SQLCipher for Android test suite on the Samsung Galaxy A32 5G Android 11?

iadcialim commented 2 years ago

hi @developernotes I have difficulty verifying this as I got the device information from firebase crashlytics.

stale[bot] commented 2 years ago

Hello, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "bug", "enhancement", or "security" and I will leave it open. Thank you for your contributions.

ItzNotABug commented 2 years ago

There are always going to be some erratic devices that would simply throw an UnsatisfiedLinkError due to internal loading issues. I solved this issue by subclassing the SupportHelper and SupportFactory & used ReLinker to load the libraries if the System failed with an Exception.

Using android-database-sqlcipher:4.5.1.

iadcialim commented 2 years ago

Hi @ItzNotABug Can you share the full source code? Much appreciated.

ItzNotABug commented 2 years ago

@iadcialim Sure.

  1. SupportFactory.kt

    class SupportFactory @JvmOverloads constructor(
    private val passphrase: ByteArray,
    private val hook: SQLiteDatabaseHook? = null,
    private val clearPassphrase: Boolean = true
    ) : SupportSQLiteOpenHelper.Factory {
    override fun create(configuration: SupportSQLiteOpenHelper.Configuration): SupportSQLiteOpenHelper {
        return SupportHelper(configuration, passphrase, hook, clearPassphrase)
    }
    }
  2. SupportHelper.kt

    class SupportHelper internal constructor(
    configuration: SupportSQLiteOpenHelper.Configuration,
    private val passphrase: ByteArray?, hook: SQLiteDatabaseHook?,
    private val clearPassphrase: Boolean
    ) : SupportSQLiteOpenHelper {
    
    // Other Java to Kotlin converted functions.
    
    companion object {
        fun loadSqlCipherLibrary(context: Context, libraryLoadedlistener: (Boolean) -> Unit) {
            val libraryName = "sqlcipher"
            try {
                System.loadLibrary(libraryName)
                libraryLoadedlistener(true)
            } catch (exception: UnsatisfiedLinkError) {
                ReLinker.loadLibrary(context, libraryName, object : ReLinker.LoadListener {
                    override fun success() = libraryLoadedlistener(true)
                    override fun failure(t: Throwable?) = libraryLoadedlistener(false)
                })
            }
        }
    }
    }

And use it like before:

SupportHelper.loadSqlCipherLibrary(appContext) { succeeded ->
    val pass = SQLiteDatabase.getBytes(appContext.strongBlob())
    val roomBuilder = Room.databaseBuilder(
        appContext, AppDatabase::class.java, "app_database"
    )

    if (succeeded) roomBuilder.openHelperFactory(SupportFactory(pass))
    else {
        // other measures..
    }
    roomBuilder.build().also { INSTANCE = it }
}

Note:

  1. See that I use a callback as per my requirement, you can change it as you like.
  2. I have currently hardcoded the "sqlcipher" library as it is the only one used internally. Check SQLiteDatabase.loadLibs(Context, File, LibraryLoader). In future releases, if it changes, you'll have to use a for loop like SQLiteDatabase.loadLibs(Context, File).
Hariharan27 commented 2 years ago

Getting same issue on the below mentioned version "net.zetetic:android-database-sqlcipher:4.4.2" "androidx.sqlite:sqlite-ktx:2.2.0" on the Galaxy Tab A7 Lite (SM-T225N) device it crashes the application Note: We are using app bundles

123dma commented 2 years ago

Hi, I'm also facing the problem reported above. I'm using version net.zetetic:android-database-sqlcipher:4.5.0.

Fatal Exception: java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlcipher.so" not found at java.lang.Runtime.loadLibrary0(Runtime.java:1087) at java.lang.Runtime.loadLibrary0(Runtime.java:1008) at java.lang.System.loadLibrary(System.java:1664) at net.sqlcipher.database.SQLiteDatabase$1.loadLibraries(SQLiteDatabase.java:6) at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:9) at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:8) at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:7) at net.sqlcipher.database.SupportHelper.<init>(SupportHelper.java:5) at net.sqlcipher.database.SupportFactory.create(SupportFactory.java:8)

in this topic it was reported that this problem does not occur in version 4.3.0.

https://discuss.zetetic.net/t/link-failure-on-certain-android-devices/4402

I would like to know if it is safe to downgrade until the problem is fixed. @developernotes

Further details follow.

Is this answer correct? https://stackoverflow.com/a/40675546/4062512

developernotes commented 2 years ago

Hi @123dma

While you shouldn't face any technical issues using SQLCipher for Android 4.3.0 now, it is recommended to use the latest version of the library as it includes many improvements. Instead, here is an approach you might consider applying to address the behavior you are experiencing.

GordonWu commented 2 years ago

I got same issue on multiple devices, I'm using version net.zetetic:android-database-sqlcipher:4.5.0. for fix that i also try ReLinker.loadLibrary, it seem to be reduce some error, but i got the new error below

Fatal Exception: java.lang.RuntimeException: Unable to get provider androidx.startup.InitializationProvider: androidx.startup.StartupException: com.getkeepsafe.relinker.MissingLibraryException: Could not find 'libsqlcipher.so'. Looked for: [armeabi-v7a, armeabi], but only found: [].
       at android.app.ActivityThread.installProvider(ActivityThread.java:7416)
       at android.app.ActivityThread.installContentProviders(ActivityThread.java:6956)
       at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6844)
       at android.app.ActivityThread.access$1300(ActivityThread.java:268)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1982)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:237)
       at android.app.ActivityThread.main(ActivityThread.java:7814)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)

I have been checked apk lib folder, the libsqlcipher.so is exist.

can someone help me to fix that?

developernotes commented 2 years ago

Hi @GordonWu

Thanks for reaching out, I have a few additional questions regarding your situation:

ReLinker.log(myLogger).loadLibrary(...);
GordonWu commented 2 years ago

Hi @developernotes Thanks for reply

developernotes commented 2 years ago

Hi @GordonWu

Thanks for your follow-up, that is helpful. Since you are deploying with App Bundles, would you consider another adjustment to the library loading approach with your next release? With ReLinker, would you adjust your usage to provide a LoadListener implementation (see usage), and in the failure call, use the SplitInstallHelper to load your library as that is meant for supporting split APK's.

GordonWu commented 2 years ago

Hi @developernotes

Thanks for the tip! I will try it for next release.

GordonWu commented 2 years ago

Hi @developernotes,

There is no luck :( I tried the way you said, although not getting MissingLibraryException but it came back java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader ,nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]] couldn't find "libsqlcipher.so".

currently i can do for now is try catch when this error occur, cancel db init and disable related functions.

developernotes commented 2 years ago

Hi @GordonWu

Thank you for your follow-up, that is unfortunate to hear the SplitInstallHelper did not resolve the issue. Can you confirm that java.lang.UnsatisfiedLinkError is being thrown when you call loadLibrary from SplitInstallHelper? Additionally, are you using this in conjunction with ReLinker?

GordonWu commented 2 years ago

Hi @developernotes

Yes, I'm use with ReLinker, here the source, the error thrown is at line SplitInstallHelper.loadLibrary(context, "sqlcipher") after Relinker LoadListener#failure

class SqlCipherInitializer : Initializer<Unit> {
    override fun create(context: Context) {
        CoroutineScope(Dispatchers.IO).launch {
            loadSqlCipherLibrary(context) { succeeded ->
                if (!succeeded) {
                    try {
                        SplitInstallHelper.loadLibrary(context, "sqlcipher")
                        return@loadSqlCipherLibrary
                    } catch (e: Exception) {
                        return@loadSqlCipherLibrary
                    }
                }

               (...some code for init database)
            }
        }
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }

    private fun loadSqlCipherLibrary(context: Context, libraryLoadedListener: (Boolean) -> Unit) {
        val libraryName = "sqlcipher"
        try {
            System.loadLibrary(libraryName)
            libraryLoadedListener(true)
        } catch (exception: UnsatisfiedLinkError) {
            ReLinker.loadLibrary(context, libraryName, object : ReLinker.LoadListener {
                override fun success() = libraryLoadedListener(true)
                override fun failure(t: Throwable?) = libraryLoadedListener(false)
            })
        }
    }
}
iadcialim commented 2 years ago

There are always going to be some erratic devices that would simply throw an UnsatisfiedLinkError due to internal loading issues. I solved this issue by subclassing the SupportHelper and SupportFactory & used ReLinker to load the libraries if the System failed with an Exception.

Using android-database-sqlcipher:4.5.1.

hi @ItzNotABug thank you for your info and src code here. i just got back to this issue once again. By the way, I don't see the purpose of subclassing SupportHelper and SupportFactory but I see that this code is the only difference here

companion object {
        fun loadSqlCipherLibrary(context: Context, libraryLoadedlistener: (Boolean) -> Unit) {
            val libraryName = "sqlcipher"
            try {
                System.loadLibrary(libraryName)
                libraryLoadedlistener(true)
            } catch (exception: UnsatisfiedLinkError) {
                ReLinker.loadLibrary(context, libraryName, object : ReLinker.LoadListener {
                    override fun success() = libraryLoadedlistener(true)
                    override fun failure(t: Throwable?) = libraryLoadedlistener(false)
                })
            }
        }
    }

Or am I missing something? Thanks

iadcialim commented 2 years ago
SqlCipherInitializer

Hi @developernotes @GordonWu Sorry mates. Im a bit confused on the floating src codes and can't figure out on how to use all of them. We got codes from: a. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1143340726 b. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1246162180 c. https://github.com/sqlcipher/android-database-sqlcipher/issues/593#issuecomment-1216728997

Can someone guide me on the correct sequence of steps on applying these workaround? Much appreciated

ItzNotABug commented 2 years ago

There are always going to be some erratic devices that would simply throw an UnsatisfiedLinkError due to internal loading issues. I solved this issue by subclassing the SupportHelper and SupportFactory & used ReLinker to load the libraries if the System failed with an Exception.

Using android-database-sqlcipher:4.5.1.

hi @ItzNotABug thank you for your info and src code here. i just got back to this issue once again.

By the way, I don't see the purpose of subclassing SupportHelper and SupportFactory but I see that this code is the only difference here


companion object {

        fun loadSqlCipherLibrary(context: Context, libraryLoadedlistener: (Boolean) -> Unit) {

            val libraryName = "sqlcipher"

            try {

                System.loadLibrary(libraryName)

                libraryLoadedlistener(true)

            } catch (exception: UnsatisfiedLinkError) {

                ReLinker.loadLibrary(context, libraryName, object : ReLinker.LoadListener {

                    override fun success() = libraryLoadedlistener(true)

                    override fun failure(t: Throwable?) = libraryLoadedlistener(false)

                })

            }

        }

    }

Or am I missing something? Thanks

Yes, Directly loading the libraries without extending he classes would work just fine. I had some other requirements at that time which required extending those classes, guess I missed that point & added the whole solution which wasn't necessary.

GordonWu commented 2 years ago
SqlCipherInitializer

Hi @developernotes @GordonWu Sorry mates. Im a bit confused on the floating src codes and can't figure out on how to use all of them. We got codes from: a. #587 (comment) b. #587 (comment) c. #593 (comment)

Can someone guide me on the correct sequence of steps on applying these workaround? Much appreciated

Hi, @iadcialim I believe that all floating src codes are pointing to the same thing, we try use ReLinker to solve dlopen failed: library "libsqlcipher.so" not found issue, and I also with use SplitInstallHelper when use aab to release product.

So, the core idea is start from b. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1246162180 , and a. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1143340726 is more completely code, the last c. https://github.com/sqlcipher/android-database-sqlcipher/issues/593#issuecomment-1216728997 is my current use code

BTW, SqlCipherInitializer : Initializer is part of android jetpack's App Startup

iadcialim commented 2 years ago

Thank you for your answers @GordonWu 1 more question: In what scenario do we need to call SQLiteDatabase.loadLibs(this);? Currently, I do not call this and this library works just fine.

GordonWu commented 2 years ago

Ah gosh, @iadcialim I'm very sorry about that, I just noticed now that I'm replying in the wrong order,

C. https://github.com/sqlcipher/android-database-sqlcipher/issues/593#issuecomment-1216728997 >>>> A. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1143340726 >>>> B. https://github.com/sqlcipher/android-database-sqlcipher/issues/587#issuecomment-1246162180

B. #587 is my current code, so i do not call this too.

iadcialim commented 2 years ago

Ah ok noted @GordonWu thanks mate

iadcialim commented 2 years ago

Thank you for your answers @GordonWu 1 more question: In what scenario do we need to call SQLiteDatabase.loadLibs(this);? Currently, I do not call this and this library works just fine.

@developernotes Do you know when should we call this?

developernotes commented 2 years ago

Hi @iadcialim

Thank you for your answers @GordonWu 1 more question: In what scenario do we need to call SQLiteDatabase.loadLibs(this);? Currently, I do not call this and this library works just fine.

You need to call SQLiteDatabase.loadLibs(...) ^1 prior to invoking a SQL operation that will perform encryption/decryption on the database?

jae-12 commented 1 year ago

Hey @iadcialim , do you know if your minimum sdk was higher than 23? or lower? I'm having a similar issue and was debating if we should add ReLinker or not but the ReLinker's github README indicates that I won't need it if minsdk is higher than 23. If you could let me know, it'd be very appreciated.

iadcialim commented 1 year ago

Hey @iadcialim , do you know if your minimum sdk was higher than 23? or lower? I'm having a similar issue and was debating if we should add ReLinker or not but the ReLinker's github README indicates that I won't need it if minsdk is higher than 23. If you could let me know, it'd be very appreciated.

Hi @jae-12 My minimum sdk is exactly 23. My app is has been live for 3 weeks now and so far my app did not encounter issue on System.loadLibrary("sqlcipher"). So it means my app has not tried using ReLinker yet as plan B.

Psijic commented 1 year ago

I got this error just recently. minSdk = 26, "net.zetetic:android-database-sqlcipher:4.5.4"

Fatal Exception: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader couldn't find "libsqlcipher.so"
       at java.lang.Runtime.loadLibrary0(Runtime.java:1029)
       at java.lang.System.loadLibrary(System.java:1673)
       at net.sqlcipher.database.SQLiteDatabase$1.loadLibraries(:6)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:3)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:2)
       at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:1)
       at net.sqlcipher.database.SupportHelper.<init>(SupportHelper.java:5)
       at net.sqlcipher.database.SupportFactory.create(SupportFactory.java:8)

Model:Samsung Galaxy A70 Version:Android 8.1.0 Rooted:Yes Crash Date:Sep 26, 2023

Also Nexus 5X Android 12 not rooted affected.

goldfish07 commented 1 year ago

try this https://github.com/sqlcipher/android-database-sqlcipher/issues/635#issuecomment-1782209894

qsdigor commented 9 months ago

I have the same issue as described here. I have been using useLegacyPackaging = true but with no luck.

developernotes commented 9 months ago

Hi @qsdigor,

There appear to be many factors that may cause this issue for some users. Have you tried using ReLinker in conjunction with a call to SplitInstallHelper.loadLibrary(...)?

ashishgingercube commented 8 months ago

Hi, I have replaced SQLiteDatabase.loadLibs(_mContext); with

SQLiteDatabase.loadLibs(_mContext, libraries -> { for (String library : libraries) { ReLinker.loadLibrary(_mContext, library); } });

But I still get this error

java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlcipher.so" not found

developernotes commented 8 months ago

Hi @ashishgingercube,

I believe this is related to your existing issue #643. Would you please keep your replies within the same thread?