Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault when writing encrypted database with vendored SQLCipher and OpenSSL on OpenBSD #1503

Open
link2xt opened this issue May 14, 2024 · 0 comments

Comments

@link2xt
Copy link
Contributor

link2xt commented May 14, 2024

I have minimized segfault to this:

use std::error::Error;
use std::fs;

use rusqlite::{Connection, OpenFlags};

fn main() -> Result<(), Box<dyn Error>> {
    fs::remove_file("foobar.db").ok();
    let conn = Connection::open_with_flags(
        "foobar.db",
        OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE,
    )?;
    conn.pragma_update(None, "key", "foobar")?;
    conn.execute("CREATE TABLE foo (bar INTEGER)", ())?;

    Ok(())
}

Corresponding Cargo.toml:

[package]
name = "minimalsegfault"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rusqlite = { version = "0.31.0", features = ["sqlcipher", "bundled-sqlcipher-vendored-openssl"] }

It does not segfault if bundled-sqlcipher-vendored-openssl feature is removed or replaced with bundled-sqlcipher.

It also does not segfault if I run it under lldb, and then does not segfault if I run it directly as target/debug/minimalsegfault, but starts segfaulting again if I remove target/debug/minimalsegfault and rebuild it:

deltachat$ sha256 target/debug/minmalsegfault
SHA256 (target/debug/minmalsegfault) = 473a948649749621cddd7dc27316323b6e99d9019de079bfaecb5c72b633ac41
deltachat$ target/debug/minmalsegfault
Segmentation fault (core dumped)
deltachat$ lldb target/debug/minmalsegfault
(lldb) target create "target/debug/minmalsegfault"
Current executable set to '/home/user/link2xt/minmalsegfault/target/debug/minmalsegfault' (x86_64).
(lldb) r
Process 81083 launched: '/home/user/link2xt/minmalsegfault/target/debug/minmalsegfault' (x86_64)
Process 81083 exited with status = 0 (0x00000000)
(lldb) ^D
deltachat$ target/debug/minmalsegfault
deltachat$ target/debug/minmalsegfault
deltachat$ rm target/debug/minmalsegfault
deltachat$ cargo build
    Finished dev [unoptimized + debuginfo] target(s) in 0.37s
deltachat$ sha256 target/debug/minmalsegfault
SHA256 (target/debug/minmalsegfault) = 473a948649749621cddd7dc27316323b6e99d9019de079bfaecb5c72b633ac41
deltachat$ target/debug/minmalsegfault
Segmentation fault (core dumped)

Backtrace from gdb:

(gdb) r
Starting program: /home/user/link2xt/minmalsegfault/target/debug/minmalsegfault
Error while reading shared library symbols:
Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/libexec/ld.so]

Program received signal SIGSEGV, Segmentation fault.
aesni_set_encrypt_key () at crypto/aes/aesni-x86_64.s:4326
4326	crypto/aes/aesni-x86_64.s: No such file or directory.
	in crypto/aes/aesni-x86_64.s
Current language:  auto; currently asm
(gdb) bt
#0  aesni_set_encrypt_key () at crypto/aes/aesni-x86_64.s:4326
#1  0x00000a2ed092b5ad in cipher_hw_aesni_initkey (dat=Variable "dat" is not available.
) at cipher_aes_hw_aesni.inc:37
#2  0x00000a2ed098af48 in cipher_generic_init_internal (ctx=Variable "ctx" is not available.
) at providers/implementations/ciphers/ciphercommon.c:221
#3  0x00000a2ed098ae12 in ossl_cipher_generic_einit (vctx=Variable "vctx" is not available.
) at providers/implementations/ciphers/ciphercommon.c:232
#4  0x00000a2ed07234b1 in evp_cipher_init_internal (ctx=Variable "ctx" is not available.
) at refcount.h:52
#5  0x00000a2ed0723613 in EVP_CipherInit_ex (ctx=Variable "ctx" is not available.
) at crypto/evp/evp_enc.c:462
#6  0x00000a2ed097685f in drbg_ctr_set_ctx_params_locked (vctx=Variable "vctx" is not available.
) at providers/implementations/rands/drbg_ctr.c:603
#7  0x00000a2ed09744b0 in drbg_ctr_instantiate_wrapper (vdrbg=Variable "vdrbg" is not available.
) at providers/implementations/rands/drbg_ctr.c:341
#8  0x00000a2ed082b774 in EVP_RAND_instantiate (ctx=Variable "ctx" is not available.
) at crypto/evp/evp_rand.c:517
#9  0x00000a2ed082ce8b in rand_new_drbg (libctx=Variable "libctx" is not available.
) at crypto/rand/rand_lib.c:687
#10 0x00000a2ed082c0c1 in RAND_get0_primary (ctx=Variable "ctx" is not available.
) at crypto/rand/rand_lib.c:734
#11 0x00000a2ed082c563 in RAND_get0_public (ctx=Variable "ctx" is not available.
) at crypto/rand/rand_lib.c:765
#12 0x00000a2ed082c484 in RAND_bytes_ex (ctx=Variable "ctx" is not available.
) at crypto/rand/rand_lib.c:378
#13 0x00000a2ed05bfa9f in sqlcipher_openssl_random (ctx=0x0, buffer=0xa31b1fd8748, length=16) at sqlcipher/sqlite3.c:110178
#14 0x00000a2ed05bdbf9 in sqlcipher_codec_ctx_init_kdf_salt (ctx=0xa31b1fe1328) at sqlcipher/sqlite3.c:108411
#15 0x00000a2ed05be679 in sqlcipher_cipher_ctx_key_derive (ctx=0xa31b1fe1328, c_ctx=0xa31b1fcee78) at sqlcipher/sqlite3.c:108790
#16 0x00000a2ed05be4af in sqlcipher_codec_key_derive (ctx=0xa31b1fe1328) at sqlcipher/sqlite3.c:108860
#17 0x00000a2ed05ba54a in sqlite3Codec (iCtx=0xa31b1fe1328, data=0xa3170ca4008, pgno=1, mode=6) at sqlcipher/sqlite3.c:107084
#18 0x00000a2ed05de20b in pager_write_pagelist (pPager=0xa31b1fcda88, pList=0xa3170ca5040) at sqlcipher/sqlite3.c:61135
#19 0x00000a2ed05ab989 in sqlite3PagerCommitPhaseOne (pPager=0xa31b1fcda88, zSuper=0x0, noSync=0) at sqlcipher/sqlite3.c:63319
#20 0x00000a2ed05abdfa in sqlite3BtreeCommitPhaseOne (p=0xa31b1fdf008, zSuperJrnl=0x0) at sqlcipher/sqlite3.c:74361
#21 0x00000a2ed05ecf79 in vdbeCommit (db=0xa31b1ff6388, p=0xa31b1fde508) at sqlcipher/sqlite3.c:87333
#22 0x00000a2ed05ec29e in sqlite3VdbeHalt (p=0xa31b1fde508) at sqlcipher/sqlite3.c:87743
#23 0x00000a2ed05f36a2 in sqlite3VdbeExec (p=0xa31b1fde508) at sqlcipher/sqlite3.c:93895
#24 0x00000a2ed05af4f1 in sqlite3Step (p=0xa31b1fde508) at sqlcipher/sqlite3.c:90705
#25 0x00000a2ed05a8ee8 in sqlite3_step (pStmt=0xa31b1fde508) at sqlcipher/sqlite3.c:90766
#26 0x00000a2ed058a52a in _ZN8rusqlite13raw_statement12RawStatement4step17h1cc4ee59cbbf8421E (self=0x79b39c47bf40) at raw_statement.rs:106
#27 0x00000a2ed058b477 in _ZN8rusqlite9statement9Statement29execute_with_bound_parameters17ha94539f0bfccc097E (self=0x79b39c47bf38) at statement.rs:659
#28 0x00000a2ed058bd63 in _ZN8rusqlite9statement9Statement7execute17h37b2ea6d243471b8E (self=0x79b39c47bf38, params=0) at statement.rs:113
#29 0x00000a2ed058c960 in _ZN8rusqlite10Connection7execute28_$u7b$$u7b$closure$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$17h95289cb346774e2aE () at lib.rs:622
#30 0x00000a2ed058b91c in _ZN4core6result19Result$LT$T$C$E$GT$8and_then17h156c923f2b70eba2E (self=Variable "self" is not available.
) at result.rs:1316
#31 0x00000a2ed058c8ec in _ZN8rusqlite10Connection7execute28_$u7b$$u7b$closure$u7d$$u7d$17h11bc1bbdb057931cE (stmt=Variable "stmt" is not available.
) at lib.rs:622
#32 0x00000a2ed058b9e7 in _ZN4core6result19Result$LT$T$C$E$GT$8and_then17h9c31c7498f85d62bE (self=Variable "self" is not available.
) at result.rs:1316
#33 0x00000a2ed058c85a in _ZN8rusqlite10Connection7execute17h911cbc4321d9f801E (self=0x79b39c47c0d0, sql=
      {data_ptr = 0xa2ed04acd7f "CREATE TABLE foo (bar INTEGER)src/main.rsdescription() is deprecated; use Display�r", length = 30}, params=0) at lib.rs:621
#34 0x00000a2ed058a855 in _ZN14minmalsegfault4main17haa5db2fd92e500efE () at main.rs:14
#35 0x00000a2ed058aeb2 in _ZN4core3ops8function6FnOnce9call_once17hb96fff8ad01e0288E () at function.rs:250
#36 0x00000a2ed058c485 in _ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17hd166fc0a34471332E (f=0xa2ed058a600 <_ZN14minmalsegfault4main17haa5db2fd92e500efE>)
    at backtrace.rs:155
#37 0x00000a2ed058ab18 in _ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17hac38d9a6d186d8e8E () at rt.rs:166
#38 0x00000a2ed09abe29 in std::rt::lang_start_internal::hf9bc85ac22917681 () from /home/user/link2xt/minmalsegfault/target/debug/minmalsegfault
#39 0x00000a2ed058aaec in _ZN3std2rt10lang_start17hb8161abf303dc758E (main=0xa2ed058a600 <_ZN14minmalsegfault4main17haa5db2fd92e500efE>, argc=1, argv=0x79b39c47c698, sigpipe=0 '\0')
    at rt.rs:165
#40 0x00000a2ed058a9f5 in main () at function.rs:249

I first thought that the problem is a NULL pointer dereference here:

#13 0x00000a2ed05bfa9f in sqlcipher_openssl_random (ctx=0x0, buffer=0xa31b1fd8748, length=16) at sqlcipher/sqlite3.c:110178
#14 0x00000a2ed05bdbf9 in sqlcipher_codec_ctx_init_kdf_salt (ctx=0xa31b1fe1328) at sqlcipher/sqlite3.c:108411

In sqlcipher_codec_ctx_init_kdf_salt the code looks like this around line 108411:

    if(ctx->provider->random(ctx->provider_ctx, ctx->kdf_salt, ctx->kdf_salt_sz) != SQLITE_OK) {

Then in the backtrace we see that sqlcipher_openssl_random is called with ctx=0x0 as the first argument, so apparently ctx->provider_ctx is NULL. But I have looked into SQLCipher code and it seems in case OpenSSL is used as a backend this is intended that provider_ctx is NULL, it is not used anywhere and OpenSSL is initialized globally.

I am running in a VM with OpenBSD current:

$ uname -msrv
OpenBSD 7.5 GENERIC.MP#59 amd64
$ rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09) (built from a source tarball)
$ cargo --version
cargo 1.77.2

Minimal example with a lockfile, segfaulting when you run cargo run:
minimalsegfault.tar.gz

The bug is also reproducible with the latest version of rusqlite repo, commit 6218aa4.

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

No branches or pull requests

2 participants