拓冰建站拓冰建站
首页 / 资讯中心 / 正文

FreeRTOS TaskSwitchContext 内存安全形式化验证:基于 CBMC 的证明分析与实践

FreeRTOS TaskSwitchContext 内存安全形式化验证基于 CBMC 的证明分析与实践【免费下载链接】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证明套件中的TaskSwitchContext证明用例说明它如何以符号执行与有界模型检查的方式验证 FreeRTOS 任务调度器中核心函数vTaskSwitchContext()的内存安全无越界、无空指针解引用等。读者将理解该证明的假设前提、harness测试驱动构造逻辑、Makefile 配置与运行方式并学会如何在本地复现这一形式化验证流程。背景为什么要证明vTaskSwitchContext的内存安全在 FreeRTOS 中vTaskSwitchContext()是每次时钟节拍中断tick interrupt到来时由调度器调用的关键函数负责决定下一个运行哪个任务并触发真正的上下文切换。它内部会执行检查调度器是否挂起uxSchedulerSuspended遍历就绪任务链表pxReadyTasksLists通过taskSELECT_HIGHEST_PRIORITY_TASK()宏挑选最高优先级就绪任务更新pxCurrentTCB指向被选中的任务控制块调用vTaskSwitchContext相关的 trace 钩子与运行时间统计钩子。该函数运行在中断上下文、每 tick 都会执行且直接操作内核全局链表与 TCB因此任何越界访问、空指针或链表遍历错误都会导致系统崩溃或内存破坏。这正是官方在 CBMC 证明基础设施 中选择它为证明对象的原因——证明套件对 FreeRTOS 代码库各入口做内存安全自动化证明并通过持续集成系统在每次 PR 提交时自动验证。证明概述与假设前提该证明用例的 READMETaskSwitchContext/README.md明确说明其目标This proof demonstrates the memory safety of the TaskSwitchContext function.具体假设如下就绪链表已初始化且每个链表均填入一个元素pxCurrentTCB指向最高优先级任务uxSchedulerSuspended被设置为非确定值nondeterministic value以覆盖挂起与未挂起两种调度器状态证明处于work-in-progress进行中状态完整假设说明记录在 harness 中。被假定安全的函数证明过程中以下四个函数被假定为内存安全、且与vTaskSwitchContext的内存安全不相关即无相关副作用prvTraceGetCurrentTaskHandleprvTraceGetTaskNumberprvTraceStoreTaskswitchulGetRunTimeCounterValue这些均属于 trace 与运行时间统计辅助函数证明时通过cbmc-viewer.json中声明的 expected-missing-functions 机制让 CBMC 将其视为黑盒从而把验证焦点集中在调度器链表遍历与 TCB 更新逻辑本身。Harness 构造驱动目标函数执行证明的核心是 harness 文件 TaskSwitchContext_harness.c它构造了满足上述假设的合法内核状态再调用被证明函数void harness() { BaseType_t xTasksPrepared; vSetGlobalVariables(); xTasksPrepared xPrepareTaskLists(); if( xTasksPrepared ! pdFAIL ) { vTaskSwitchContext(); } }流程分三步vSetGlobalVariables()将uxSchedulerSuspended设为非确定值nondet_ubasetype()使 CBMC 同时探索挂起/未挂起两条路径xPrepareTaskLists()先调用prvInitialiseTaskLists()初始化全部就绪链表然后为每个优先级i0..configMAX_PRIORITIES-1构造一个 TCB 并插入对应链表最后通过listGET_OWNER_OF_NEXT_ENTRY将pxCurrentTCB指向最高优先级configMAX_PRIORITIES - 1链表的第一个元素仅在链表准备成功非pdFAIL时调用vTaskSwitchContext()避免在未初始化状态下做无效验证。辅助函数xUnconstrainedTCB辅助访问函数头文件 tasks_test_access_functions.h 提供了xUnconstrainedTCB()用于生成带约束的任意 TCB通过pvPortMalloc( sizeof( TCB_t ) )分配真实大小的 TCB设置优先级uxPriority初始化状态链表项xStateListItem与事件链表项xEventListItem并将链表项 owner 指向 TCB 自身使用nondet_bool()非确定地设置链表项的值优先级或portMAX_DELAY使 CBMC 能探索不同的链表值分布。该文件中还包含关键注释填充每个就绪链表的目的是保证tasks.c中taskSELECT_HIGHEST_PRIORITY_TASK()相关断言README 注释中提到的 tasks.c 第 175 行附近不会失败从而让证明覆盖到正常的链表遍历路径。Makefile 配置如何约束 CBMC 的证明空间证明构建参数记录在 Makefile.json 中{ ENTRY: TaskSwitchContext, DEF: [ FREERTOS_MODULE_TEST, portGET_HIGHEST_PRIORITY(uxTopPriority, uxReadyPriorities)__CPROVER_assume( uxTopPriority configMAX_PRIORITIES ), mtCOVERAGE_TEST_MARKER()__CPROVER_assert(1, \Coverage marker\) ], CBMCFLAGS: [ --unwind 1, --unwindset prvInitialiseTaskLists.0:8,xPrepareTaskLists.0:8,vListInsert.0:2 ], OBJS: [ $(ENTRY)_harness.goto, $(FREERTOS)/Source/tasks.goto, $(FREERTOS)/Source/list.goto ], INC: [ $(FREERTOS)/Test/CBMC/proofs/Task/TaskSwitchContext/ ] }各字段含义字段作用ENTRY指定证明的入口函数名TaskSwitchContext与 harness 中被调用函数一致DEF定义预处理器宏重写内核内部宏以约束探索空间portGET_HIGHEST_PRIORITY被改写为__CPROVER_assume( uxTopPriority configMAX_PRIORITIES )保证优先级索引始终落在合法范围mtCOVERAGE_TEST_MARKER()被改写为始终为真的断言coverage markerCBMCFLAGSCBMC 命令行参数--unwind 1限制整体循环展开--unwindset对prvInitialiseTaskLists.0、xPrepareTaskLists.0展开 8 次、vListInsert.0展开 2 次精确控制三个关键函数的循环展开深度OBJS参与证明的 goto 程序对象harness 编译产物、内核tasks.goto与链表list.goto即证明范围锁定在任务调度与链表两大内核模块INC额外头文件搜索路径指向本证明目录从宏改写可以看出该证明的核心验证策略用符号假设替代真实硬件行为portGET_HIGHEST_PRIORITY在真实实现中依赖configUSE_PORT_OPTIMISED_TASK_SELECTION下的硬件位操作同时保留链表插入、遍历与 TCB 指针更新的真实逻辑从而在可控状态空间内证明内存安全。缺失函数声明哪些内核行为被抽象cbmc-viewer.json 声明了expected-missing-functions预期缺失函数主要包括移植层函数pxPortInitialiseStack、vPortEnterCritical、vPortExitCritical、xPortStartScheduler、vPortGenerateSimulatedInterrupt等与具体硬件移植相关调度相关函数vTaskSuspendAll、xTaskResumeAll、vTaskMissedYield、vTaskPlaceOnEventList、xTaskRemoveFromEventList、pvTaskIncrementMutexHeldCount、xTaskPriorityInherit等应用钩子vApplicationTickHook。这些函数在证明运行环境中被当作外部黑盒从而把验证聚焦于vTaskSwitchContext自身及其直接操作的链表/TCB 数据。这正体现了 CBMC 证明模块化抽象的思想只验证目标入口的内存安全而不必展开整个内核。如何运行与查看证明结果官方证明基础设施说明见 CBMC/README.md。整体流程如下安装 CBMC 工具链确保命令行可用cbmc、goto-ccWindows 上为goto-cl、goto-instrument生成报告还需cbmc-viewer准备依赖Python 3.7、Make64 位机器需安装 32 位 gcc 库Linux 下sudo apt-get install gcc-multilib初始化子模块在仓库根目录执行git submodule update --init --recursive --checkout内核源码位于FreeRTOS/Source子模块中tasks.goto、list.goto由该子模块源码编译生成生成证明 Makefile进入proofs目录执行python3 prepare.pyWindows 下生成 Linux Makefile 可加--system linux反之用--system windows运行证明进入证明目录cd proofs/Task/TaskSwitchContext后执行make查看报告make会生成 HTML 与 JSON 两种格式报告打开html/index.html查看若运行成功则Errors一节显示None。该 README 同时说明proofs目录下每个叶子目录都对应一个内核入口的内存安全证明如 TaskCreate、TaskDelay、TaskIncrementTick 等TaskSwitchContext只是其中针对上下文切换核心函数的一例。patches目录中的补丁会在运行证明前移除源码中的static与volatile限定符以保证 goto 程序对目标函数的可达性。结论与局限本证明用例的意义在于把调度器切换任务时不会产生内存安全问题这一关键性质从依赖人工审查提升为机器可验证的数学结论。通过 harness 精心构造的链表状态、nondet符号值对调度器状态挂起与否、链表项取值的全覆盖以及--unwind系列参数对循环的有限展开CBMC 得以在有界范围内穷举vTaskSwitchContext的合法执行路径。同时需注意其局限该证明仍标注为 work-in-progress依赖对 trace 函数与移植层函数的内存安全假定且循环展开是有界的bounded因此它验证的是在给定假设与展开深度内的内存安全而非对任意运行时间的完全证明。理解这些前提才能正确评估该证明在 FreeRTOS 形式化验证体系中的定位与价值。【免费下载链接】FreeRTOSClassic FreeRTOS distribution. Started as Git clone of FreeRTOS SourceForge SVN repo. Submodules the kernel.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeRTOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门