操作系统安全与端侧 AI 推理部署:常见反模式与安全防护架构
操作系统安全与端侧 AI 推理部署:常见反模式与安全防护架构
把大模型或小参数量语言模型(SLM)放到嵌入式设备上,通常要同时处理性能、设备权限和运维约束。
在算力受限的边缘板卡上,为了优化推理延迟或提升吞吐帧率,部分系统设计在操作系统层面采用了削弱隔离粒度的做法。然而,工程实践表明,在 Demo 演示阶段看似高效的优化方式,置于真实生产环境后往往会演变为系统安全与稳定隐患。端侧 AI 部署在追求执行效率的同时,更需保障系统稳健性。若过度放宽 Linux 操作系统的安全边界,将带来潜在的安全风险。
常见端侧 AI 部署反模式拆解
综合常见端侧推理项目的架构设计,存在三个典型且需关注的反模式:
1. 为追求调度效率直接授予 CAP_SYS_ADMIN 或 Root 特权
在嵌入式 Linux 系统中,推理任务常需要进行 CPU 核心绑定(sched_setaffinity)或设置实时调度优先级(SCHED_FIFO)。部分部署配置直接在 systemd 服务文件中指定 User=root。
这种配置意味着,若推理引擎在解析模型输入时发生缓冲区溢出,越权行为将直接获取设备的最高控制权,从而构成对内网其他节点的安全威胁。
2. 基于未隔离共享内存进行零拷贝
为省去用户态、内核态与 NPU 驱动之间的多级内存复制,部分实现自定义字符设备驱动,通过 remap_pfn_range 将连续物理内存直接映射给应用层。
然而,若该段内存缺乏访问控制列表(ACL)及地址空间隔离保护,同一设备上的其他普通权限进程便可能通过 mmap 读取模型推理过程中的敏感中间张量,甚至导出模型权重。
3. 在应用层内存中解密模型文件
部分方案将加密的模型权重保存在 Flash 中,系统启动时由推理进程读取至内存并完成解密。
在未启用 Linux 内核 ptrace 限制的情况下,通过挂载调试工具即可提取解密后的完整权重,造成资产泄露风险。
建立安全的无特权端侧推理架构
这些风险不等于只能以性能换安全。Linux 提供了可组合的隔离机制,但具体代价取决于驱动、硬件和推理运行时:
- 进程降级与资源硬隔离:利用
cgroups v2的cpuset子系统,在系统启动阶段为推理进程划定固定的 CPU 核心池,无需在运行时动态申请高特权调度接口。 seccomp-bpf系统调用过滤:先通过实际运行跟踪得到运行时需要的调用集合,再按架构和版本编写策略。它可以缩小攻击面,但不能替代内存安全、输入校验和设备访问控制。- 利用
DMA-BUF传递缓冲区:DMA-BUF 通过文件描述符共享缓冲区并管理生命周期。是否允许导出、映射和同步仍取决于具体驱动与权限模型,不能把它视为自动的保密机制。
基于 C 语言的 seccomp-bpf 沙箱实施代码
以下代码只演示过滤器的结构,不是一份可直接用于推理运行时的白名单。真实部署必须用 strace、审计日志或运行时文档确认调用集,并在目标板卡上回归测试。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <errno.h>
// 检查架构并限制为 x86_64 或 ARM64
#if defined(__x86_64__)
#define ARCH_NR AUDIT_ARCH_X86_64
#elif defined(__aarch64__)
#define ARCH_NR AUDIT_ARCH_AARCH64
#else
#error "Unsupported Architecture"
#endif
static int apply_inference_seccomp_sandbox(void) {
// 允许推理运行时所需的极少数安全 syscall
struct sock_filter filter[] = {
// 1. 检查架构是否匹配
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, arch))),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARCH_NR, 1, 0),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
// 2. 读取 syscall 编号
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
// 3. 显式拦截并拒绝 ptrace (防止内存 dump)
#ifdef __NR_ptrace
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_ptrace, 0, 1),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EPERM & SECCOMP_RET_DATA)),
#endif
// 4. 白名单允许:futex, read, write, ioctl, exit_group
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_read, 4, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_write, 3, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_ioctl, 2, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 1, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_futex, 0, 1),
// 匹配成功返回 ALLOW,不匹配则拒绝并中断
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS)
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
// 启用 NO_NEW_PRIVS,阻止后续 exec 获得额外权限
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
perror("PR_SET_NO_NEW_PRIVS 失败");
return -1;
}
// 装载 seccomp 过滤器
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
perror("PR_SET_SECCOMP 载入失败");
return -1;
}
printf("端侧推理 seccomp 低开销沙箱装载成功。\n");
return 0;
}
int main(void) {
printf("完成模型初始化与硬件 Device 句柄绑定...\n");
// 加载沙箱
if (apply_inference_seccomp_sandbox() != 0) {
exit(EXIT_FAILURE);
}
// 沙箱激活后的推理循环逻辑
printf("沙箱保护中:执行安全推理逻辑...\n");
return 0;
}
部署前应记录的评估项
不同 SoC、模型、驱动版本和策略复杂度下,延迟与内存变化会不同。部署前可按下列维度记录基线和隔离后的结果:
| 部署模式与配置 | 运行特权 | 系统调用白名单 | P99 推理延迟 (ms) | 内存额外开销 | 内存 Dump 攻击防御 |
|---|---|---|---|---|---|
| 特权模式 | 进程身份与 capability | 实际调用集 | 记录 P50/P99 | 记录 RSS/缓冲区 | 检查越权路径是否仍可用 |
| 共享缓冲区方案 | 缓冲区导出权限 | 映射与同步调用 | 记录 P50/P99 | 记录共享缓冲区占用 | 尝试跨进程访问与 fd 泄漏 |
| 受限模式 | 无特权用户、最小 capability | 经回归验证的白名单 | 与基线对比 | 与基线对比 | 验证拒绝行为和正常推理 |
端侧 AI 的工程推进既需要考虑算法剪枝与帧率表现,也需兼顾生产环境下的系统稳定性与安全防线。
端侧部署的目标不是套一份固定策略,而是在目标硬件上验证:推理流程仍可用,越权路径被限制,性能开销处于团队可接受范围。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)