Docker 向け Seccomp セキュリティプロファイル

読む時間の目安: 5 分

セキュリティコンピューティングモード(secure computing mode; seccomp)は Linux カーネルの機能です。 これを使うと、コンテナー内で利用できる処理を限定することができます。 システムコールseccomp()は呼び出し側プロセスの seccomp 状態を操作します。 この機能は、アプリケーションのアクセス処理を制限するものとして利用することができます。

この機能を利用するためには、Docker がseccompを使ってビルドされていること、そしてカーネルがCONFIG_SECCOMPを有効にしていることが必要です。 カーネルがseccompをサポートしているかどうかは、以下のようにして確認します。

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

メモ

seccompプロファイルは seccomp 2.2.1 を必要としますが、これは Ubuntu 14.04、Debian Wheezy、Debian Jessie では利用できません。 そのディストリビューションにおいてseccompを利用する場合は、(パッケージをインストールするのではなく)最新の Linux 実行モジュール をダウンロードして利用する必要があります。

コンテナーへのプロファイルの受け渡し

デフォルトのseccompプロファイルは、seccomp を使ってコンテナーを実行するための、十分に考慮されたデフォルトを提供します。 そして 300 以上あるシステムコールのうち 44 個を無効とします。 これは幅広くアプリケーションとの互換性を提供しつつ、適度なセキュリティ保護を実現します。 デフォルトの Docker プロファイルは こちら にあります。

実際にプロファイルは許可リスト方式をとるものであり、デフォルトではシステムコールのアクセスを拒否します。 そして特定のシステムコールを許可します。 プロファイルはSCMP_ACT_ERRNOdefaultActionを定義することで動作し、指定したシステムコールのみ、その動作をオーバーライドします。 SCMP_ACT_ERRNOの効果はPermission Deniedエラーを発生させることです。 次にプロファイルにおいては、システムコールのうち、完全に動作を許容するものを列記します。 これによって各actionSCMP_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 Accounting syscall which could let containers disable their own resource limits or process accounting. Also gated by CAP_SYS_PACCT.
add_key Prevent containers from using the kernel keyring, which is not namespaced.
bpf Deny loading potentially persistent bpf programs into kernel, already gated by CAP_SYS_ADMIN.
clock_adjtime Time/date is not namespaced. Also gated by CAP_SYS_TIME.
clock_settime Time/date is not namespaced. Also gated by CAP_SYS_TIME.
clone Deny cloning new namespaces. Also gated by CAP_SYS_ADMIN for CLONE_* flags, except CLONE_NEWUSER.
create_module Deny manipulation and functions on kernel modules. Obsolete. Also gated by CAP_SYS_MODULE.
delete_module Deny manipulation and functions on kernel modules. Also gated by CAP_SYS_MODULE.
finit_module Deny manipulation and functions on kernel modules. Also gated by CAP_SYS_MODULE.
get_kernel_syms Deny retrieval of exported kernel and module symbols. Obsolete.
get_mempolicy Syscall that modifies kernel memory and NUMA settings. Already gated by CAP_SYS_NICE.
init_module Deny manipulation and functions on kernel modules. Also gated by CAP_SYS_MODULE.
ioperm Prevent containers from modifying kernel I/O privilege levels. Already gated by CAP_SYS_RAWIO.
iopl Prevent containers from modifying kernel I/O privilege levels. Already gated by CAP_SYS_RAWIO.
kcmp Restrict process inspection capabilities, already blocked by dropping CAP_SYS_PTRACE.
kexec_file_load Sister syscall of kexec_load that does the same thing, slightly different arguments. Also gated by CAP_SYS_BOOT.
kexec_load Deny loading a new kernel for later execution. Also gated by CAP_SYS_BOOT.
keyctl Prevent containers from using the kernel keyring, which is not namespaced.
lookup_dcookie Tracing/profiling syscall, which could leak a lot of information on the host. Also gated by CAP_SYS_ADMIN.
mbind Syscall that modifies kernel memory and NUMA settings. Already gated by CAP_SYS_NICE.
mount Deny mounting, already gated by CAP_SYS_ADMIN.
move_pages Syscall that modifies kernel memory and NUMA settings.
name_to_handle_at Sister syscall to open_by_handle_at. Already gated by CAP_DAC_READ_SEARCH.
nfsservctl Deny interaction with the kernel nfs daemon. Obsolete since Linux 3.1.
open_by_handle_at Cause of an old container breakout. Also gated by CAP_DAC_READ_SEARCH.
perf_event_open Tracing/profiling syscall, which could leak a lot of information on the host.
personality Prevent container from enabling BSD emulation. Not inherently dangerous, but poorly tested, potential for a lot of kernel vulns.
pivot_root Deny pivot_root, should be privileged operation.
process_vm_readv Restrict process inspection capabilities, already blocked by dropping CAP_SYS_PTRACE.
process_vm_writev Restrict process inspection capabilities, already blocked by dropping CAP_SYS_PTRACE.
ptrace Tracing/profiling syscall. Blocked in Linux kernel versions before 4.8 to avoid seccomp bypass. Tracing/profiling arbitrary processes is already blocked by dropping CAP_SYS_PTRACE, because it could leak a lot of information on the host.
query_module Deny manipulation and functions on kernel modules. Obsolete.
quotactl Quota syscall which could let containers disable their own resource limits or process accounting. Also gated by CAP_SYS_ADMIN.
reboot Don’t let containers reboot the host. Also gated by CAP_SYS_BOOT.
request_key Prevent containers from using the kernel keyring, which is not namespaced.
set_mempolicy Syscall that modifies kernel memory and NUMA settings. Already gated by CAP_SYS_NICE.
setns Deny associating a thread with a namespace. Also gated by CAP_SYS_ADMIN.
settimeofday Time/date is not namespaced. Also gated by CAP_SYS_TIME.
stime Time/date is not namespaced. Also gated by CAP_SYS_TIME.
swapon Deny start/stop swapping to file/device. Also gated by CAP_SYS_ADMIN.
swapoff Deny start/stop swapping to file/device. Also gated by CAP_SYS_ADMIN.
sysfs Obsolete syscall.
_sysctl Obsolete, replaced by /proc/sys.
umount Should be a privileged operation. Also gated by CAP_SYS_ADMIN.
umount2 Should be a privileged operation. Also gated by CAP_SYS_ADMIN.
unshare Deny cloning new namespaces for processes. Also gated by CAP_SYS_ADMIN, with the exception of unshare --user.
uselib Older syscall related to shared libraries, unused for a long time.
userfaultfd Userspace page fault handling, largely needed for process migration.
ustat Obsolete syscall.
vm86 カーネルにおける x86 リアルモード仮想マシン。 CAP_SYS_ADMIN からも呼び出される。
vm86old カーネルにおける x86 リアルモード仮想マシン。 CAP_SYS_ADMIN からも呼び出される。

デフォルトの seccomp プロファイルがない状態での実行

コンテナーを実行する際にunconfinedを指定すれば、デフォルトの seccomp プロファイルをなしにして実行することができます。 profile.

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