Group of Software Security In Progress

Understanding and Detecting Disordered Error Handling With Precise Function Pairing

作者:Qiushi Wu, Aditya Pakki, Navid Emamdoost, Stephen McCamant, and Kangjie Lu

单位:University of Minnesota

出处:Usenix Security 2021

原文:https://github.com/QiushiWu/QiushiWu.github.io/blob/main/papers/hero.pdf

Introduction

软件程序会遇到形如内存分配失败的错误,并会通过错误处理(Error Handling)的方法来处理。错误处理代码本身也会出现错误,进而导致安全问题。 在实际的错误处理中,程序一般会执行清理操作,例如释放内存或者减小引用计数。以下的处理模式可能会导致问题:

  • 以错误顺序进行清理操作
  • 重复的清理操作
  • 不完善的清理操作

针对上述问题,本文总结出一种关于错误处理代码的bug类别,并称之为Disordered Error Handling (DiEH). 在此基础上,作者实现了名为HERO(Handling ERrors Orderly)的DiEH自动化检测工具。 HERO基于error-handling的特殊结构,对标准和自定义的函数进行配对,以此来推测error-handling预期的清理函数。 利用HERO,作者在Linux Kernel,FreeBSD以及OpenSSL中总共发现了239个DiEH bug。

作者的贡献如下:

  • 首次对DiEH漏洞进行了定义并对其进行了深入调研。
  • 设计了一种精确的函数配对分析方法(Delta-based pairing)
  • 实现了一个有效的检测系统HERO,在流行的开源代码中发现了多个新问题

Background

Error Handling

-w683

Leader and followerfunctions

类似内存或者锁的资源是有限的。针对资源的操作,通常会有与之对应的操作来保证资源的平衡(例如内存申请与释放,锁的获取与释放)。

leader function:获取资源或者改变资源状态的函数 follower function: 恢复资源的函数

leader function与follower function构成一个function pair,例如:

  • allocation/deallocation
  • lock/unlock
  • refcount increase/decrease

上图的 v4l2_device_register/v4l2_device_unregister,video_device_alloc/video_device_release,video_register_device/video_unregister_device

Unique error-handling struct – EH stacks and deltas

follower function用来处理与之对应的leader function,行为与栈类似。 利用图1举例,增量delta是指,NP和EP在函数流程递进时分别新增的leader function和follower function。 作者利用EH stacks和delta来实现精确的函数配对。 -w715

Disordered Error Handling

作者认为,出现以下三种条件时,即发生了DiEH:

  1. 一个函数至少包含一处error path
  2. 函数内至少有一处leader function
  3. 在error path,相应的follower function以错误的顺序、重复或者缺失调用

更具体的,

  • EP表示函数一处error path
  • [LD]是EP中的leader function列表
  • [FL]表示EP中所有的follower function
  • [FL]’表示根据函数配对的先验知识,EP中期望的follower function -w344

-w504

Classification of DiEH bugs

  • Incorrect-order follower functions:
    • video_device_release和video_unregister_device的顺序搞反
  • Redundant follower functions
    • video_register_device出错时,video_unregister_device仍然会被调用
  • Inadequate follower functions
    • rga->src_mmu_pages等指针没有被释放

Causes of DiEH

  • follower function设计不合理,某些函数即使调用失败,也会使相应的refcount增加
  • 代码的复杂性以及清理操作之间的依赖,例如一个内存释放函数的参数是另一个函数参数的成员变量。
  • 定制化的follower function

作者手工检测了2019年100个内核的CVE,DiEH是其中22个的成因。前两年内核的patch,42%的memory leak和45%的double free都是由于DiEH造成的。

Design and Implementation

Challenges in Identifying DiEH

  • Analysis of error-handling structures
    • 如何去识别函数中的normal path和error path
    • 如何去识别normal path和error path的leader function和follower function
  • Function-pair identification
    • 根据作者的调研,内核中80%的follower function是定制的,类似k-meld的方法不太适用
  • Elimination of harmless DiEH cases
    • EH stack的路径会涉及路径约束(返回值相关),存在不可达路径
    • 针对顺序错误的EiDH,如果follower function是不相关,顺序是没有影响的。

HERO Techniques

-w1465

Understanding error-handling structures

作者首先对error check进行识别。通常的模式是if语句,检查返回错误码函数的返回值。 错误检查之前的代码可以认为是normal path。 在此基础上,作者将上述信息表示在error-handling graph(EHG)上

Pairing functions with EH deltas

作者的insight是,follower function会与leader function反序出现。对比两个相邻的EHS,可以得到EH delta,见Figure 2.

Detecting DiEH bugs with identified pairs

作者的检测流程是,先检测DiEH case,进一步过滤不可达路径以及无害路径,最终进行输出。 利用function pair信息,作者可以得到对应的[FL]’信息,并将其与[FL]进行对比。 作者实现了一种symbolic summary的方法,来过滤不可达路径。 为了过滤无害的EiDH,作者设计了follower-dependency reasoning的方法,来判断follower function之间的依赖关系

Workflow of HERO

  1. 将带检测代码编译为LLVM IR,并在此基础上生成call graph和 control flow graph
  2. 生成error-handling graph。识别error-handling struct,提取EH stack。
  3. 根据EH stack,计算delta,进行leader-follower配对

Details of HERO

Extracting Error-Handling Structures

  • Identifying error checks, normal and error paths
    • 作者收集了常见的error code以及常见的error-handling function
    • 当函数返回NULL或者错误码或者调用常见的出错处理函数(pr_err(), panic()),HERO认为该路径为EH
  • Filtering follower functions by removing noises
    • 类似kprintf,dev_err或者panic之类的函数。
  • Filtering leader functions through data dependency
    • leader function和对应的follower function会通过变量联系

Constructing EH stacks

EH stacks分为三部分,<ERROR, [LD], [FL]>. 为了避免路径爆炸,作者仅做过程内分析

-w981

Removing irrelevant functions in error paths

  1. error-logging function,类似dev_err
  2. exit function, 类似panic 具体的实现方式是构建特征然后模式匹配。针对exit函数,也要识别它们的封装函数。最终作者找到537个不相干函数

Evaluation

实验环境:

  • Intel Xeon CPU 48-cores
  • 256GB RAM
  • Ubuntu-18.04 OS
  • O2 LLVM IR

-w703 -w728

-w563 -w463