首页 > 系统相关 >Linux Kernel CFI机制简介及测试禁用

Linux Kernel CFI机制简介及测试禁用

时间:2024-07-28 19:10:45浏览次数:16  
标签:Kernel cfi int void CFI kCFI func Linux hello

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

环境说明

  无

前言


  当我们为android移植linux的驱动程序的时候,总会遇到一些错误,这些错误有一部分就是android 内核开启的安全的机制导致的。本文就会介绍一种内核的安全机制:Kernel Control Flow Integrity(kCFI)。

  此外,这里还要说明一下,Control Flow Integrity(CFI)与 Kernel Control Flow Integrity(kCFI)是不一样的,kCFI只检查函数指针,CFI还具备其他很多的检查,详情请参考:https://clang.llvm.org/docs/ControlFlowIntegrity.html





Kernel Control Flow Integrity(kCFI)原理简单介绍


  Control Flow Integrity的翻译是控制流完整性,从直译来看,其实就是用一些方法保证来保证我们的指令执行到正确的位置。我们从clang官方文档知道,kCFI只检查函数指针,那么其实kCFI就是保证函数指针跳转到正确的位置,并且返回到正确的位置。

  从这里来看,其实我们可以看到对于函数指针来说,我们需要保护两个地方:跳转到正确的位置、返回到正确的位置。这两个地方有两个专有名词:

  • forward-edge
  • backward-edge

  此外,我们还应该知道,在编写代码的时候,分为直接函数调用(direct function call),间接函数调用(indirect function call)。他们的示例如下:

void target(void)
{
    //... ...
}

typedef void(*fn)(void);
int main(int argc, char * argv[])
{
    // direct function call
    target();

    //indirect function call
    fn _id_fn = target;
    _id_fn();
} 

  从示例可以知道,indirect function call其实就是函数指针这种调用形式。

  此外,我们还要知道,如果我们想破坏代码的执行流,那么我们必须在可写、可读、可执行的内存里面写入shellcode,并跳转到这个shellcode,否则我们的代码是无法工作的。那么显而易见的事情是,通过函数指针来调用函数,我们的目标是明确的,因此我们可以校验这些目标的原型、地址等等信息。

  因为我们需要验证目标的原型、地址等等信息,所以,当我们在生成可执行文件的时候,需要知道所有的函数目标的信息,这个时候,就需要一个叫做Link Time Optimization(LTO)的功能,因为只有最终可执行文件链接时,才知道所有的函数目标信息。





kCFI演示示例


  首先在qemu中运行一个arm64的linux模拟器,然后为linux内核配置如下内核选项:

# General architecture-dependent options -> LTO
CONFIG_CFI_CLANG=y
CONFIG_CFI_PERMISSIVE=y

  我们的测试驱动例子:

#include <linux/module.h>  // 必须的头文件,定义了MODULE_*宏
#include <linux/kernel.h>  // 包含内核信息头文件
#include <linux/init.h>    // 包含 __init 和 __exit 宏

static int param_int = 0;
module_param(param_int, int, 0644);

static void hello_cfi_i(int i){
    printk(KERN_INFO "hello_cfi_i\n");
}
static void hello_cfi_f(float i){
    printk(KERN_INFO "hello_cfi_f\n");
}

typedef void (*hello_cfi_func_i)(int);
typedef void (*hello_cfi_func_f)(float);


struct node {
    hello_cfi_func_i i0[1];
    hello_cfi_func_f f0[1];
    hello_cfi_func_i i1[1];
    hello_cfi_func_f f1[1];
    hello_cfi_func_i i2[1];
    hello_cfi_func_f f2[1];
};
struct node fn_arr = {
    .i0 = {hello_cfi_i},
    .f0 = {hello_cfi_f},
    .i1 = {hello_cfi_i},
    .f1 = {hello_cfi_f},
    .i2 = {hello_cfi_i},
    .f2 = {hello_cfi_f},
};
// 模块初始化函数
static int __init hello_init(void)
{

    fn_arr.i0[param_int](param_int);

    printk(KERN_INFO "Hello, World!\n");
    return 0;  // 返回0表示加载成功
}

// 模块清理函数
static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye, World!\n");
}

// 注册模块初始化和清理函数
module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");  // 模块许可证
MODULE_AUTHOR("Your Name");  // 模块作者
MODULE_DESCRIPTION("A simple Hello World Module");  // 模块描述

  我们传入参数0,执行fn_arr.i0[0],测试正常跳转

rep_img

  我们传入参数1,执行fn_arr.i0[1],测试传入参数原型不匹配(本来应该调用hello_cfi_i,实际调用hello_cfi_f)

rep_img

  测试数组越界访问

rep_img




后记


  从上面来看,kCFI一般会对调用类型、调用的目标地址进行判断,更多细节,去看CFI的具体原理。

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

标签:Kernel,cfi,int,void,CFI,kCFI,func,Linux,hello
From: https://www.cnblogs.com/Iflyinsky/p/18328698

相关文章

  • 绝对实用Linux命令行下的文件夹逐层创建术,从小白到大神的必学技能
    哈喽,大家好,我是木头左!基础篇:初识Linux文件系统在深入了解如何在Linux中逐层创建文件夹之前,需要对Linux的文件系统有一个基本的认识。Linux文件系统以其树状结构而著称,其中/(根目录)是所有其他目录和文件的起点。每个分区、设备、目录都可以被挂载在这个树中的某个节点上。文件......
  • Linux文件权限管理
    1.文件权限位说明Linux文件或目录的基本权限位是由九个字符来控制的,每三位字符为一组。前三位是用户权限位中三位表示用户组权限位后三位表示其他用户权限位rwxr-xr-xuser(用户)group(用户组)others(其他用户)代表字符为u代表字符为g代表字符为o2.文件权限详细说明......
  • Linux常用打包压缩命令
    压缩命令应用场景tar大部分使用tar即可。创建,查看,解压,解压到指定目录gzip一般配合其他命令使用zip+unzip一般用于解压zip格式的压缩包1.tar打包压缩命令1.1命令详解【功能说明】在Linux系统里,tar是将多个文件打包在一起,并且可以实现解压打包的文件的命令。是系统管理......
  • Linux网络:传输层协议TCP(三)滑动窗口及流量控制
    目录一、关于滑动窗口在TCP中的应用1.1什么是滑动窗口,为什么要有滑动窗口1.2滑动窗口的实现1.3滑动窗口针对丢包重传的处理机制二、流量控制一、关于滑动窗口在TCP中的应用1.1什么是滑动窗口,为什么要有滑动窗口在上一篇博文中博主阐述了确认应答ACK策略,对每一个对......
  • Linux内核-异常输出调用栈CallTrace与Ftrace工具集
    1dump_stack函数打印内核调用堆栈。举个例子:我们定义四个函数aaa、bbb、ccc、ddd,然后bbb中调用aaa,ccc中调用bbb,ddd函数谁都不调用。在入口函数中,我们调用ccc与ddd函数,看看堆栈打印效果如何:#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#incl......
  • Blender 4.2 LTS (macOS, Linux, Windows) - 开源 3D 创意软件 (渲染 建模 雕刻)
    Blender4.2LTS(macOS,Linux,Windows)-开源3D创意软件(渲染建模雕刻)创造的自由Blender获得GNUGPL许可,由其贡献者拥有。因此,Blender永远是免费和开源软件。使命以免费/开源软件的形式将世界上最好的3DCG技术交到艺术家手中。想象每个人都应该自由地创......
  • Linux——CPU占不上去的解决办法
    一、将调节器升至performance:1.1查看当前的调节器:cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor如果不是performance,则进入root账户1.2进入root账户先进入管理员账户输入命令:suroot如果没有root账号,则参考博客:Linux系统下的root用户初始密码设......
  • Linux——手动清理内存缓存
    前言:使用free-m命令可以查看内存缓存。一、方法1.1先进管理员账户,然后进root账户1.2运行下面的命令:syncecho1>/proc/sys/vm/drop_caches#清空目录项缓存echo0>/proc/sys/vm/drop_caches#还原默认配置,这一步如果出错,则不用管sync二、小贴士......
  • linux服务器使用docker部署ES相关记录
    ES/可视化工具Kibana/ik分词器最好使用相同版本部署,实在找不到资源可基于ES版本,其余可向下兼容找最高版本docker创建网络因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:dockernetworkcreatees-netES配置文件夹数据卷挂载:需先复制config......
  • 【Linux应用编程】Day10_进程 一文详细剖析进程,从基本概念到创建再到进程操作直至消亡
    进程详细剖析进程,包括以下内容:⚫程序与进程基本概念;⚫程序的开始与结束;⚫进程的环境变量与虚拟地址空间;⚫进程ID;⚫fork()创建子进程;⚫进程的消亡与诞生;⚫僵尸进程与孤儿进程;⚫父进程监视子进程;⚫进程关系与进程的六种状态;⚫守护进程;⚫进程间通信概......