2

我們的Android軟件爲SQLite使用了一個虛擬文件系統(VFS),它一直在正常工作。一旦我們開始在Android 6(Marshmallow)中使用它,各種奇怪的錯誤開始發生,傳遞給ftruncate(),堆棧溢出,數據損壞等的負偏移量很大。使用readelf(和其他工具),我們最終跟蹤問題到libsqlite.so使用的進口變化:棒棒糖和較早的進口ftruncatemmap,最新的庫進口ftruncate64mmap64。我們通過改變「解決」這個問題我們使用取決於API版本的功能(棉花糖是版本23):當源代碼調用ftruncate時,Android Marshmallow libsqlite.so如何使用ftruncate64?

/* 
* Empirical testing of Tab S2 running Marshmallow revealed the SQLite 
* unix_syscall table uses "ftruncate" and "mmap" as connection points, 
* but the actual functions linked against are the *64 versions. This 
* leads to stack corruption and all sorts of nasty errors as a result. 
*/ 
if (getApiVersion() >= 23) // for Marshmallow 
{ setUnixSystemCall(NULL, "ftruncate", our_ftruncate64); 
    setUnixSystemCall(NULL, "mmap", our_mmap64); 
} 
else      // for Lollipop & older 
{ setUnixSystemCall(NULL, "ftruncate", our_ftruncate); 
    setUnixSystemCall(NULL, "mmap", our_mmap); 
} 

查看源代碼,無論是從http://www.sqlite.org/2015/sqlite-amalgamation-3081002.ziphttps://github.com/android/platform_external_sqlite/blob/master/dist/sqlite3.c所有的C源調用是ftruncatemmap這使得我們的方法「最值得懷疑」。

如何libsqlite.so進口和使用ftruncate64mmap64其中源代碼僅調用ftruncatemmap?我們沒有看到正確的源代碼庫嗎?在鏈接步驟中發生了什麼?棉花糖是否取消了對這些功能的非64位版本的支持?

回答

1

事實證明NDK中的標題並不完全匹配OS所用的相應標題!

仿生:https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include

這裏是爲了建立NDK的方式:https://android.googlesource.com/platform/ndk/+/marshmallow-release

尤其

https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include/unistd.h

#if defined(__USE_FILE_OFFSET64) 
extern int truncate(const char *, off_t) __RENAME(truncate64); 
extern off_t lseek(int, off_t, int) __RENAME(lseek64); 
extern ssize_t pread(int, void *, size_t, off_t) __RENAME(pread64); 
extern ssize_t pwrite(int, const void *, size_t, off_t) __RENAME(pwrite64); 
extern int ftruncate(int, off_t) __RENAME(ftruncate64); 

https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include/sys/mman.h也有類似的宏mmap - 在__RENAME()在系統標頭意味着任何代碼中使用該系統的頭文件(例如,libc.so)將只出口ftruncate64,不ftruncate建,當調用ftruncate應用程序對libc.so鏈接,它代替進口ftruncate64而不是源代碼寫的電話。

我們並沒有潛入__RENAME()宏觀中來研究這種魔法是如何發生的 - 試圖讓產品離開門的現實阻止了我們可以在兔子洞下跌多深。如果有人想進一步調查,那麼這就是你開始的地方。

相關問題