ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

FreeRTOS CBMC 内存安全证明解析:以 xTaskGetTickCount 形式化验证为例

FreeRTOS CBMC 内存安全证明解析:以 xTaskGetTickCount 形式化验证为例 FreeRTOS CBMC 内存安全证明解析以 xTaskGetTickCount 形式化验证为例【免费下载链接】FreeRTOSClassic FreeRTOS distribution. Started as Git clone of FreeRTOS SourceForge SVN repo. Submodules the kernel.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeRTOS导读本文基于 FreeRTOS 官方 CBMCC Bounded Model Checker有界模型检查器验证套件中TaskGetTickCount证明的配套文档及其 harness、构建配置系统讲解 FreeRTOS 是如何对内核 API本案例为xTaskGetTickCount进行内存安全memory safety形式化验证的。读完本文你将掌握CBMC 证明目录的标准文件布局、harness验证入口的编写范式、Makefile.json构建配置中每个字段ENTRY、CBMCFLAGS、OBJS的含义、cbmc-viewer.json中预期缺失函数清单的作用以及单线程计算下无需假设与抽象这一结论背后的验证原理。一、证明对象与文档定位本案例的关联文档位于 FreeRTOS/Test/CBMC/proofs/Task/TaskGetTickCount/README.md全文仅五句但信息密度很高核心陈述有三条本证明proof用于演示TaskIncrementTick函数的内存安全对于单线程计算该证明既不需要假设assumptions也不需要抽象abstractions本证明仍处于进行中work-in-progress状态证明假设以 harness 为准。需要特别指出的是README 的文字表述TaskIncrementTick与目录命名、harness 实际调用之间并不完全一致。从该证明目录下的源码与构建配置看实际被验证的对象是任务 APIxTaskGetTickCountharness 中直接调用了xTaskGetTickCount()而 Makefile.json 中的ENTRY字段也命名为TaskGetTickCount。从源码结构看README 首句的表述更接近沿用了相邻证明TaskIncrementTick的模板阅读时应以 harness 与实际构建配置为准。xTaskGetTickCount是 FreeRTOS 任务控制 API 家族中的一员其语义是从内核返回当前系统 tick 计数值即内核全局 tick 变量当前快照。在本仓库中内核源码以 submodule 形式挂载FreeRTOS/Source目录CBMC 证明则通过 Makefile.json 中的OBJS字段引用编译产物$(FREERTOS)/Source/tasks.goto来完成对真实内核代码的链接验证——这正是该证明验证的是真实实现而非桩代码的关键所在。二、验证套件全景Task 系列证明TaskGetTickCount证明只是 FreeRTOS CBMC 验证体系的一环。在 FreeRTOS/Test/CBMC/proofs/Task 目录下与它并列的还有 14 个针对任务子系统核心函数的证明TaskCheckForTimeOut校验任务超时检查逻辑TaskCreate/TaskDelete任务创建与删除路径TaskDelay延时 API 验证TaskGetCurrentTaskHandle获取当前任务句柄TaskGetSchedulerState调度器状态查询TaskGetTaskNumber任务编号读取TaskIncrementTicktick 递增逻辑TaskPrioritySet优先级设置TaskResumeAll/TaskSuspendAll调度器挂起/恢复TaskSetTimeOutState超时状态初始化TaskStartScheduler调度器启动TaskSwitchContext上下文切换。每个证明目录都遵循完全一致的四文件布局README.md证明说明、ProofName_harness.c验证 harness、Makefile.json构建与链接配置、cbmc-viewer.json结果查看与缺失函数清单。多数证明还会附带tasks_test_access_functions.h测试访问头文件。这种高度模板化的组织方式意味着理解其中一个证明的结构即可快速迁移到其他证明。三、深入解析验证 harnessharness验证入口是 CBMC 证明的核心它定义了以何种初始状态、调用哪条被验证路径。TaskGetTickCount的完整 harness 位于 TaskGetTickCount_harness.c除去许可证注释后验证逻辑仅十数行#include stdint.h /* FreeRTOS includes. */ #include FreeRTOS.h #include task.h void harness() { TickType_t xTickCount; xTickCount xTaskGetTickCount(); }逐行拆解void harness()CBMC 验证套件约定以harness作为证明入口函数替代传统main。构建时该函数与编译为 goto 程序的内核目标文件tasks.goto链接CBMC 从harness开始执行符号执行#include FreeRTOS.h与#include task.h引入内核配置宏与任务 API 声明。TickType_t的具体位宽16 位或 32 位由FreeRTOSConfig.h中的configUSE_16_BIT_TICKS决定这正是证明针对真实配置而非固定类型宽度的体现xTickCount xTaskGetTickCount();以最直白的方式调用目标 API 并捕获返回值。局部变量xTickCount用于承接返回值保证 CBMC 的符号执行覆盖到函数返回路径。该 harness 没有添加任何__CPROVER_assume前置约束也没有为调用环境搭建抽象模型——这与 README 中单线程计算无需假设或抽象的陈述完全吻合。由于xTaskGetTickCount的语义仅是读取内核全局 tick 计数并返回其调用路径不涉及链表遍历、不依赖堆分配、不触发上下文切换因此在单线程、展开深度为 1 的约束下CBMC 可以穷尽验证该函数对所有可能全局状态的访问都是内存安全的。四、构建配置 Makefile.json 逐字段解读Makefile.json 是整个证明的构建蓝图它被 CBMC 套件的构建脚本解析后生成实际的证明构建目标。其内容如下{ ENTRY: TaskGetTickCount, CBMCFLAGS: [ --unwind 1 ], OBJS: [ $(ENTRY)_harness.goto, $(FREERTOS)/Source/tasks.goto ] }三个字段分别承担不同职责字段取值作用ENTRYTaskGetTickCount证明名称同时约定 harness 函数名TaskGetTickCount_harness与生成产物命名TaskGetTickCount_harness.gotoCBMCFLAGS--unwind 1传给 CBMC 的验证选项指示循环展开深度为 1。对xTaskGetTickCount这类无循环、无递归的纯读取函数展开 1 次即可覆盖全部执行路径这也是单线程无需抽象能成立的计算前提OBJS$(ENTRY)_harness.goto与$(FREERTOS)/Source/tasks.goto链接进证明的两份 goto 程序前者是 harness 本身后者是把FreeRTOS/Source/tasks.c编译成的 goto 中间表示。正是这一行保证了验证面向的是内核真实实现而非手工编写的等价模型。$(ENTRY)与$(FREERTOS)属于套件内建的变量替换$(ENTRY)展开为TaskGetTickCount$(FREERTOS)指向内核源码根目录。goto 程序是 CBMC 工具链的中间表示形式由 C 源码经goto-cc转换而来后续的符号执行、有界模型检查都在该表示上进行。五、cbmc-viewer.json 与预期缺失函数清单cbmc-viewer.json 承担两个职责一是声明证明名称与证明根目录proof-name: TaskGetTickCount、proof-root: Test/CBMC/proofs供查看器工具定位结果二是通过expected-missing-functions字段列出验证过程中允许缺失不提供定义的函数符号。清单中出现了两类函数与硬件移植/运行时环境相关的函数pxPortInitialiseStack、vPortCloseRunningThread、vPortDeleteThread、vPortEnterCritical、vPortExitCritical、vPortGenerateSimulatedInterrupt、xPortStartScheduler、vApplicationTickHook。这些是端口层port layer或用户钩子函数在纯内存安全验证中不提供实现仅以符号形式存在tasks.c 内部但不在本调用路径上的函数pvTaskIncrementMutexHeldCount、uxTaskGetTaskNumber、vTaskInternalSetTimeOutState、vTaskMissedYield、vTaskPlaceOnEventList、vTaskPriorityDisinheritAfterTimeout、vTaskSuspendAll、xTaskGetCurrentTaskHandle、xTaskPriorityDisinherit、xTaskPriorityInherit、xTaskRemoveFromEventList、xTaskResumeAll。它们虽然定义在tasks.c中但xTaskGetTickCount的执行路径不会触及因此以缺失但预期的方式登记避免链接器报错同时向读者明确标注本证明的验证范围就是读取全局 tick 变量并返回这一最小调用路径。这份清单本身就是对xTaskGetTickCount调用图的一个侧面证明它不进入临界区vPortEnterCritical/vPortExitCritical缺失、不操作事件链表vTaskPlaceOnEventList等缺失、不涉及任务优先级继承机制xTaskPriorityInherit等缺失——从这些缺失函数可以反推出该 API 是零副作用、无阻塞、可被任何上下文安全调用的只读接口。六、无假设、无抽象的验证含义与局限README 中最值得展开的论断是No assumptions nor abstractions are required for single-threaded computation.单线程计算不需要假设也不需要抽象。这句话包含两层含义为何不需要假设assumptions在 CBMC 验证中assume通常用于约束符号输入如指针指向合法内存、枚举取值合法。xTaskGetTickCount无参数、不依赖外部输入harness 中也没有__CPROVER_assume语句验证从全符号化的内核全局状态出发对所有可能的 tick 计数值进行穷举检查因此无需任何前提约束。为何不需要抽象abstractions抽象如把复杂数据结构替换为简化模型通常用于降低验证难度。本案例中被验证的路径极短——读取一个全局变量并返回--unwind 1的展开深度已足够覆盖全部执行路径状态空间小到可以直接对真实实现完成穷举抽象反而会引入验证了错误的代码的风险。局限work-in-progressREADME 明确标注该证明仍在演进中。当前验证范围仅限单线程、无中断场景下的内存安全属性数组越界、空指针解引用、非法内存访问等。并发场景下 tick 变量被中断/其他上下文修改时的读写竞争data race属性、以及对TaskIncrementTick完整逻辑的覆盖均不在当前证明结论之内。因此本文描述的是该 API 在单线程模型下的内存安全已被形式化验证而非该 API 在所有并发场景下绝对安全。七、如何在本仓库中查看与复现该证明要在本仓库中进一步研究该证明可以按以下路径逐步展开阅读证明说明README.md本文所依据的关联文档查看验证入口TaskGetTickCount_harness.charness 全量源码含许可证与包含关系查看构建配置Makefile.jsonENTRY/CBMCFLAGS/OBJS三字段注意其引用了$(FREERTOS)/Source/tasks.goto即内核源码的编译中间产物查看缺失函数清单cbmc-viewer.json含完整expected-missing-functions列表与proof-name/proof-root元信息横向对比同类证明进入 FreeRTOS/Test/CBMC/proofs/Task 目录对照阅读TaskDelay、TaskCreate、TaskIncrementTick等证明的 harness 与Makefile.json即可总结出 FreeRTOS 内存安全验证的通用范式每个证明独立目录、统一四文件布局、harness 只暴露最小调用路径、Makefile.json以$(FREERTOS)变量链接触达真实内核代码。需要注意的是运行 CBMC 验证需要安装 CBMC 工具链cbmc、goto-cc等并以本仓库中 FreeRTOS/Test/CBMC 目录下的构建脚本驱动Makefile.json且由于内核以 submodule 方式挂载首次使用前需确保FreeRTOS/Source下的内核源码已就绪证明产物tasks.goto依赖该目录的编译。结语TaskGetTickCount证明虽小却是理解 FreeRTOS CBMC 验证体系的最佳起点它以极简的 harness 展示了无假设、无抽象、单线程穷举的验证风格用Makefile.json串起harness 真实内核 goto 程序的链接关系再以cbmc-viewer.json的缺失函数清单反推出xTaskGetTickCount的只读、无副作用特性。读懂这一个证明就能举一反三地读懂 Task 系列其余 14 个证明以及 Queue、list 等子系统中的内存安全验证实践。【免费下载链接】FreeRTOSClassic FreeRTOS distribution. Started as Git clone of FreeRTOS SourceForge SVN repo. Submodules the kernel.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeRTOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表