如何在不限制父进程的情况下为子进程应用seccomp过滤?
问题解答
核心结论:这种方法不可行
原因有两点:
- seccomp过滤规则是线程级绑定的,当调用
execve时,整个进程的地址空间会被完全替换,原进程的所有线程(包括设置了seccomp规则的线程)都会被销毁,新程序的初始线程不会继承原线程的seccomp规则。 - 退一步说,如果spawner的线程已经设置了禁止
execve的规则,那么它自己调用execve的时候就会被seccomp拦截,根本无法完成切换到app的操作。
可行方案
方案1:fork子进程后,在execve前设置seccomp规则
这是最常规且可靠的方式:
- spawner先调用
fork()创建子进程 - 在子进程上下文(尚未调用
execve)中,加载禁止execve的seccomp过滤规则 - 最后在子进程中调用
execve启动app
因为execve不会清除子进程已设置的seccomp规则(只要规则配置正确,未触发终止进程的动作),app启动后会继承这个规则,所有syscall都会受到限制。
方案2:利用内核seccomp继承特性(Linux 3.17+)
如果目标系统内核版本≥3.17,可以借助seccomp的扩展特性:
- 在spawner中创建seccomp过滤规则时,使用
SECCOMP_FILTER_FLAG_NEW_LISTENER标记生成一个监听器文件描述符 - fork子进程后,将该文件描述符传递给子进程,子进程通过该监听器应用规则,再执行
execve
这种方式适合需要批量给多个子进程应用相同规则的场景,避免重复加载规则的开销。
方案3:通过ptrace拦截syscall
如果seccomp的使用有环境限制,可以用ptrace实现类似功能:
- spawner调用
fork()后,在子进程中调用ptrace(PTRACE_TRACEME, ...),然后执行execve启动app - spawner作为跟踪进程,捕获app发起的
execve系统调用,直接阻止该调用执行
不过这种方式的性能开销比seccomp大,适合对性能要求不高的场景。
内容的提问来源于stack exchange,提问作者Melab
相关产品推荐
相关产品推荐

