Fil-C 0.680 版本实现了一套内存安全的上下文切换方案,通过能力模型封堵了传统 setjmp/longjmp 与 ucontext API 常见的栈损坏漏洞。
传统 API 的危险根源
setjmp/longjmp 在 C 程序中常用于异常处理,尤其在信号处理器中“抛出”异常时几乎是唯一选择。ucontext 系列 API(getcontext、setcontext、makecontext、swapcontext)则是协程和纤程的基础,Boost 库的 fiber 实现就依赖它们。
这些 API 的共同问题是:一旦被误用,longjmp 或 swapcontext 会尝试恢复到已被释放的栈上继续执行。在传统 C 实现中,这种“悬空栈执行”会导致最令人困惑的崩溃——调试器甚至无法打印堆栈跟踪;如果攻击者利用这类逻辑漏洞,还可能让程序执行任意代码。
Fil-C 的安全策略
Fil-C 采用了完全不同的实现思路:它对每个栈和每个上下文都维护能力标签,追踪它们的所有权和生命周期。任何试图访问悬空栈的操作都会被拦截。
具体来说,Fil-C 禁止了两种典型误用:一是 makecontext 创建的上下文指向已释放的栈,后续 swapcontext 或 setcontext 会被拒绝;二是 swapcontext 的目标参数传入当前正在执行的上下文,这会被视为安全错误并触发 panic,而非像某些实现那样退化为 longjmp 或导致悬空栈执行。
对于 setjmp/longjmp 的复杂性,Fil-C 同样做了处理。编译器优化 setjmp 覆盖的变量时可能产生意外行为:volatile 变量会被视为栈分配而非寄存器或溢出槽,Fil-C 对这类语义的特殊处理确保了可预测性。
为什么这值得关注
Fil-C 的核心承诺是:所有非法操作都会在发生误用的位置触发 panic,而不会让程序在悬空栈上继续运行。这意味着开发者面对的是明确的错误,而不是难以复现的崩溃。在 C 的历史中,上下文切换 API 一直是内存安全的重灾区,Fil-C 的方案提供了一个可复制的思路。
编注:信源为 fil-c.org 技术文档,材料侧重机制原理与安全策略,未涉及性能基准或与其他实现的对比数据。