Docker 的 Seccomp 安全配置文件

安全计算模式(seccomp)是 Linux 内核的一项功能。您可以使用它来限制容器内可用的操作。seccomp()系统调用作用于调用进程的 seccomp 状态。您可以使用此功能来限制应用程序的访问权限。

此功能仅在 Docker 使用 seccomp 构建且内核已启用 CONFIG_SECCOMP 配置时可用。要检查您的内核是否支持 seccomp

$ grep CONFIG_SECCOMP= /boot/config-$(uname -r)
CONFIG_SECCOMP=y

为容器传递一个配置文件

默认 seccomp 配置文件为使用 seccomp 运行容器提供了合理的默认设置,并在 300 多个系统调用中禁用了约 44 个。它在提供广泛应用程序兼容性的同时具有中等程度的保护性。默认的 Docker 配置文件可在此处找到 这里

实际上,该配置文件本质上是一个允许列表,默认情况下会拒绝所有系统调用,然后仅对特定的系统调用进行放行。该配置文件通过为 defaultActionSCMP_ACT_ERRNO 定义操作并针对特定系统调用覆盖该操作来工作。SCMP_ACT_ERRNO 的效果是触发一个 Permission Denied 错误。接下来,配置文件定义了一个完全允许的系统调用列表,因为它们的 action 被覆盖为 SCMP_ACT_ALLOW。最后,针对 personality 等其他特定系统调用,还定义了一些具体规则,以允许带有特定参数的这些系统调用的变体。

seccomp 对于以最少数权限运行 Docker 容器至关重要。不建议更改默认的 seccomp 配置文件。

运行容器时,除非您使用 --security-opt 选项覆盖它,否则它将使用默认配置文件。例如,以下内容明确指定了策略:

$ docker run --rm \
             -it \
             --security-opt seccomp=/path/to/seccomp/profile.json \
             hello-world

默认配置文件阻止了大量系统调用

Docker 的默认 seccomp 配置文件是一个白名单,用于指定允许的系统调用。下表列出了因未包含在白名单中而被实际阻止的重要(但非全部)系统调用。该表还说明了每个系统调用被阻止而非列入白名单的原因。

系统调用描述
acct可能导致容器禁用其自身资源限制或进程计时的会计系统调用。同样受 CAP_SYS_PACCT 控制。
add_key阻止容器使用非命名空间的密钥环。
bpf拒绝将潜在的持久化 bpf 程序加载到内核中,这已经由 CAP_SYS_ADMIN 进行限制。
clock_adjtime时间/日期未命名空间化。同时受 CAP_SYS_TIME 限制。
clock_settime时间/日期未命名空间化。同时受 CAP_SYS_TIME 限制。
clone拒绝克隆新命名空间。此外还受 CAP_SYS_ADMIN 的 CLONE_* 标志门控,CLONE_NEWUSER 除外。
create_module拒绝内核模块的操纵和功能。已过时。同时也受 CAP_SYS_MODULE 限制。
delete_module拒绝操作和内核模块的功能。同样受 CAP_SYS_MODULE 限制。
finit_module拒绝操作和内核模块的功能。同样受 CAP_SYS_MODULE 限制。
get_kernel_syms拒绝检索导出的内核和模块符号。已过时。
get_mempolicy修改内核内存和 NUMA 设置的系统调用。已由 CAP_SYS_NICE 限制。
init_module拒绝操作和内核模块的功能。同样受 CAP_SYS_MODULE 限制。
ioperm防止容器修改内核 I/O 权限级别。已由 CAP_SYS_RAWIO 控制。
iopl防止容器修改内核 I/O 权限级别。已由 CAP_SYS_RAWIO 控制。
kcmp限制进程检查能力,已通过丢弃 CAP_SYS_PTRACE 进行阻止。
kexec_file_loadkexec_load 类似的姊妹系统调用,功能相同但参数略有不同。同样受 CAP_SYS_BOOT 控制。
kexec_load拒绝加载新内核以供稍后执行。同时受 CAP_SYS_BOOT 控制。
keyctl阻止容器使用非命名空间的密钥环。
lookup_dcookie跟踪/分析系统调用,这可能会泄露大量主机信息。同时受 CAP_SYS_ADMIN 限制。
mbind修改内核内存和 NUMA 设置的系统调用。已由 CAP_SYS_NICE 限制。
mount拒绝挂载,已由 CAP_SYS_ADMIN 限制。
move_pages修改内核内存和NUMA设置的系统调用。
nfsservctl拒绝与内核 NFS 守护进程交互。自 Linux 3.1 起已废弃。
open_by_handle_at旧容器逃逸的原因。同样受 CAP_DAC_READ_SEARCH 限制。
perf_event_open跟踪/分析系统调用,这可能会泄露大量主机信息。
personality防止容器启用 BSD 模拟。该功能本身并不危险,但测试不足,存在大量内核漏洞的潜在风险。
pivot_root拒绝 pivot_root,应为特权操作。
process_vm_readv限制进程检查能力,已通过丢弃 CAP_SYS_PTRACE 进行阻止。
process_vm_writev限制进程检查能力,已通过丢弃 CAP_SYS_PTRACE 进行阻止。
ptrace跟踪/分析系统调用。在 4.8 之前的 Linux 内核版本中,为避免绕过 seccomp 而阻止此操作。跟踪/分析任意进程已被禁止(通过丢弃 CAP_SYS_PTRACE),因为它可能会泄露大量主机信息。
query_module禁止对内核模块进行操纵和操作。已废弃。
quotactl配额系统调用可能允许容器禁用其自身的资源限制或进程记账。同时受 CAP_SYS_ADMIN 控制。
reboot不要让容器重启主机。同时也受 CAP_SYS_BOOT 限制。
request_key阻止容器使用非命名空间的密钥环。
set_mempolicy修改内核内存和 NUMA 设置的系统调用。已由 CAP_SYS_NICE 限制。
setns拒绝将线程与命名空间关联。同时受 CAP_SYS_ADMIN 限制。
settimeofday时间/日期未命名空间化。同时受 CAP_SYS_TIME 限制。
stime时间/日期未命名空间化。同时受 CAP_SYS_TIME 限制。
swapon拒绝将 swap 交换到文件/设备。同时受 CAP_SYS_ADMIN 限制。
swapoff拒绝将 swap 交换到文件/设备。同时受 CAP_SYS_ADMIN 限制。
sysfs已过时的系统调用。
_sysctl已废弃,被 /proc/sys 取代。
umount应该是一个特权操作。同时也受 CAP_SYS_ADMIN 限制。
umount2应该是一个特权操作。同时也受 CAP_SYS_ADMIN 限制。
unshare拒绝为进程克隆新命名空间。这也受 CAP_SYS_ADMIN 控制,但 unshare --user 除外。
uselib与共享库相关的较旧的系统调用,已废弃多年。
userfaultfd用户空间页面错误处理,主要用于进程迁移。
ustat已过时的系统调用。
vm86在内核 x86 实模式虚拟机中。同样受 CAP_SYS_ADMIN 限制。
vm86old在内核 x86 实模式虚拟机中。同样受 CAP_SYS_ADMIN 限制。

在不使用默认 seccomp 配置文件的情况下运行

您可以传递 unconfined 以在不加载默认 seccomp 配置文件的情况下运行容器。

$ docker run --rm -it --security-opt seccomp=unconfined debian:jessie \
    unshare --map-root-user --user sh -c whoami