问题

百度网盘推出Linux客户端已经有一段时间了。 期间,在Fedora32时我就已经给他们提过一个启动即crash的问题,后面一直也没修复.

baidu-netdisk-crash-2020-11-12_19-15.png

这都 Fedora 33了,我又提了一次,而且还把gdb的backtrace发给了他们,显示已经处理。 实际上几个月过去了都没见动静。只能自己动手,丰衣足食了。

解决

老灯注意到, 百度网盘链接的库都是比较老的,因此那个客户端在Ubuntu 18.04 上面肯定是可以正常运行。

那个 rpm 包压根不是对标最新的Fedora的,而是给那些基于RHEL的同样使用rpm包管理的古董国产操作系统使用的。

因此老灯下载 baidunetdisk_3.5.0_amd64.deb,并解压出实际的程序.

首先我们跑一下,看看bt 吧:

Thread 1 "baidunetdisk" received signal SIGSEGV, Segmentation fault.
0x00007ffff5096179 in EVP_MD_CTX_clear_flags () from /lib64/libcrypto.so.1.1

(gdb) bt
#0  0x00007ffff5096179 in EVP_MD_CTX_clear_flags () at /lib64/libcrypto.so.1.1
#1  0x00007ffff508b261 in EVP_DigestInit_ex () at /lib64/libcrypto.so.1.1
#2  0x00007ffff50ab1e8 in HMAC_Init_ex () at /lib64/libcrypto.so.1.1
#3  0x00007fffd1a92766 in sqlcipher_openssl_hmac
    (ctx=<optimized out>, hmac_key=0x227a99ce02d8 "\f>@)YUj\001\346\063vr\312\062\016\243\232\312\334\324\302\027\201-\330ƨ\213É<)", key_sz=32, in=0x227a9a00b548 "\250\235J_h1E\214\v\033u\266\342P.\240\063\244\337V\313\360T\rqu<c:\303E\234\061-\216\365\255\033Dz\203\b\001\027\257\215\033\070{i9H\376\346H\223DB\244\001\314d\302\022\310\376\315\b\343\"\362e\227\252T\363\215\351\323\005\271\022ǎ\340 \205\a墭\240ZЯ\266\330 \335\334\314ё\255\262a+N\367\021\214\322\b\021)\356\362=\201\310\354\005\273o\250a)$\254z\226\371\322\003n\241\244Z\032\277\217\060\225\353.\276\001\206;\245Ȩ\245\211㓫\326\313\370V\360\327\t\310RX\362\026P\223\302\032\027\351\067\003|\034\024\r\021R\233\334R=\376&\022\b\235\033\313\315\361mW", <incomplete sequence \310>..., in_sz=976, in2=0x7fffffffa910 "\001", in2_sz=4, out=0x227a99f925e8 "")
    at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:18404
#4  0x00007fffd1ab03aa in sqlcipher_page_hmac
    (out=0x227a99f925e8 "", in_sz=<optimized out>, in=0x227a9a00b548 "\250\235J_h1E\214\v\033u\266\342P.\240\063\244\337V\313\360T\rqu<c:\303E\234\061-\216\365\255\033Dz\203\b\001\027\257\215\033\070{i9H\376\346H\223DB\244\001\314d\302\022\310\376\315\b\343\"\362e\227\252T\363\215\351\323\005\271\022ǎ\340 \205\a墭\240ZЯ\266\330 \335\334\314ё\255\262a+N\367\021\214\322\b\021)\356\362=\201\310\354\005\273o\250a)$\254z\226\371\322\003n\241\244Z\032\277\217\060\225\353.\276\001\206;\245Ȩ\245\211㓫\326\313\370V\360\327\t\310RX\362\026P\223\302\032\027\351\067\003|\034\024\r\021R\233\334R=\376&\022\b\235\033\313\315\361mW", <incomplete sequence \310>..., pgno=<optimized out>, ctx=0x227a99d3f078) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:17506
#5  sqlcipher_page_cipher
    (ctx=[email protected]=0x227a99d095a8, for_ctx=[email protected]=0, pgno=<optimized out>, mode=[email protected]=0, page_sz=1008, in=0x227a9a00b548 "\250\235J_h1E\214\v\033u\266\342P.\240\063\244\337V\313\360T\rqu<c:\303E\234\061-\216\365\255\033Dz\203\b\001\027\257\215\033\070{i9H\376\346H\223DB\244\001\314d\302\022\310\376\315\b\343\"\362e\227\252T\363\215\351\323\005\271\022ǎ\340 \205\a墭\240ZЯ\266\330 \335\334\314ё\255\262a+N\367\021\214\322\b\021)\356\362=\201\310\354\005\273o\250a)$\254z\226\371\322\003n\241\244Z\032\277\217\060\225\353.\276\001\206;\245Ȩ\245\211㓫\326\313\370V\360\327\t\310RX\362\026P\223\302\032\027\351\067\003|\034\024\r\021R\233\334R=\376&\022\b\235\033\313\315\361mW", <incomplete sequence \310>..., out=0x227a99f92218 "") at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:17556
#6  0x00007fffd1ac1a84 in sqlite3Codec (iCtx=0x227a99d095a8, data=0x227a9a00b538, pgno=1, mode=3) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:16249
#7  0x00007fffd1a93595 in readDbPage ([email protected]=0x227a9a00b970, iFrame=<optimized out>) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:50416
#8  0x00007fffd1adf61e in sqlite3PagerGet (pPager=0x227a99f44008, pgno=pg[email protected]=1, [email protected]=0x7fffffffaa68, [email protected]=0)
    at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:52923
#9  0x00007fffd1ae1d08 in btreeGetPage (flags=0, ppPage=<synthetic pointer>, pgno=1, pBt=0x227a99fb3648) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:60539
#10 lockBtree ([email protected]=0x227a99fb3648) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:61441
#11 0x00007fffd1ae5af0 in sqlite3BtreeBeginTrans (p=0x227a99d683c8, wrflag=0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:61799
#12 0x00007fffd1b17fe8 in sqlite3InitOne ([email protected]=0x227a99f67e08, [email protected]=0, [email protected]=0x227a99c81090) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:112652
#13 0x00007fffd1b1822c in sqlite3Init ([email protected]=0x227a99f67e08, [email protected]=0x227a99c81090) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:112831
#14 0x00007fffd1b1a098 in sqlite3ReadSchema (pParse=0x227a99c81088) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:112868
#15 sqlite3LocateTable (pParse=0x227a99c81088, isView=0, zName=0x227a99fea708 "sqlite_master", zDbase=0x0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:32141
#16 0x00007fffd1b1a84a in selectExpander (pWalker=0x7fffffffadb0, p=0x227a99fea208) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:117593
#17 0x00007fffd1aa2e02 in sqlite3WalkSelect ([email protected]=0x7fffffffadb0, [email protected]=0x227a99fea208) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:87991
#18 0x00007fffd1aa327f in sqlite3WalkSelect (p=0x227a99fea208, pWalker=0x7fffffffadb0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:87988
#19 sqlite3SelectExpand (pSelect=0x227a99fea208, pParse=0x227a99c81088) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:52306
#20 sqlite3SelectPrep (pParse=0x227a99c81088, p=0x227a99fea208, pOuterNC=0x0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:52392
#21 0x00007fffd1af7762 in sqlite3Select ([email protected]=0x227a99c81088, p=0x227a99fea208, [email protected]=0x7fffffffb0e0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:118172
#22 0x00007fffd1b1250d in yy_reduce (yyruleno=111, yypParser=0x227a99abe708) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:133385
#23 sqlite3Parser ([email protected]=0x227a99abe708, [email protected]=1, yyminor=..., [email protected]=0x227a99c81088) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:3399
#24 0x00007fffd1b15fbe in sqlite3RunParser
    (pParse=[email protected]=0x227a99c81088, zSql=[email protected]=0x7fffd1b3c178 "SELECT name FROM sqlite_master WHERE type='table' AND name=:tbl_name", pzErrMsg=[email protected]=0x7fffffffb1f8)
    at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:135410
#25 0x00007fffd1b169a9 in sqlite3Prepare
    (db=[email protected]=0x227a99f67e08, zSql=[email protected]=0x7fffd1b3c178 "SELECT name FROM sqlite_master WHERE type='table' AND name=:tbl_name", nBytes=[email protected]=-1, saveSqlFlag=[email protected]=1, pReprepare=[email protected]=0x0, ppStmt=[email protected]=0x7fffffffb378, pzTail=0x0) at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:113061
#26 0x00007fffd1b16ea0 in sqlite3LockAndPrepare
    (db=0x227a99f67e08, zSql=0x7fffd1b3c178 "SELECT name FROM sqlite_master WHERE type='table' AND name=:tbl_name", nBytes=-1, saveSqlFlag=1, pOld=0x0, ppStmt=0x7fffffffb378, pzTail=0x0)
    at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:113153
#27 0x00007fffd1b173b6 in sqlite3_prepare_v2 (db=<optimized out>, zSql=<optimized out>, nBytes=<optimized out>, ppStmt=<optimized out>, pzTail=<optimized out>)
--Type <RET> for more, q to quit, c to continue without paging--c
    at /home/neokylinv7/桌面/SourceCode/mazu/source/sqlcipher/sqlite3.c:113229
#28 0x00007fffd185cf6d in baiduyun::minos::database::SqliteStatement::prepare(char const*) ([email protected]=0x7fffffffb360, [email protected]=0x7fffd1b3c178 "SELECT name FROM sqlite_master WHERE type='table' AND name=:tbl_name") at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/base/database_statement.cpp:34
#29 0x00007fffd185c3e5 in baiduyun::minos::database::SqliteConnection::table_existed(char const*) (this=<optimized out>, [email protected]=0x7fffd1b983f2 "version") at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/base/database_connection.cpp:134
#30 0x00007fffd18b0bde in baiduyun::minos::database::TransmitDataInstance::initialize(char const*, baiduyun::minos::database::SqliteEncrytKeys const&) (this=0x227a999be900, path=0x227a99d3f0f8 "/home/ttys3/.config/baidunetdisk/AppData/at_trche", encrypt_keys=...) at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/persist/transmit_data_instance.cpp:74
#31 0x00007fffd185f431 in baiduyun::minos::log::LogController::initialize(char const*, baiduyun::minos::database::SqliteEncrytKeys const&) (this=0x227a99d4e3c0, [email protected]=0x227a995bbe98 "{\"root\":\"\\/home\\/ttys3\\/.config\\/baidunetdisk\\/AppData\\/\",\"name\":\"at\",\"use_default_key\":\"1\"}\n", encrypt_keys=...) at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/log/log_controller.cpp:109
#32 0x00007fffd1848f79 in (anonymous namespace)::logcontroller_initialize (encrypt_keys=..., config=0x227a995bbe98 "{\"root\":\"\\/home\\/ttys3\\/.config\\/baidunetdisk\\/AppData\\/\",\"name\":\"at\",\"use_default_key\":\"1\"}\n") at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/minos-agent.cpp:47
#33 minos_agent_global_init(char const*, void const*, int, void const*, int) (config=0x227a995bbe98 "{\"root\":\"\\/home\\/ttys3\\/.config\\/baidunetdisk\\/AppData\\/\",\"name\":\"at\",\"use_default_key\":\"1\"}\n", encrypt_key=<optimized out>, key_len=<optimized out>, encrypt_newkey=0x0, newkey_len=<optimized out>) at /home/neokylinv7/桌面/SourceCode/mazu/source/kernel/minos-agent.cpp:141
#34 0x00007fffe08e5008 in baidu::netdisk::sdk::sdk_minos_init (newkey_len=0, encrypt_newkey=0x0, key_len=0, encrypt_key=0x0, config=0x227a995bbe98 "{\"root\":\"\\/home\\/ttys3\\/.config\\/baidunetdisk\\/AppData\\/\",\"name\":\"at\",\"use_default_key\":\"1\"}\n") at /home/common/桌面/project/browserengine/source/browserengine/sdk/minosagent/minos_wrapper.h:32
#35 baidu::netdisk::sdk::MinosConfigManager::init_minos(std::string const&) ([email protected]=0x7fffffffbc5e, app_path="/home/ttys3/.config/baidunetdisk") at /home/common/桌面/project/browserengine/source/browserengine/sdk/minosagent/minos_config_manager.cpp:61
#36 0x00007fffe0731c87 in browser_engine_global_init(browser_engine_internal_log_callback, browser_engine_common_event_callback) (log_callback=<optimized out>, event_callback=<optimized out>) at /home/common/桌面/project/browserengine/source/browserengine/browser_engine.cpp:144
#37 0x00007ffff6159b10 in ffi_call_unix64 () at /lib64/libffi.so.6
#38 0x00007ffff61590a3 in ffi_call () at /lib64/libffi.so.6
#39 0x00007fffe0f927f9 in FFI::FFICall(Nan::FunctionCallbackInfo<v8::Value> const&) () at /tmp/.org.chromium.Chromium.gNqpPK
#40 0x00007fffe0f925a6 in Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) () at /tmp/.org.chromium.Chromium.gNqpPK
#41 0x0000555557cdc6d7 in  ()

目测翻车在libcrypto.so.1.1, 而且是跟sqlite加密有关.

我们把baidunetdisk动态链接到相关的加密库都找出来:

❯ ldd baidunetdisk | grep -i -E 'ssl|crypt'
	libgcrypt.so.20 => /lib64/libgcrypt.so.20 (0x00007fa18d693000)
	libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fa18d3cd000)
	libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007fa18d0c0000)

经验告诉我,这个baidunetdisk挂的原因是, Fedora 33上面的包都比较新,尤其是 openssl 库. 因此,解决办法是,去下载老版本的 Ubuntu 18.04 的包,然后把so文件取出来,强制baidunetdisk使用这些旧版本的库即可.

ldd 一下很容易找出依赖关系: libkrb5.so.3 -> libk5crypto.so.3 -> libcrypto.so.1.1

老灯下载了以下包:

https://ubuntu.pkgs.org/18.04/ubuntu-main-amd64/libkrb5support0_1.16-2build1_amd64.deb.html
https://ubuntu.pkgs.org/18.04/ubuntu-main-amd64/libk5crypto3_1.16-2build1_amd64.deb.html
https://ubuntu.pkgs.org/18.04/ubuntu-main-amd64/libkrb5-3_1.16-2build1_amd64.deb.html
https://ubuntu.pkgs.org/18.04/ubuntu-main-amd64/libgssapi-krb5-2_1.16-2build1_amd64.deb.html
http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb

测试下, krb 的包已经成功加载:

❯ env LD_LIBRARY_PATH=$(pwd) ldd ./baidunetdisk | grep /opt/
	libffmpeg.so => /opt/baidunetdisk/./libffmpeg.so (0x00007f8fc36a8000)
	libgssapi_krb5.so.2 => /opt/baidunetdisk/./libgssapi_krb5.so.2 (0x00007f8fc1588000)
	libkrb5.so.3 => /opt/baidunetdisk/./libkrb5.so.3 (0x00007f8fc0bf4000)
	libk5crypto.so.3 => /opt/baidunetdisk/./libk5crypto.so.3 (0x00007f8fc09c2000)
	libkrb5support.so.0 => /opt/baidunetdisk/./libkrb5support.so.0 (0x00007f8fc07af000)

编辑 /usr/share/applications/baidunetdisk.desktop, 将Exec=/opt/baidunetdisk/baidunetdisk --no-sandbox %U 修改成:

Exec=/bin/env LD_LIBRARY_PATH=/home/ttys3/Apps/baidunetdisk /home/ttys3/Apps/baidunetdisk/baidunetdisk --no-sandbox %U

注意,这里老灯把baidu的目录放在/home/ttys3/Apps/baidunetdisk, 测试过程中发现放在默认的 /opt/baidunetdisk 无法成功运行(有可能跟selinux有关,暂时没空看了,解决了问题完事)。

baidunetdisk-fedora33-2020-12-20_21-53.png