我的编程空间,编程开发者的网络收藏夹
学习永远不晚

AndroidNativefdsan检测工具介绍

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

AndroidNativefdsan检测工具介绍

正文

本文分析基于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检测工具的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

AndroidNativefdsan检测工具介绍

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

AndroidNativefdsan检测工具介绍

这篇文章主要为大家介绍了AndroidNativefdsan检测工具介绍,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-10

介绍几款 Python 类型检查工具

近日,微软在 Github 上开源了一个 Python 静态类型检查工具:pyright ,引起了社区内的多方关注。微软在开源项目上的参与力度是越来越大了,不说收购 Github 这种大的战略野心,只说它家开源的 VS Code 编辑器,在
2023-01-31

Network Stumbler和NetIQChariot带宽测试工具介绍

Network Stumbler是一个无线网络扫描工具,主要用于扫描和识别附近的无线网络。它可以显示附近的无线网络名称(SSID)、信号强度、加密类型等信息,帮助用户找到并连接到合适的无线网络。NetIQChariot是一个用于测试网络性能
2023-09-09

win11检测工具在哪

目前,微软官方还没有发布Windows 11检测工具。但是,你可以通过以下方法检测你的设备是否满足Windows 11的最低系统要求:1. 访问微软的官方网站(https://www.microsoft.com/zh-cn/windows/
2023-08-31

Java工具集介绍12_09

Java工具集介绍12_091)Java 6 for MacOSX版本发布如果你是一个Mac用户,现在就值得高兴了,开源社区刚刚解决了这个问题,把Java 6移植到苹果的系统中。2)UMLGraph新版本:UMLGraph 5.0UMLGr
2023-06-03

SSL检测工具有哪些

常见的SSL检测工具包括:1. SSL Checker:可以检测SSL证书的有效性和安全性,支持多种协议和加密方式。2. SSL Labs:由Qualys提供的在线工具,可以评估网站的SSL配置和安全性,并提供详细的报告和建议。3. Dig
2023-06-05

Linux下常用的3种网络测速工具介绍

本篇内容介绍了“Linux下常用的3种网络测速工具介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!fastfast 是 Netflix 提
2023-06-01

一款强大的端到端测试工具Playwright介绍

这篇文章主要为大家介绍了一款强大的端到端测试工具Playwright介绍,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-29

python实用小工具介绍

一、秒级启动一个HTTP下载服务器在实际工作中,时不时会有这样的一个需求:将文件传给其他同事。将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输。但是,如果需要传送的文件较多,那么,操作起来就会比较麻烦。此外,如果文
2023-01-31

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录