引言
系统调用是用户空间程序与内核交互的入口,也是安全攻击面的核心所在。seccomp(Secure Computing Mode)作为Linux内核提供的沙箱机制,能夠在进程粒度上精细控制系统调用能力,最小化攻击权限。本文从内核机制到生交实战,全面剖析系统调用拦截与seccomp沙箱技术。
一、系统调用机制内核剖析
1.1 用户态到内核态的切换过程
系统调用本质上是受控的用户态到内核态切换。以x86_64架构为例,执行流程如下:
- entry_SYSCALL_64:汇编入口,保存寄存器到pt_regs,切换到内核栈
- do_syscall_64:从rax取出系统调用号,查sys_call_table跳转
- 参数传递:rdi、rsi、rdx、r10、r8、r9顺序传递六个参数
- 返回值写入rax,执行sysretq恢复到用户态
1.2 系统调用表与调用流
sys_call_table是一个函数指针数组,索引即为系统调用号。例如__x64_sys_read读取文件,__x64_sys_write写入数据。
1.3 传统拦截技术对比
在seccomp出现之前,系统调用拦截主要有以下方式:
- ptrace:通过调试接口拦截,性能开销大(每次调用两次上下文切换)
- LD_PRELOAD:覆盖glibc封装函数,无法拦截直接syscall指令,易被绕过
- LSM钩子:SELinux/AppArmor提供强制性访问控制,粒度过粗
- kprobes:内核探测点,功能强大但面向内核模块,风险高
二、seccomp-BPF机制深度解析
2.1 架构设计
seccomp(Secure Computing)支持两种模式:
- SCMP_ACT_MODE_STRICT (mode 1):仅允许read/write/_exit/sigreturn四个调用,任何其他调用触发SIGKILL
- SCMP_ACT_MODE_FILTER (mode 2, seccomp-BPF):加载BPF过滤器,对每个系统调用执行程序判定返回动作
2.2 BPF过滤执行流程
当进程执行系统调用时,过滤流程如下:
- CPU保存寄存器上下文到内核栈
- seccomp检查进程是否有附加的BPF过滤器
- 有过滤器时,调用
seccomp_run_filters()将pt_regs压入BPF栈执行程序 - BPF程序通过
seccomp_data结构体获取系统调用号、参数、指令指针等信息 - 根据返回值决定动作:KILL/LOG/ALLOW/ERRNO/TRACE/NOTIF
2.3 BPF程序结构与指令限制
seccomp-BPF有以下严格约束:
- 仅能访问
struct seccomp_data(固定大小256字节) - 最多4096条指令(经典BPF,

发表评论 取消回复