Seccomp是Linux内核的一种安全机制,它可以限制进程可以调用的系统调用。它的实现基于Linux内核的ptrace机制,可以使用它来监视和控制进程的行为。seccomp(安全计算模式)是Linux内核中的一种计算机安全设施。seccomp允许进程进行单向转换,进入“安全”状态,此时它不能进行任何系统调用,除了exit()、sigreturn()、read()和write(),以及已经打开的文件描述符。如果尝试进行其他系统调用,内核将仅记录事件或通过SIGKILL或SIGSYS终止进程。从这个意义上说,它不会虚拟化系统的资源,而是完全隔离进程。通过prctl(2)系统调用并使用PR_SET_SECCOMP参数,或(自Linux内核3.17以来)通过seccomp(2)系统调用启用seccomp模式。以前可以通过向/proc/self/seccomp文件写入来启用seccomp模式,但现在已经弃用,改为使用prctl()。在一些内核版本中,seccomp禁用了RDTSC x86指令,该指令返回自开机以来经过的处理器周期数,用于高精度计时。仅当Docker已使用seccomp构建,并且内核配置已启用CONFIG_SECCOMP时,才可用此功能。要检查内核是否支持seccomp,请执行以下操作: (uname -r) CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_SECCOMP_FILTER=y CONFIG_SECCOMP=y
默认的seccomp配置文件为使用seccomp运行容器提供了合理的默认设置,并在300多个系统调用中禁用了大约44个。它在提供广泛的应用程序兼容性的同时,具有适度的保护性。默认的Docker配置文件可以在此处找到。实际上,该配置文件是一个允许列表,它默认拒绝对系统调用的访问,然后允许特定的系统调用。该配置文件通过定义SCMP_ACT_ERRNO的defaultAction来工作,并仅针对特定的系统调用覆盖该操作。SCMP_ACT_ERRNO的效果是导致Permission Denied错误。接下来,该配置文件定义一个特定的系统调用列表,这些系统调用是完全允许的,因为它们的操作被覆盖为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 禁止克隆新的命名空间。对于CLONE_*标志,除CLONE_NEWUSER外,还需要CAP_SYS_ADMIN权限。
- 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_load kexec_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设置的系统调用。
- name_to_handle_at:打开文件句柄的姐妹系统调用,已通过CAP_DAC_READ_SEARCH进行门控。
- 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:跟踪/分析系统调用。在Linux内核版本4.8之前被阻止以避免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:禁止开始/停止文件/设备的交换。也通过CAP_SYS_ADMIN进行门控。
- swapoff:禁止开始/停止文件/设备的交换。也通过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的限制。