内核并发消杀器(KCSAN)技术分析

news/2024/3/28 20:09:20/文章来源:https://blog.csdn.net/feelabclihu/article/details/129210940

一、KCSAN介绍

KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器,它依赖于编译时插装,并使用基于观察点的采样方法来检测竞态,其主要目的是检测数据竞争。

KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race)的工具,同时它也可以控制报告哪种类型的数据竞争。

KCSAN知道LKMM定义的所有标记原子操作,以及LKMM尚未提到的操作,例如原子位掩码操作(bit mask)。

KCSAN扩展了LKMM,例如通过提供data_race()标记,来表示存在数据竞争和缺乏原子可能性。

1.1 LKMM(Linux内核内存一致性模型)

Linux内核内存模型目前在源代码树中的memory-barrier.txt和atomic_ops.txt文件中有非正式的定义。包含以下组成部分:

  • 变量访问(Variable Access)

使用READ_ONCE()、WRITE_ONCE()和ACCESS_ONCE()宏来保护从共享(但非原子)变量的加载和存储;

  • 内存屏障(Memory Barriers)

一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作。比如barrier、smp_mb/smp_wmb/smp_rmb等;

  • 锁操作(Locking Operations)

  • 原子操作(Atomic Operations)

  • 控制依赖(Control Dependencies)

Linux内核提供了一个有限的控件依赖的概念,在某些情况下对依赖控件的存储进行优先加载;

  • RCU宽限期授权关系(Grace-Period Relationships)

允许更新者等待所有已经存在的读侧临界区完成,再回收旧的资源;

  • C11原子原语 (C11 Atomics)

将原子原语的实现委托给编译器;如果多个体系结构采用这种方法,将减少体系结构特定代码的数量。

1.2 数据竞争

为什么要关心数据竞争?

C语言的发展独立于并发性。如果给定的变量或访问没有任何特别之处,则变量只会在响应当前线程的存储时发生变化。

  • C语言和编译器的进化对并发性不敏感

  • 优化编译器正变得越来越丰富

因此,编译器可以并且使用各种优化,包括负载融合、代码重新排序和许多其他可能导致并发算法故障的优化。

读取拆分(单次访问多次读取)

存储拆分(单次访问多次写入)读取融合(编译器直接使用上一次对这个变量的load结果,而不是真正再去load一次)

存储融合(编译器优化写入变量流程,不再真实写入)

代码重排(把一些类似的计算归在一起,节省占用的寄存器,改善现代超标量微处理器里面各个运算单元的利用效率)

虚拟读取(编译器优化会导致多次读取,导致后续加载异常)

虚拟存储(编译器优化会导致多次存储,导致后续存储异常)

.....

因此需要告诉编译器并发代码,Linux提供内存一致性模型,也提供检查方法解决此类问题。

1.2.1 访问方式

  • 普通访问

  • 标记访问

2790912af748210feb93c91910abbedc.png

1.2.2 同步冲突访问的检测条件

  • 在访问同一个地方并且至少有一个是写操作

  • 至少有一个是普通访问(比如x+42)

以下线程打钩的是标准做法;打叉的是可能存在数据竞争的情况。

7a37e970f29116de275b1c75f61c7911.png

1.2.3 哪些不属于数据竞争

例如:使用不对称的锁机制,并且使用READ_ONCE/WRITE_ONCE标记访问。

9cb3ce9f157e732f367e30efd7703f05.png

二、依赖与配置方案

2.1 版本支持

KCSAN支持GCC/CLANG编译,需要GCC版本11,CLANG 12以上版本。

x86_64: >=5.8  ARM64: >=5.17

d98e2c063c31717b1ee5aec789ac5661.png

7ee359ed6cd1b25b009400a77f7b79b5.png

2.2 KCSAN工具链支持

cc-option,-fsanitize=thread --param tsan-distinguish-volatile=1

4121a19b890b29f92c197c8ab6273e97.png

2.3 配置选项支持

d2db6d3d00c41d69c16be6e51dea9cc3.png

三、工作原理与触发条件

3.1 使用方式

检查未标记读取是否写入竞争,会持续扫描内核的主要分支,在访问的内存位置上设置观察点,挑出导致数据争用的数据,并将其报告给内核日志。

●用“软观察点”查找竞争

〇设置观察点和失速通道;

〇如果监测点已经存在,那么竞争检查将照常进行;

〇如果值改变了--> 竞争;

〇失速通道随机延迟,增加观察竞争状态的机会;

默认值:任务[1,80]us,中断[1,20]us。

●为所有检测内存访问设置观察点

〇 注释标记访问,仅用于检查非标记访问是否存在观察点;

KCSAN从不在标记的访问上设置观察点;

如果对并发访问的变量的所有访问都正确地标记了,KCSAN将永远不会触发观察点,因此永远不会报告访问。

●采样: 周期性建立观察点

〇默认值:平均2000次访问。

3.2 KCSAN软观测点

基于地址页索引

〇可以溢出到相邻槽。

〇使用索引确保报告元数据给匹配的生产者/消费者。

具有灵活、可缩放的特点,以数组的形式存放。

12297e0eed5ecb25eaca420e5a01504e.png

代码片段如下:

入口函数check_access,在check_access数据地址、长度、类型;在check_access函数执行find_watchpoint判断。需要检测的ptr已经插桩编译。

36fa9ffbd54e29b72aab0f2dd697b725.png

3.3 KCSAN 运行流程

  1. 进入check_access函数,格式描述包含数据指针、长度、读写类型;

  2. 确认是否需要观测,需要满足至少一个写操作且为普通访问;

  3. 如果判定需要观测,加入观察列表;

  4. 延时一段时长,查看是否有访问、变更数据等情况;如果有,则生产数据表,并打印数据到控制台;如果没有则退出;

  5. 在步骤3,如果未发现合适的观测点,则该数据运行流程退出

ae519daa5e5d1c91fd834f009bd0466f.png

3.4 ASSERT检测机制

KCSAN提供有一种断言检测机制,检查在数据竞争模型以外的情况下提供竞争检测;

22fee62609ed412cccf55ffbc5d9d9e5.png

599d2a762be5af7eb1a1067ac3bf484a.png

3.4.1 ASSERT集合

29a9bd09848578d3f8ac353e4042fc0a.png

3.5 KCSAN特点

79595087b38558dd81e6109cabb31a7a.png

四、测试套件

4.1 KUNIT测试模型

KCSAN提供KUNIT的支持

  1. 创建多个access_thread线程用于测试用例函数的调用接口;

  2. 挂接console跟踪点,该跟踪点监控串口输出数据;如果有数据竞争报错,可以捕获并判断;

  3. 启动测试用例接口函数,实现测试函数的挂接并提供超时判定(缺省执行500毫秒);

  4. 在执行超时以后,判断输出是否与预想一致;并给出判断结果。

f3e919f1d5359bca73e431f397743b4f.png

4.2 测试条件

1. 配置CONFIG_KCSAN_KUNIT_TEST=y使能KUNIT

2. KCSAN功能正常开启

4.3 测试环境

QEMU Linux 6.11 core 4 GCC11

测试覆盖:

1. 不同条件下的数据竞争data_race

de9cc624f01b45529d57c30801c7cd08.png

2.断言函数数据竞争assert_exclusive_x

e4c8f29a580e3f2beb21c57e13fa951e.png

3. barrier/lock判定

008bc3d9c37aff8e84fbb7039a0fa7b2.png

五、过程与案例分析

5.1 KCSAN启动过程

1. 在完成KCSAN配置后,系统启动时有“kcsan:enable early”打印:

f4b4e644061749a9d07f6ba11ecd8001.png

2.后台会实时进行观测点的监控与比对,如果比中会有”BUG:KCSAN”控制台打印来描述数据竞争的信息;这些信息包括调用函数、数据竞争地址、CPU号、进程号等;可在不同的测试场景进行压力测试;

c3efef7f042faf1036dbd335dbabab8c.png

3.在运行过程中,查看“KCSAN kernel debug”节点查看当前的状态,这些状态信息包括观测点、数据竞争、ASSERT报错等一系列信息;

ae686250ae82e0c8463622671916fd52.png

5.2 案例一

描述:IGMP协议timer超时与事件函数在读写mr_ifc_count变量的数据竞争

net: igmp: fix data-race in igmp_ifc_timer_expire()

8523c4aae073ffb066896db29380e075.png

解决办法:

1.  igmp_ifc_event/ igmp_ifc_timer_expire函数在读写mr_ifc_count变量存在数据竞争,需要使用LLKM 访问保护;

2. 修改调用mr_ifc_count点,使用READ_ONCE/WRITE_ONCE保证编译器的一致性;

3. mr_ifc_count和in_dev->mr_ifc_count值不等时启动重传机制;

67e5d08b6314aea0525cea125071b8a3.png

5.3 案例二

描述:在taskstats_exit()中分配和测试任务统计时,会有一个竞争在读写sig->stats

When assiging and testing taskstats in taskstats_exit() there's a race when writing and reading sig->stats

1327be744b70b96872c13ff95fc08bcc.png

解决办法:

1. 结构体成员sig->stats存在数据竞争,需要使用LLKM访问保护;

2. smp_load_acquire/smp_store_release函数解决CPU数据同步和编译器同步问题,适用于同一个函数内部的数据竞争;

48b113a7ad6528afa0734d3b3bf73747.png

六、总结

本文从工作原理、运行流程、测试方式等多个方面介绍了KCSAN,旨在让读者能够对KCSAN运行有一个直观的认识,利用KCSAN在产品中解决一些数据竞争问题;数据竞争是一个复杂问题,用KCSAN能帮助大家快速找到数据竞争问题,进而寻找方法解决或规避,本文更多传递是一种发现和解决此类问题的思路。

消杀器技术在不断地迭代和更新,也让大家多一份探寻世界、改变世界的机会;借此机会,站在巨人的肩膀上,让大家看得更远、走得更远,愿大家都有一个美好的明天。

七、参考文档

更多案例分享:

https://github.com/google/kernel-sanitizers/blob/master/kcsan/FOUND_BUGS.md

LKMM:

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0124r2.html

KCSAN ASSERT:

https://www.kernel.org/doc/html/next/dev-tools/kcsan.html#c.ASSERT_EXCLUSIVE_ACCESS

KUNIT测试框架

https://kunit.dev/third_party/kernel/docs/api/test.html?highlight=kunit_expect_false

测试使用内核源码地址

https://kernel.source.codeaurora.cn/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.1.1&id=ebdb69c5b054f115ef5ff72f0bb2aaa1718904e6

0da0327291e008068485379c2c87bded.gif

长按关注内核工匠微信

Linux内核黑科技| 技术文章 | 精选教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73978.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络原理8】HTTP请求篇

在上一篇文章当中,我们也提到了什么是HTTP。 每一个HTTP请求,都会对应一个HTTP响应。 下面这一篇文章,将聊一下HTTP请求的一些内容 目录 一、URL 第一部分:协议名称 第二部分:认证信息(新的版本已经没有了) 第三部分&#xf…

【数通网络交换基础梳理1】二层交换机、以太网帧、MAC地址详解及数据帧转发原理(爆炸细)

一、网络模型 万年不变,先从模型结构分析,现在大家熟知的网络模型有两种。第一种是,OSI七层模型,第二种是TCP/IP模型。在实际运用中,参考更多的是TCP/IP模型。 OSI七层模型 TCP/IP模型 不需要全部理解,…

Spring MVC 源码- HandlerExceptionResolver 组件

HandlerExceptionResolver 组件HandlerExceptionResolver 组件,处理器异常解析器,将处理器( handler )执行时发生的异常(也就是处理请求,执行方法的过程中)解析(转换)成对…

Python变量的定义和使用

定义:变量就是计算机内存中存储某些数据的位置的名称 形象理解变量就是一个存放东西的容器,该容器的名字就叫做变量,容器存放的东西就是变量的值 变量的组成: 标识:标识对象所储存的内存地址,使用内置函数i…

六千字让你明白什么是数字孪生?

文章目录1. 背景2. 数字孪生基础2.1 概念2.2 价值3. 技术生态3.1 技术体系3.2 核心技术3.2.1 多领域、多尺度融合建模3.2.2 数据驱动与物理模型融合的状态评估3.2.3 数据采集和传输3.2.4 全生命周期数据管理3.2.5 虚拟现实呈现3.2.6 高性能计算3.3 建设3.3.1 重点3.3.1.1 数字孪…

SEATA是什么?它的四种分布式事务模式

一、SEATA是什么? Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。 在继续学习使用SEATA之前,对s…

数据结构栈的经典OJ题【leetcode最小栈问题大剖析】【leetcode有效的括号问题大剖析】

目录 0.前言 1.最小栈 1.1 原题展示 1.2 思路分析 1.2.1 场景引入 1.2.2 思路 1.3 代码实现 1.3.1 最小栈的删除 1.3.2 最小栈的插入 1.3.3 获取栈顶元素 1.3.4 获取当前栈的最小值 2. 有效的括号 0.前言 本篇博客已经把两个关于栈的OJ题分块,可以根据目…

【华为OD机试模拟题】用 C++ 实现 - 分糖果(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

Jina 3.14 版本发布!支持独立部署Executor

Jina 是一个 MLOps 框架,赋能开发者在云上构建多模态、跨模态的应用程序。Jina 能够将 PoC 提升为生产就绪服务。基础设施的复杂性交给 Jina,开发者能够直接轻松使用高级解决方案和云原生技术。🌟 GitHubhttps://github.com/jina-ai/jina/rel…

基于博客系统的测试用例

登陆界面博客预览页博客详情页博客编辑页

【华为OD机试模拟题】用 C++ 实现 - 时间格式化(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

MATLAB绘制雷达图/蜘蛛图

雷达图/蜘蛛图 1 方法一 函数来源为MATLAB | 如何使用MATLAB绘制雷达图(蜘蛛图) 1.1 调用函数 1.2 案例 2 方法二 函数来源为MATLAB帮助-spider_plot 2.1 调用函数 语法(Syntax): spider_plot(P)spider_plot(P, Name, Value, ...)h …

内网穿透常用方法系列总结

前言在内网渗透时,一个WebShell或CobaltStrike、Metasploit上线等,只是开端,更多是要内网横向移动,扩大战果,打到核心区域。但后渗透的前提是需要搭建一条通向内网的“专属通道”,才能进一步攻击。可实战中…

中国ETC行业市场规模及未来发展趋势

中国ETC行业市场规模及未来发展趋势编辑根据市场调研在线网发布的2023-2029年中国ETC行业发展策略分析及战略咨询研究报告分析:随着政府坚持实施绿色出行政策,ETC行业也受到了极大的支持。根据中国智能交通协会统计,2017年中国ETC行业市场规模…

高端装备的AC主轴头结构

加工机器人的AC主轴头和位置相关动力学特性1. 位置依赖动态特性及其复杂性2. AC主轴头2.1 常见主轴头摆角结构2.2 摆动机构3. 加装AC主轴头的作用和局限性4. 切削机器人的减速器类型5. 其他并联结构形式参考文献资料1. 位置依赖动态特性及其复杂性 However, FRF measurements …

【华为OD机试模拟题】用 C++ 实现 - 求解连续数列(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

【异常】导出Excel异常This archive contains unclosed entries.

一、异常说明 二、定位问题代码 一看问题, 上下文都是与订单相关的内容。 查询代码的使用地方,发现出现在这个Mybatis的select语句中 查看备注,发现是订单物流,那就没跑了, 肯定是商城的物流模块出了问题 那是什么地…

Gin获取Response Body引发的OOM

有轮子尽量用轮子 😭 😭 😭 😭 😭 😭 我们在开发中基于Gin开发了一个Api网关,但上线后发现内存会在短时间内暴涨,然后被OOM kill掉。具体内存走势如下图: 放大其中一次 在…

软件测试之测试模型

软件测试的发展 1960年代是调试时期(测试即调试) 1960年 - 1978年 论证时期(软件测试是验证软件是正确的)和 1979年 - 1982年 破坏性测试时期(为了发现错误而执行程序的过程) 1983年起,软件测…