最近海思被爆的驱动代码的漏洞比较多,而且有几个可以用来root安卓设备,所以这两天投入了一下X版本的代码安全审计。结合自己之前分析的一些导致安卓root的CVE总结出了一些小技巧,记录一下。

不能一棒子打死说海思代码写的不好,因为有些模块参数校验做的还是相当不错,不过另有一些模块就根本没有考虑对用户入参的校验了,所以问题出在这里面。

另外一些开发人员,对像remap_pfn_range函数使用可能引发的安全问题认识不足,所以这里总结的都是一些值得开发或安全人员关注的点。

一、copy_from_user/copy_to_user

copy_from_user和copy_to_user涉及到用户态与内核态的数据交互,因此数据校验不足会导致比较严重的安全问题。举一个实际例子:

首先从华为官网下载荣耀6移动版的内核代码,地址是传送门,忍不住吐槽一句,有人说"华为用了linux内核的代码自己却不开源,大家快来看,他不要脸。"看看小米做的,其它厂商做的打脸了吧?

在source insight工程中打开,搜索关键字"copy_from_user"

先看一处没有问题的代码,

通过关键字定位到707行有一处copy_from_user调用,实现用户数据到内核内存的拷贝。要关注两个参数,一个是to地址大小,即这里的para_in,另一个是拷贝长度即usr_para_size

分析目的缓冲区para_in大小是否足够容纳usr_para_size大小的数据。

通过分析可以知道,para_in = kzalloc(para_size_in, GFP_KERNEL); ,申请空间大小为para_size_in大小,而para_size_in = usr_para_size + SIZE_CMD_ID; 因此这里不存在缓冲区溢出问题,这是一份校验做的比较好的代码示例。

我们再看一处漏洞代码,

hifi_misc是进行语音处理的模块,其中对应设备节点/dev/hifi_misc权限为system和audio,其内核入口如下

通过不同的cmd,进行不同的分支处理:

当cmd为HIFI_MISC_IOCTL_WRITE_PARAMS时,会调用hifi_dsp_write_param函数,将用户态传入的算法参数拷贝到内核空间:

继续跟踪hifi_dsp_write_para函数,发现其存在堆溢出漏洞:

int hifi_dsp_write_param(unsigned long arg)

{

...

if (copy_from_user(&para, (void*)arg, sizeof(struct misc_io_sync_param))) {  // -> arg to para

loge("copy_from_user fail.\n");

ret = ERROR;

goto error1;

}

...

hifi_param_vir_addr = (unsigned char*)ioremap(hifi_param_phy_addr, SIZE_PARAM_PRIV); // -> 分配堆内存,大小SIZE_PARAM_PRIV

if (NULL == hifi_param_vir_addr) {

loge("hifi_param_vir_addr ioremap fail\n");

ret = ERROR;

goto error2;

}

logd("hifi_param_vir_addr = 0x%x\n", (unsigned int)hifi_param_vir_addr);

logd("user addr = 0x%x, size = %d", (unsigned int)para.para_in, para.para_size_in);

ret = copy_from_user(hifi_param_vir_addr, para.para_in, para.para_size_in); // -> 未对para校验,堆溢出

...

}

漏洞PoC很简单,为para_in申请超过200*1024的内存传入即可,但前提是首先通过其它漏洞获得system或audio权限。

二、put_user/get_user

put_user实现了数据从内核到用户态的拷贝,与copy_to_user类似;get_usr相应的与copy_from_user类似,只不过put_usr/get_user常用于小数据量的拷贝,其效率更高。比如copy_from_user在拷贝4个字节的数据时,其内部其实调用的就是get_usr。

put_user ( x, ptr);

x

Value to copy to user space.

ptr

Destination address, in user space.

基于v6k和v7 ARM平台上的Linux kernel 3.5.4及之前的版本中的'get_user'和'put_user' API函数中存在安全漏洞,该漏洞源于程序没有验证目标地址ptr。攻击者可借助特制的应用程序利用该漏洞读取或修改任意内核内存位置的内容。

因此在未打补丁的相应安卓设备上,对get_user和put_user的调用都存在安全问题。下面代码,如果我们传入的para.para_out是一处内核代码,则会导致拒绝服务,精心构造可能导致任意代码执行,业界曾报过此类安卓root漏洞,可以参考CVE-2013-6282。

三、mmap

mmap可以实现将设备内存映射到用户空间,会使用到struct vm_area_struct结构体,当用户空间调用mmap时,系统通过创建一个表示该映射的VMA(虚拟内存区)作为响应。支撑mmap的驱动程序需要帮助进行完成VMA的初始化。

该结构中的重要成员:

unsigned long vm_start;

unsigned long vm_end;

该VMA所覆盖的虚拟地址范围。

struct file * vm_file;

指向与该区域相关联的file结构体指针。

unsigned long vm_pgoff;

以页为单位,文件中该区域的偏移量。当映射一个文件或设备时,它是该区域中被映射的第一页在文件中的位置。

unsigned long vm_flags;

描述该区域的一套标志。驱动程序最感兴趣的标志是VM_IO和VM_RESERVED。  VM_IO将VMA设置成一个内存映射IO区域。VM_IO会阻止系统将该区域包含在进程的核心转存中。VM_RESERVED告诉内存管理系统不要将该VMA交换出去;大多数设备映射中都设置该标志。

struct vm_operations_struct * vm_ops;

内核能调用的一套函数,用来对该内存区进行操作。它的存在表示内存区域是一个内核“对象”。

一个驱动程序只映射与其外围设备相关的一小段地址,而不是映射全部地址的例子。为了向用户空间只映射部分内存的需要,驱动程序只需要使用偏移量即可。下面的代码揭示了驱动程序如何对起始于物理地址simple_region_start(页对齐),大小为simple_region_size字节的区域进行映射的工作过程:

(注:“外围设备” 即是设备文件。 vm_pgoff; 为要映射区域在“外围设备”文件中的偏移量(以页为单位),“外围设备”文件即是指外围设备的一段内存。这个偏移量即使相对于这段内存开始的偏移量)

unsigned long off = vma->vm_pgoff <

unsigned long physical = simple_region_start + off; //计算相对于文件开始的偏移

unsigned long vsize = vma->vm_end - vma->vm_start; //要映射的区域大小

unsigned long psize = simple_region_size - off; //偏移之后文件的剩余空间

if (vsize > psize) //是否偏移之后文件的剩余空间不足以满足要映射的空间大小

return -EINVAL; /* 跨度过大*/

remap_pfn_range(vma, vma_>vm_start, physical, vsize, vma->vm_page_prot);

做代码审计时,需重点关注remap_pfn_range的两个参数physical和vsize,physical代表设备中映射的起始物理地址,而vsize表示映射的大小。这两个参数设置不当,会导致映射任意地址和大小内存,从而任意内存的读写。

仍通过一个例子看一下,

hifi_misc_mmap内核函数中,虽然phys_page_addr使用的是固定地址,但size却使用用户传入的vma->vm_end-vma->vm_start计算,由外部输入控制。因此可以实现对phys_page_addr之后任意设备内存的读写。

四、%pK

漏洞利用的一个重要步骤,就是获取一些敏感内核态内存地址,通常会通过Information Leak等漏洞获取。而代码中大量使用的%p为攻击者打开方便之门,对root漏洞来说,通过动态解析这些内核指针,可以实现通用root方案。

因此建议打印内核指针时,使用%pK加以保护,这块是个人理解。

支持linux的代码审计,linux驱动代码审计经验谈相关推荐

  1. 【Linux开发】linux设备驱动归纳总结(一):内核的相关基础概念

    linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  2. linux网卡驱动离线安装_新装Linux系统没有网卡驱动的解决办法和步骤

    刚安装的linux系统没有网卡驱动,下面给出我的解决方法: (机器系统是RHEL5.3) 首先说明几个命令: #lsmod --显示已载入系统的模块. 执行lsmod指令,会列出所有已载入系统的模块. ...

  3. linux open函数_Linux驱动开发 / 字符设备驱动内幕 (1)

    哈喽,我是老吴,继续记录我的学习心得. 一.保持专注的几个技巧 将最重要的事放在早上做. 待在无干扰环境下,比如图书馆. 意识到刚坐下开始投入工作前,有点负面小情绪是特别正常的现象. 让"开 ...

  4. kali linux查看网卡_CentOS7.6安装无线网卡驱动|Linux如何安装网卡驱动|Linux如何让配置网卡...

    此前提到,Thinkpad E490安装CentOS7.6遇到内核崩溃的问题,解决之后,安装CentOS7.6操作系统成功. 安装时发现,系统能够检测到有线网卡,但无法检测到无线网卡,说明CentOS ...

  5. Linux系统驱动全吗,linux系统需要给硬件安装驱动程序么?谁推荐一下linux系统阿~要驱动最全...

    需要,不过大部分linux都自带,少量的也都有自动安装文件 比如ati的显卡驱动什么的. 之前还自己写过驱动,linux的驱动比windows的驱动透明度高很多 大部分硬件基本上 都可以识别的 也可以 ...

  6. linux显卡驱动卸载和安装,Linux下Nvidia显卡驱动卸载和卸载后的问题

    Linux下Nvidia显卡驱动卸载和卸载后的问题 由于在Ubuntu下安装了Nvidia显卡驱动后开机一直处于循环登录界面,密码输入正确也是进不去,然后就决定卸载Nvidia显卡驱动. 首先是在能使 ...

  7. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之设备树模型

    文章目录 前言 1.设备树的作用 2.设备树的语法 2.1.设备树的逻辑图和dts文件.dtb文件 2.1.1.1Devicetree格式 1DTS文件的格式 node的格式 properties的格 ...

  8. Linux内核的Nand驱动流程分析

    最近在做Linux内核移植,总体的感觉是这样的,想要彻底的阅读Linux内核代码几乎是不可能的,至少这还不是嵌入式学期初期的重要任务.内核代码解压后有250M左右,据统计,有400多万行,而且涉及到了 ...

  9. linux 网卡驱动 优化,Linux多核环境网卡驱动优化研究①.PDF

    Linux多核环境网卡驱动优化研究①.PDF 2014 年 第 23 卷 第 10 期 计 算 机 系 统 应 用 Linux 多核环境网卡驱动优化研究① 姚萌萌, 张 俊, 沈 亮 (无锡江南计算技 ...

  10. Linux下的硬件驱动——USB设备(下)

    Linux下的硬件驱动--USB设备(下)(驱动开发部分) 文档选项 打印本页 将此页作为电子邮件发送 未显示需要 JavaScript 的文档选项 级别: 初级 赵明, 联想软件设计中心嵌入式研发处 ...

最新文章

  1. 华中科技大学计算机通信与网络实验,华中科技大学计算机通信与网络实验报告Socket编程实验.docx...
  2. 10x系列之Clay.io的服务发现
  3. 机器学习基础专题:逻辑回归
  4. 汇编语言程序开发过程
  5. 矩阵的特征向量和特征值
  6. 你真的会用Gson吗?Gson使用指南(三)
  7. ubuntu linux开机启动自动加载ko驱动程序_一文讲透 CentOS 开机流程
  8. 毁掉孩子自信的10个杀手
  9. 期末考试、考研、学技术
  10. 阿里十大最受开发者欢迎的工具!
  11. controller报错MissingServletRequestParameterException: Required xxx parameter ‘xxx’ is not present
  12. 计算机组成原理 论文总结,计算机组成原理论文
  13. 【线性代数】思维脑图
  14. IBM SPSS Statistics教程—文件的拆分和合并
  15. 破局人工智能:构建AI,与腾讯云一起探索语音应用场景
  16. 计算机一个小键盘按不出来怎么办,巧妙解决电脑键盘右边的数字键失灵问题
  17. 【C/C++】简单的程序小游戏-推箱子代码
  18. 80psi等于多少kpa_kpa与psi的换算(kpa与psi对照表)
  19. JSAPI微信支付开发流程和坑
  20. 转行程序员日记---2020-10-16【最近有点累】

热门文章

  1. codeforces1428F Fruit Sequences
  2. 黑客的滑铁卢——美国大断网全纪实
  3. 程序员应该学什么语言
  4. asp万年历简易版本
  5. ipv6测试工具-支持ipv6的web压力测试工具curl-load
  6. 阿里cdn请求原理以及缓存机制
  7. An exception has been thrown during the rendering of a template
  8. Java判断闰年和平年
  9. [2001年写的小说]星际争霸之外传
  10. gstarcad 2021|gstarcad pro2021(浩辰CAD) 64位附安装教程