Container和VM的隔离性分析 (4) Seccomp

487 阅读6分钟

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,请执行以下操作:  grepSECCOMP/boot/config grep SECCOMP /boot/config-(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的限制。