返回顶部
首页 > 资讯 > 移动开发 >AndroidNativefdsan检测工具介绍
  • 782
分享到

AndroidNativefdsan检测工具介绍

AndroidNativefdsan检测工具AndroidNative 2023-02-10 12:02:31 782人浏览 泡泡鱼
摘要

目录正文一个fd由生到死的所有者tag组成tag的创建和检验过程正文 本文分析基于Android T(13) fdsan,全名为file descriptor sanitizer,

正文

本文分析基于Android T(13)

fdsan,全名为file descriptor sanitizer,是Android中的一种检测工具,用于检测fd的use-after-close和double-close错误。这两个错误会给设备留下安全漏洞,甚至造成数据泄露等安全问题。然而现实情况是这两种错误非常隐蔽,且难以排查。这才催生了fdsan的诞生。

fdsan由Google的工程师Josh Gao开发。最初在Android 10中引入,检测到错误时会打印log并继续运行。Android 11更改了运行模式,一旦检测到错误就立即abort,让问题暴露得更加醒目。

要让这些问题可以被检测,关键是要构建fd的所有权体系。

这套体系的建立有两个重要前提:

  • Android中大多数fd并非直接通过open/close的原生接口进行管理,而是通过unique_fd,FileOutputStream,ParcelFileDescriptor之类的封装形式。
  • fd是一个整数,且每个进程所能创建的fd都有上限,早期为1024,现在为32768。因此即便为每个fd创建单独的所有权管理数据也不会消耗多少空间。

一个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 {
  
  ANDROID_FDSAN_OWNER_TYPE_GENERIC_00 = 0,
  ANDROID_FDSAN_OWNER_TYPE_GENERIC_FF = 255,
  
  ANDROID_FDSAN_OWNER_TYPE_FILE = 1,
  
  ANDROID_FDSAN_OWNER_TYPE_DIR = 2,
  
  ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD = 3,
  
  ANDROID_FDSAN_OWNER_TYPE_sqlITE = 4,
  
  ANDROID_FDSAN_OWNER_TYPE_FILEINPUTSTREAM = 5,
  
  ANDROID_FDSAN_OWNER_TYPE_FILEOUTPUTSTREAM = 6,
  
  ANDROID_FDSAN_OWNER_TYPE_RANDOMacCESSFILE = 7,
  
  ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
  
  ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE = 9,
  
  ANDROID_FDSAN_OWNER_TYPE_DATAGRAMSocketIMPL = 10,
  
  ANDROID_FDSAN_OWNER_TYPE_SOCKETIMPL = 11,
  
  ANDROID_FDSAN_OWNER_TYPE_ZIPARCHive = 12,
};

tag中的value主要用作唯一性标识。对于native层的封装(譬如unique_fd)而言,value为封装对象的指针值;对于Java层的封装(譬如FileInputStream)而言,value为封装对象的hash code。这两种值在同一个进程里都具有唯一性。

tag的创建和检验过程

了解完tag的构成后,接下来便是tag的创建和检验过程。

通过封装对象创建相应fd时(通常在对象的构造函数内),tag便会创建。而所有的close都会去进行tag检验,不论该close是通过封装对象的析构调用还是直接调用。举个例子,当一个fd通过FileInputStream创建时,对象回收期间便会close fd。可是如果我们不小心将此fd传到了JNI函数中,通过close函数直接去操作它,那么检测时我们就会发现:期望的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创建数量较少的进程,便可以使用较小的table来节省内存。

fdsan自引入之际便全局打开,对于保障系统的安全至关重要。但受限于它的原理,仍然有一些fd的use-after-close和double-close错误无法被检出。它们是:

  • 不使用任何封装形式,而只是通过open和close来操作fd。这样即便对同一个fd double-close,由于期望的tag和实际的tag都为0,因此错误无法检出。
  • 使用自定义的封装形式来操作fd,而没有在自定义的形式中接入fdsan。无法检出的理由同上。
  • 单纯的use-after-close,而并非由double-close引发的use-after-close也无法检出。严格意义上来说,我认为这个工具只能检出fd的double-close。原因是检测代码只插入在close函数里,对于fd的其他操作并无检测。

除了检测fd的错误外,存在全局table中的tag数据在生成tombstone时也会输出,表示每个fd的ownership。unowned表明该fd的创建未接入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检测工具的资料请关注编程网其它相关文章!

--结束END--

本文标题: AndroidNativefdsan检测工具介绍

本文链接: https://lsjlt.com/news/195476.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • AndroidNativefdsan检测工具介绍
    目录正文一个fd由生到死的所有者tag组成tag的创建和检验过程正文 本文分析基于Android T(13) fdsan,全名为file descriptor sanitizer,...
    99+
    2023-02-10
    Android Native fdsan检测工具 Android Native
  • 介绍几款 Python 类型检查工具
    近日,微软在 Github 上开源了一个 Python 静态类型检查工具:pyright ,引起了社区内的多方关注。 微软在开源项目上的参与力度是越来越大了,不说收购 Github 这种大的战略野心,只说它家开源的 VS Code 编辑...
    99+
    2023-01-31
    几款 类型 工具
  • 官方压测工具mysqlslap介绍及使用
    mysqlslap是官方的一款做压力测试的工具,可以模拟多个客户端进行并发测试。 比如可以模拟多少并发,执行多少次,针对某个存储引擎……等等 比如对myisam引擎做并发量为100,查询次数为1000...
    99+
    2024-04-02
  • Pytest测试报告工具Allure用法介绍
    简介 Allure Framework是一种灵活的、轻量级、多语言测试报告工具。 不仅可以以简洁的网络报告形式非常简洁地显示已测试的内容, 而且还允许参与开发过程的每个人从日常执行中...
    99+
    2024-04-02
  • cypress测试工具特点及使用介绍
    目录cypress测试工具一、什么是cypress二、cypress独有特点其他亮点cypress测试工具 cypress现在可谓是越来越火爆了,github上已经30.2K sta...
    99+
    2024-04-02
  • Network Stumbler和NetIQChariot带宽测试工具介绍
    Network Stumbler是一个无线网络扫描工具,主要用于扫描和识别附近的无线网络。它可以显示附近的无线网络名称(SSID)、...
    99+
    2023-09-09
    NetIQChariot
  • win11检测工具在哪
    目前,微软官方还没有发布Windows 11检测工具。但是,你可以通过以下方法检测你的设备是否满足Windows 11的最低系统要求...
    99+
    2023-08-31
    win11
  • mysql中自带压力测试工具mysqlslap介绍
    下面一起来了解下mysql中自带压力测试工具mysqlslap介绍,相信大家看完肯定会受益匪浅,文字在精不在多,希望mysql中自带压力测试工具mysqlslap这篇短内容是你想要的。测试示例1查询300次...
    99+
    2024-04-02
  • pt(Percona Toolkit)工具介绍
           pt(Percona Toolkit)工具介绍一.介绍1.找出重复的索引和外键    pt-duplicate-key-c...
    99+
    2024-04-02
  • MySQL 5.7 mysqldumpslow工具介绍
    mysqldumpslow工具可以用来归纳总结慢查询日志的信息。 MySQL慢查询日志包含执行时间较长的查询信息。mysqldumpslow工具可以解析MySQL慢查询日志文件并打印出他们内容的汇总信息...
    99+
    2024-04-02
  • mydumper工具使用介绍
    背景:mysqldump mysqlpump mydumper 三种逻辑备份工具的比较 mysqlpump的介绍(转):http://www.cnblogs.com/zhoujinyi/p/5684903...
    99+
    2024-04-02
  • Java工具集介绍12_09
    Java工具集介绍12_091)Java 6 for MacOSX版本发布如果你是一个Mac用户,现在就值得高兴了,开源社区刚刚解决了这个问题,把Java 6移植到苹果的系统中。2)UMLGraph新版本:UMLGraph 5.0UMLGr...
    99+
    2023-06-03
  • SSL检测工具有哪些
    常见的SSL检测工具包括:1. SSL Checker:可以检测SSL证书的有效性和安全性,支持多种协议和加密方式。2. SSL L...
    99+
    2023-06-05
    SSL检测 SSL
  • oracle管理工具的介绍
    oracle管理工具的介绍(1)===================================================================sql*plus是oracle自带的工具...
    99+
    2024-04-02
  • java的Guava工具包介绍
    集合 普通集合 List<String> list = Lists.newArrayList(); Set<String> set = Sets.newH...
    99+
    2024-04-02
  • python实用小工具介绍
    一、秒级启动一个HTTP下载服务器在实际工作中,时不时会有这样的一个需求:将文件传给其他同事。将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输。但是,如果需要传送的文件较多,那么,操作起来就会比较麻烦。此外,如果文...
    99+
    2023-01-31
    小工具 python
  • 内存检测工具有哪些
    常见的内存检测工具有:1.Memtest86,系统检测软件;2.鲁大师,专业的硬件检测工具;3.RAMExpert,内存数据型号检测工具;4.MemTest,内存检测工具;5.CPU-Z,CPU检测软件;常见的内存检测工具有以下几种:Mem...
    99+
    2024-04-02
  • 一款强大的端到端测试工具Playwright介绍
    目录Playwright跨浏览器支持多编程语言保存登录信息执行环境的隔离测试框架Playwright Playwright 是微软公司开源的一款 UI 自动化测试工具,它的第一个版...
    99+
    2023-01-29
    端到端测试工具Playwright 端到端测试
  • Linux下常用的3种网络测速工具介绍
    本篇内容介绍了“Linux下常用的3种网络测速工具介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!fastfast 是 Netflix 提...
    99+
    2023-06-01
  • appium测试之APP元素定位及基本工具介绍
    添加配置 这里跟我们之前所说的appium测试工具的配置差不多。 deviceName:设备名称 platformName:测试平台 platformVersion:平台版本 app...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作