SECCOMP_MODE_FILTERを呼び出す前にno_new_privsを設定する必要があるのはなぜですか?

SECCOMP_MODE_FILTERを呼び出す前にno_new_privsを設定する必要があるのはなぜですか?

存在するマニュアルページ私は次の行を読んだ。

実際にシステムコールを行わずにゼロを返すのではなく、呼び出し元のユーザーIDをゼロ以外の値に設定するためにsetuid(2)を使用しようとします。

私は彼らが何を言いたいのか理解していません。誰でも私にこれを説明できますか?

ありがとうございます。

答え1

まず、seccomp(2)マンページの次の段落を参照してください。

SECCOMP_RET_ERRNO

この値を使用すると、フィルター戻り値の SECCOMP_RET_DATA 部分がシステム・コールを実行せずに、errno 値としてユーザー・スペースに渡されます。

したがって、seccompフィルタはカーネルを飛び越える代わりに、実際のシステムコールが実行されます。任意の値を返す到着〜であるふりをするシステムコールが実行され、指定された結果が生成されました。これも扱う成功結果、戻り値が0に設定されている場合。

libseccomp以下は、どのように動作するかを示すサンプルベースのプログラム()ですsec.c(簡潔にするために、すべてのエラーチェックは省略されています)。

#include <stdio.h>
#include <seccomp.h>

int main() {
    scmp_filter_ctx seccomp;

    seccomp = seccomp_init(SCMP_ACT_ALLOW);

    // Make the `openat(2)` syscall always "succeed".
    seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(0), SCMP_SYS(openat), 0);

    // Install the filter.
    seccomp_load(seccomp);

    FILE *file = fopen("/non-existent-file", "r");

    // Do something with the file and then perform the cleanup.
    // <...>

    return 0;
}

実行の追跡中にプログラムをコンパイルして実行すると、ファイルはファイルシステムには存在しませんが、システムopenat(2)コールが0を返したことがわかります(つまり、「実行」は成功しました)。/non-existent-file

$ gcc sec.c -lseccomp -o sec

# Run the program showing the openat(2) invocations and their results.
$ strace -e trace=openat ./sec
...
openat(AT_FDCWD, "/non-existent-file", O_RDONLY) = 0
...

# Ensure that the file does not exist.
$ stat /non-existent-file
stat: cannot stat '/non-existent-file': No such file or directory

それでは、seccompフィルタの機能を理解しました。あなたの質問で引用したフレーズのポイントに近づいてみましょう。 2つのことを考えてみましょう:

  • 権限のないプロセスは、一部のカーネルメカニズムを使用して権限を向上させることができます。
  • このメカニズムを使用して権限を付与するいくつかのツールがあります。一時的に限られた数のジョブにのみ使用できます。

典型的な例は、SUIDが所有するバイナリであるsudo(8)ユーティリティです。root権限のないプロセスのコンテキストでこれを実行すると、呼び出しプロセスに完全なスーパーユーザー権限(サンドボックスやコンテナなどの一部の特殊な場合を除く)が付与され、ファイルを調べて呼び出し側のユーザーがsudo(8)要求/etc/sudoersされた操作を実行できることを確認します。 。そうでsudo(8)あれば実行は継続され、そうでなければ実行は拒否されます。また、sudo(8)任意のユーザーに代わって実行できます。要求された操作を実行する前に、適切な資格情報を設定してください。

たとえば、/etc/sudoersファイルに次のレコードが含まれているとします。

testuser ALL=(anotheruser) NOPASSWD: /bin/bash

ユーザーは次のコマンドを使用して自分の代わりにシェルを実行testuserできます。anotheruser

sudo -u anotheruser -i /bin/bash

今話題に近づいています。testuser- 所有プロセスにseccompフィルタがインストールされ、実際に実行せずにカーネルをsetuid(2)ロールバックしてからsudo -u anotheruser -i /bin/bash?まあ、私たちは以下を見ることができます:

  • カーネルはsudo(8)バイナリのSUIDビットをチェックし、呼び出しプロセスの権限を適切に高めます。
  • sudo(8)実行が許可されていることを確認/etc/sudoersしてください。testuser/bin/bashanotheruser
  • 次に、プロセスの資格情報に対する適切な変更をsudo(8)呼び出し、その権限を「ダウングレード」します。setuid(2)
  • ユーザーがインストールしたseccompフィルタは、「ダウングレード」が完了したかのように自動的に成功を報告します。
  • sudo(8)次に、プロセスが実行を示し、実行を継続することanotheruserを信頼してください/bin/bash
  • setuid(2)フィルタでスキップして実際に実行されなかったので、実際にスーパーユーザー権限で実行しました!

setuid(2)したがって、権限のないユーザーがseccompフィルタをインストールできるようにした場合は、そのユーザーが呼び出しをトラップして特権資格情報を「ハイジャック」することもできます。一時的に高い権限で実行されるため、マンページに制限があります。

呼び出しスレッドのユーザー名前空間にCAP_SYS_ADMIN機能があるか、スレッドのno_new_privsビットが設定されている必要があります。

この文の最初の部分の意味は明らかです。CAP_SYS_ADMINプロセスに多数の権限を付与する能力なので、それを所有するプロセスがシステムに混乱を引き起こすほど強力であると仮定しても安全です。 2番目の部分はどうですか?

このno_new_privsビットはプロセスの属性であり、設定されている場合はカーネルに通知します。いいえSUIDビットなどの特権昇格メカニズムを使用すると(したがって、このような呼び出しはsudo(8)まったく機能しません)、このビットが設定されている特権のないプロセスがseccompフィルタを使用できるようにするのは安全です。そのプロセスが一時的に権限を上昇させることは不可能です。したがって、これらの権限を「奪う」方法はありません。

関連情報