3. VxWorks内核裁剪与攻击面缩减

VxWorks 的默认工程配置往往为了兼容性和开发便利,把大量组件、驱动、协议栈和调试服务一并编入镜像。对安全加固而言,这些“用不到但存在”的代码就是攻击面:每一个可被外部触发的系统调用、每一个监听端口的服务、每一个可被加载的驱动,都可能成为漏洞入口。本节的核心思路是:先通过组件依赖分析确定“最小可用集合”,再移除未使用驱动与服务,最后用系统调用过滤和编译期安全选项把剩余攻击面进一步收紧。

一、组件依赖分析:从“全量”到“最小集”

VxWorks 的组件以 INCLUDE_* 宏的形式在 config.h / configAll.h 中声明,组件之间存在隐式依赖。例如启用 INCLUDE_NETWORK 会连带引入网络缓冲、MUX、协议栈等;启用 INCLUDE_DEBUG 会引入符号表和调试代理。裁剪不能靠“凭感觉删宏”,否则会出现链接失败或运行期异常。

推荐做法是先用工具生成依赖视图,再人工确认。VxWorks 提供 vxprj 命令行工具,可导出组件依赖关系:

vxprj component list > comps.txt
vxprj component depend INCLUDE_NETWORK > net_dep.txt
vxprj bundle list > bundles.txt

其中 vxprj component depend 会列出某组件所依赖的其它组件,这是判断“删掉它会不会连带破坏其它功能”的关键依据。实际工程中,建议按“功能域”分组裁剪:网络域、文件系统域、调试域、图形域、USB/PCI 域。每个域先确认是否被业务代码引用,再决定保留或移除。

裁剪前务必保留一份可启动的基线镜像,并记录每个被移除组件的名称与原因,便于回滚和审计。

二、未使用驱动与服务的移除

驱动和服务的移除比组件宏更细粒度。常见可移除对象包括:未使用的串口驱动、未挂载的文件系统(如 dosFs、rawFs)、未使用的网络服务(FTP、Telnet、rlogin、SNMP)、以及调试服务(WDB 目标代理、符号表)。移除方式有两种:一是从 config.h 中注释掉对应 INCLUDE_*;二是在 usrConfig.c 或 sysLib.c 中删除对应的初始化调用。

以移除 Telnet 服务为例,需同时处理三处:

/* config.h 中移除 */
#undef INCLUDE_TELNETD

/* usrConfig.c 中移除初始化 */
/* telnetdInit(); 已删除 */

/* 确认无其它模块调用 telnetdInit */

移除后应通过 vxprj build 重新编译,观察链接阶段是否报未定义符号。若报错,说明仍有模块引用该服务,需继续追溯调用链。编译通过后,用 nm 或 vxnm 检查最终镜像中是否还存在相关符号,确认移除彻底。

三、系统调用过滤

VxWorks 内核并不像 Linux 那样有统一的 syscall 表,但可以通过“符号可见性”和“入口收敛”实现类似过滤。具体手段包括:

  • 关闭 INCLUDE_SYM_TBL 和 INCLUDE_STANDALONE_SYM_TBL,使外部无法通过符号名定位内核函数;
  • 移除 INCLUDE_WDB 及其相关代理,关闭远程调试入口;
  • 对必须保留的服务,通过 loginLib 或自定义钩子限制调用来源(如仅允许本地任务调用);
  • 使用 taskSpawn 的优先级和选项参数限制新任务的权限,避免任意任务调用敏感接口。

下图展示了从“全量内核”到“最小化内核”的攻击面收敛路径,以及各阶段的关键操作与观察点:

VxWorks 内核裁剪与攻击面收敛路径 全量内核 默认 configAll.h 网络/调试/文件系统全开 依赖分析 vxprj component depend 生成组件依赖图 组件裁剪 移除未用 INCLUDE_* 删除初始化调用 编译验证 vxprj build nm 查符号 攻击面清单 • 网络协议栈 • FTP/Telnet/SNMP • WDB 调试代理 • 符号表 • 未用文件系统 依赖分析输出 INCLUDE_NETWORK → MUX, END, TCP/IP INCLUDE_DEBUG → SYM_TBL, WDB INCLUDE_DOSFS → CBIO, MSDOS 裁剪操作 #undef INCLUDE_TELNETD #undef INCLUDE_WDB #undef INCLUDE_SYM_TBL 删除 telnetdInit() 删除 wdbInit() 验证要点 链接无报错 符号已消失 镜像缩小 启动正常 功能回归 编译期安全选项 栈保护 -fstack-protector 检测栈溢出 只读重定位 -Wl,-z,relro GOT 只读保护 地址随机化 -fPIE -pie 加载基址随机 符号剥离 strip 镜像 减少信息泄露

四、编译期安全选项实践

VxWorks 使用 GCC 或 Diab 编译器,编译选项在 Makefile 或工程属性中设置。以下选项在 VxWorks 7 的 GCC 工具链中可直接使用:

CFLAGS += -fstack-protector-strong
CFLAGS += -fPIE
LDFLAGS += -pie -Wl,-z,relro,-z,now
CFLAGS += -D_FORTIFY_SOURCE=2

其中 -fstack-protector-strong 会在函数栈帧中插入 canary 值,函数返回前校验,检测到篡改则调用 __stack_chk_fail 终止任务。-Wl,-z,relro,-z,now 使 GOT 表在加载后立即绑定并设为只读,防止 GOT 覆写攻击。-fPIE -pie 使镜像支持地址随机化,增加攻击者定位代码的难度。

需要注意:VxWorks 内核本身是静态链接的,部分选项(如 PIE)对内核镜像效果有限,但对 RTP(Real-Time Process)用户态进程效果显著。因此建议对 RTP 应用强制启用上述选项,内核则重点使用栈保护和符号剥离。

五、裁剪效果验证

裁剪完成后,应从三个维度验证:

验证维度方法判断标准
镜像大小对比裁剪前后 vxWorks 文件大小体积下降,通常可缩减 30%~60%
符号暴露nm vxWorks | grep -i telnet无输出,说明符号已移除
功能回归运行核心业务任务,检查网络、文件、任务调度业务功能正常,无异常重启
裁剪后若出现启动挂起,优先检查是否误删了 INCLUDE_WDB 之外的调试依赖,或 sysLib.c 中仍引用了已移除的驱动初始化函数。建议逐项回滚,定位最小破坏点。