システムコールのインターセプション#

LXD では非特権コンテナで、いくつか特定のシステムコールをインターセプトできます。もし、それが安全であると見なせるのであれば、ホスト上で特権を昇格させて実行します。

これを行うことで、対象のシステムコールではパフォーマンスに影響があり、LXD ではリクエストを評価するための作業が必要となり、もし許可されれば昇格した特権で実行されます。

特定のシステムコールインターセプションのオプションの有効化はコンテナの設定オプションを使ってコンテナ単位で行われます。

利用できるシステムコール#

mknodmknodat システムコールを使用して、色々なスペシャルファイルを作成できます。

もっとも一般的にはコンテナ内部で、ブロックデバイスやキャラクターデバイスを作成するために呼び出されます。このようなデバイスを作成することは、非特権コンテナ内では許可されません。これは、ディスクやメモリのようなリソースに直接書き込みのアクセスを許可することになり、特権を昇格するのに非常に簡単な方法であるためです。

しかし、作成しても安全であるファイルもあります。このような場合に、システムコールをインターセプトすることで、特定の処理のブロックが解除され、非特権コンテナ内部で実行できるようになります。

現時点で許可されているデバイスは次のものです:

  • overlayfs whiteout (char 0:0)

  • /dev/console (char 5:1)

  • /dev/full (char 1:7)

  • /dev/null (char 1:3)

  • /dev/random (char 1:8)

  • /dev/tty (char 5:0)

  • /dev/urandom (char 1:9)

  • /dev/zero (char 1:5)

キャラクターデバイス以外のすべてのファイルタイプは、現時点では通常通りカーネルに送られるので、この機能を有効にしても動作は全く変わりません。

この機能は security.syscalls.intercept.mknodtrue に設定することで有効に出来ます。

bpf#

カーネル内の eBPF プログラムを管理するために bpf システムコールを使用します。 これらは様々なカーネルサブシステムにアタッチされます。

一般に、信頼していない eBPF プログラムをロードするのはタイミングベースの攻撃を 容易にするので問題です。

LXD の eBPF サポートは現在のところデバイスの cgroup エントリを管理するプログラムに 限定しています。有効にするには security.syscalls.intercept.bpfsecurity.syscalls.intercept.bpf.devices の両方を true に設定する必要があります。

mount#

`mount システムコールは物理と仮想ファイルシステムの両方のマウントを可能にします。 デフォルトでは、非特権コンテナはカーネルにより制限され、いくつかの仮想とネットワーク ファイルシステムのみに限定されています。

物理ファイルシステムをマウントできるようにするにはシステムコールインターセプションが使えます。 LXD はこれを取り扱うために様々な選択肢を提供しています。

security.syscalls.intercept.mount は全体の機能を制御するのに使用され、 他のいずれかの選択肢を機能させるためには有効にする必要があります。

security.syscalls.intercept.mount.allowed はコンテナ内に直接マウント可能な ファイルシステムのリストを指定できます。 これはユーザが信頼できないデータをカーネルに送り込むことを許すため 最も危険な選択肢です。 これにより簡単にホストシステムをクラッシュさせたり攻撃が出来てしまいます。 そのため信頼された環境でのみ使うようにすべきです。

security.syscalls.intercept.mount.shift は上記に加えてコンテナで使用される UID/GID マップでマウントした結果をシフトさせるのに使用できます。 これは非特権コンテナ内で全てが nobody/nogroup として表示されるのを回避するために必要です。

これらよりもっと安全な代替は security.syscalls.intercept.mount.fuse で ファイルシステムの名前と FUSE ハンドラの組を指定できます。 これが設定されると指定されたファイルシステムのどれかをマウントしようとすると そのファイルシステムに対応する FUSE ハンドラ呼び出しにリダイレクトされます。

これは全て呼び出し側として実行されるので、カーネルのアタックサーフェスに まつわる全ての問題を回避し、そのため一般的に安全と考えられます。 しかし、あらゆる種類のシステムコールインターセプションはホストシステムに 過大な負荷をかける簡単な方法になることを留意しておくべきです。

sched_setscheduler#

sched_setscheduler システムコールはプロセスの優先度を管理するのに使えます。

これを許可するとユーザが自分のプロセスの優先度を著しく上げることを許すため、 潜在的に多くのシステムリソースを使われることになります。

これはまた SCHED_FIFO のようなスケジューラへのアクセスを許すので、 一般的には欠陥と考えられ、システム全体の安定性に著しく影響を与える可能性があります。 このため通常の状況下では、真の root ユーザ (あるいはグローバルの CAP_SYS_NICE) のみがこれの使用を許すべきです。

setxattr#

setxattr システムコールは、拡張ファイル属性を設定するのに使われます。

現時点で、これにより処理される属性は次のものです:

  • trusted.overlay.opaque (overlayfs directory whiteout)

この介入は多数の文字列で行う必要があるため、現在のところ、対象の少数の属性のみインターセプトする簡単な方法がありません。上記の属性のみを許可しているため、カーネルが以前に許可していた他の属性を破損する可能性があります。

この機能は security.syscalls.intercept.setxattrtrue に設定することで有効にできます。

sysinfo#

sysinfo システムコールはいくつかのディストリビューションでリソース使用量を報告するのに /proc/ エントリーの代わりに使用されます。

システム全体ではなく個々のコンテナのリソース使用情報を提供するために、このシステムコール・インターセプションモードはシステムコールのレスポンスに cgroup ベースのリソース使用情報を設定します。