最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android Native fdsan檢測工具介紹

 更新時間:2023年02月10日 09:27:08   作者:蘆半山  
這篇文章主要為大家介紹了Android Native fdsan檢測工具介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

本文分析基于Android T(13)

fdsan,全名為file descriptor sanitizer,是Android中的一種檢測工具,用于檢測fd的use-after-close和double-close錯誤。這兩個錯誤會給設備留下安全漏洞,甚至造成數據泄露等安全問題。然而現實情況是這兩種錯誤非常隱蔽,且難以排查。這才催生了fdsan的誕生。

fdsan由Google的工程師Josh Gao開發(fā)。最初在Android 10中引入,檢測到錯誤時會打印log并繼續(xù)運行。Android 11更改了運行模式,一旦檢測到錯誤就立即abort,讓問題暴露得更加醒目。

要讓這些問題可以被檢測,關鍵是要構建fd的所有權體系。

這套體系的建立有兩個重要前提:

  • Android中大多數fd并非直接通過open/close的原生接口進行管理,而是通過unique_fd,FileOutputStream,ParcelFileDescriptor之類的封裝形式。
  • fd是一個整數,且每個進程所能創(chuàng)建的fd都有上限,早期為1024,現在為32768。因此即便為每個fd創(chuàng)建單獨的所有權管理數據也不會消耗多少空間。

一個fd由生到死的所有者

基于這兩個條件,fdsan使用一個64-bit的tag來表明一個fd由生到死的所有者。

tag組成

tag由兩部分組成,最高位的8-bit構成type,后面的56-bit構成value。Type表示fd通過何種封裝形式進行管理,譬如ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD就表示fd通過unique_fd進行管理。

對于應用工程師而言,他們接觸到的大多為Java/Kotlin代碼,因此Java中常用的FileInputStream/FileOutputStream/ParcelFileDescriptor等封裝形式也有相應的type。

詳細列表如下。

enum android_fdsan_owner_type {
  /*
   * Generic Java or native owners.
   *
   * Generic Java objects always use 255 as their type, using identityHashCode
   * as the value of the tag, leaving bits 33-56 unset. Native pointers are sign
   * extended from 48-bits of virtual address space, and so can have the MSB
   * set to 255 as well. Use the value of bits 49-56 to distinguish between
   * these cases.
   */
  ANDROID_FDSAN_OWNER_TYPE_GENERIC_00 = 0,
  ANDROID_FDSAN_OWNER_TYPE_GENERIC_FF = 255,
  /* FILE* */
  ANDROID_FDSAN_OWNER_TYPE_FILE = 1,
  /* DIR* */
  ANDROID_FDSAN_OWNER_TYPE_DIR = 2,
  /* android::base::unique_fd */
  ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD = 3,
  /* sqlite-owned file descriptors */
  ANDROID_FDSAN_OWNER_TYPE_SQLITE = 4,
  /* java.io.FileInputStream */
  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 5,
  /* java.io.FileOutputStream */
  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 6,
  /* java.io.RandomAccessFile */
  ANDROID_FDSAN_OWNER_TYPE_RANDOMACCESSFILE = 7,
  /* android.os.ParcelFileDescriptor */
  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
  /* ART FdFile */
  ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE = 9,
  /* java.net.DatagramSocketImpl */
  ANDROID_FDSAN_OWNER_TYPE_DATAGRAMSOCKETIMPL = 10,
  /* java.net.SocketImpl */
  ANDROID_FDSAN_OWNER_TYPE_SOCKETIMPL = 11,
  /* libziparchive's ZipArchive */
  ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE = 12,
};

tag中的value主要用作唯一性標識。對于native層的封裝(譬如unique_fd)而言,value為封裝對象的指針值;對于Java層的封裝(譬如FileInputStream)而言,value為封裝對象的hash code。這兩種值在同一個進程里都具有唯一性。

tag的創(chuàng)建和檢驗過程

了解完tag的構成后,接下來便是tag的創(chuàng)建和檢驗過程。

通過封裝對象創(chuàng)建相應fd時(通常在對象的構造函數內),tag便會創(chuàng)建。而所有的close都會去進行tag檢驗,不論該close是通過封裝對象的析構調用還是直接調用。舉個例子,當一個fd通過FileInputStream創(chuàng)建時,對象回收期間便會close fd??墒侨绻覀儾恍⌒膶⒋薴d傳到了JNI函數中,通過close函數直接去操作它,那么檢測時我們就會發(fā)現:期望的tag是一個非零值(由type和value構成),實際的tag為0(通過原生close函數進行操作時tag為0),繼而報錯。

典型的報錯log如下(與上述例子無關),一個通過opendir打開的fd,最終卻直接通過close關閉,而不是closedir。

pid: 610, tid: 610, name: lmkd  >>> /system/bin/lmkd <<<
uid: 1069
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: 'fdsan: attempted to close file descriptor 15, expected to be unowned, actually owned by DIR* 0x745b003c00'
    x0  0000000000000000  x1  0000000000000262  x2  0000000000000006  x3  0000007fc8696f90
    x4  0000000000000000  x5  0000000000000000  x6  0000000000000000  x7  0000000000000010
    x8  00000000000000f0  x9  643eeef5a527dc04  x10 0000000000000001  x11 0000000000000000
    x12 0000000000000008  x13 0000000060345fc8  x14 000216096eb6f000  x15 000024dad07fc39e
    x16 000000745b715948  x17 000000745b6f4390  x18 000000745c0bc000  x19 0000000000000262
    x20 0000000000000262  x21 000000745bc34000  x22 000000745cfdeb5c  x23 0000000000000003
    x24 0000007fc8697080  x25 ffffff80ffffffc8  x26 0000007fc8696d00  x27 0000007fc8696cc0
    x28 0000000000000000  x29 0000007fc8697020
    lr  000000745b6abf4c  sp  0000007fc8696c40  pc  000000745b6abf6c  pst 0000000000001000
backtrace:
      #00 pc 000000000008df6c  /apex/com.android.runtime/lib64/bionic/libc.so (fdsan_error(char const*, ...)+588)
      #01 pc 000000000008dc68  /apex/com.android.runtime/lib64/bionic/libc.so (android_fdsan_close_with_tag+740)
      #02 pc 000000000008e3d0  /apex/com.android.runtime/lib64/bionic/libc.so (close+16)
      #03 pc 000000000000b110  /system/bin/lmkd (start_wait_for_proc_kill(int)+184)
      #04 pc 000000000000a45c  /system/bin/lmkd (find_and_kill_process(int, int, char const*, meminfo*, timespec*, bool)+744)
      #05 pc 00000000000098a0  /system/bin/lmkd (mp_event_common(int, unsigned int, polling_params*)+2140)
      #06 pc 000000000000ba1c  /system/bin/lmkd (call_handler(event_handler_info*, polling_params*, unsigned int)+64)
      #07 pc 00000000000053a8  /system/bin/lmkd (main+2440)
      #08 pc 000000000008506c  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)

且慢,討論了這么久的tag到底存在什么地方?可以肯定的是存在一個全局的table中,由于fd是一個32768以內的整數,因此可以將fd作為table的索引。此外,Josh將這個table設計成可擴容的,初始大小為128,擴容后可以存放下所有fd的tag。這樣對于大多數fd創(chuàng)建數量較少的進程,便可以使用較小的table來節(jié)省內存。

fdsan自引入之際便全局打開,對于保障系統的安全至關重要。但受限于它的原理,仍然有一些fd的use-after-close和double-close錯誤無法被檢出。它們是:

  • 不使用任何封裝形式,而只是通過open和close來操作fd。這樣即便對同一個fd double-close,由于期望的tag和實際的tag都為0,因此錯誤無法檢出。
  • 使用自定義的封裝形式來操作fd,而沒有在自定義的形式中接入fdsan。無法檢出的理由同上。
  • 單純的use-after-close,而并非由double-close引發(fā)的use-after-close也無法檢出。嚴格意義上來說,我認為這個工具只能檢出fd的double-close。原因是檢測代碼只插入在close函數里,對于fd的其他操作并無檢測。

除了檢測fd的錯誤外,存在全局table中的tag數據在生成tombstone時也會輸出,表示每個fd的ownership。unowned表明該fd的創(chuàng)建未接入fdsan。

open files:
...
fd 47: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/base.apk (owned by ZipArchive 0xfffd2ae7dd90)
fd 48: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/split_config.arm64_v8a.apk (owned by ZipArchive 0xfffd2ae82390)
fd 49: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/split_config.en.apk (owned by ZipArchive 0xfffd2ae83ac0)
fd 50: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/split_config.hdpi.apk (owned by ZipArchive 0xfffd2ae84e00)
fd 51: /data/data/com.tencent.mm/files/splitcompat/2103/verified-splits/delivery.config.arm64_v8a.apk (owned by ZipArchive 0xfffd2ae80b10)
fd 52: /data/data/com.tencent.mm/files/splitcompat/2103/verified-splits/delivery.apk (owned by ZipArchive 0xfffd2ae803a0)
fd 53: anon_inode:[eventfd] (owned by unique_fd 0xfffd7ae85e84)
fd 54: anon_inode:[eventpoll] (owned by unique_fd 0xfffd7ae85edc)
fd 55: anon_inode:[eventfd] (owned by unique_fd 0xfffd7ae99ce4)
fd 56: anon_inode:[eventpoll] (owned by unique_fd 0xfffd7ae99d3c)
fd 57: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/base.apk (unowned)
fd 58: /data/app/~~TPUHOtvHOT-iL2f4uUrFSg==/com.tencent.mm-FKuS1oTvzRpPMOXX-SE_ZQ==/split_config.arm64_v8a.apk (unowned)

最后值得注意的一點是,fdsan在vfork得到的子進程里是不工作的。原因是vfork得到的子進程雖然會拷貝父進程的fd,但是使用的地址空間仍然屬于父進程。因此fd和存儲fd tag的內存產生了錯配,在子進程中操作fd不會被父進程感知到,而tag的修改則會直接影響父進程的table。

【參考文檔】 android.googlesource.com/platform/bi…

以上就是Android Native fdsan檢測工具介紹的詳細內容,更多關于Android Native fdsan檢測工具的資料請關注腳本之家其它相關文章!

相關文章

最新評論

安泽县| 远安县| 吕梁市| 西藏| 砀山县| 黎川县| 寿光市| 浦北县| 南安市| 中阳县| 高雄县| 永济市| 晋宁县| 德化县| 阜平县| 丁青县| 开原市| 枝江市| 德清县| 南华县| 婺源县| 灵石县| 石首市| 潞城市| 民县| 阜南县| 靖宇县| 光山县| 长乐市| 崇仁县| 增城市| 霍林郭勒市| 阿克苏市| 加查县| 桑日县| 顺平县| 湘西| 祁连县| 开阳县| 海宁市| 如皋市|