Linux 名前空間ユーザーの詳細な説明

Linux 名前空間ユーザーの詳細な説明

ユーザー名前空間は Linux 3.8 で追加された新しい名前空間で、ユーザー ID やグループ ID、キー、機能などのセキュリティ関連のリソースを分離するために使用されます。同じユーザーのユーザー ID とグループ ID は、異なるユーザー名前空間では異なる場合があります (PID 名前空間と同様)。つまり、ユーザーは、あるユーザー名前空間では通常のユーザーである一方、別のユーザー名前空間ではスーパーユーザーである可能性があります。

ユーザー名前空間はネストできます (現在、カーネルは最大 32 層を制御します)。システムのデフォルトのユーザー名前空間を除き、すべてのユーザー名前空間には親ユーザー名前空間があり、各ユーザー名前空間には 0 個以上の子ユーザー名前空間を含めることができます。 プロセス内で unshare または clone が呼び出されて新しいユーザー名前空間が作成されると、現在のプロセスの元のユーザー名前空間が親ユーザー名前空間になり、新しいユーザー名前空間が子ユーザー名前空間になります。

注: この記事のデモ環境は Ubuntu 16.04 です。

ユーザー名前空間を作成する

unshare コマンドの --user オプションを使用して、新しいユーザー名前空間を作成できます。

$ unshare -user -r /bin/bash 

-r パラメータを使用して、新しいユーザー名前空間のルート ユーザーを外部ニックネーム ユーザーにマッピングします (マッピングに関連する概念については次に説明します)。新しいユーザー名前空間では、ルート ユーザーに、uts 名前空間などの他の名前空間を作成する権限が与えられます。これは、現在の bash プロセスにすべての機能があるためです。

新しい uts 名前空間を作成して試してみましょう。

$ unshare --uts /bin/bash 

新しい uts 名前空間が正常に作成されたことがわかります。これは、ユーザー名前空間を除き、他のタイプの名前空間を作成するには CAP_SYS_ADMIN 機能が必要になるためです。新しいユーザー名前空間が作成され、uid と gid がマップされると、このユーザー名前空間の最初のプロセスは完全な機能をすべて持つようになり、他のタイプの新しい名前空間を作成できるようになります。

実際、上記の操作 (2 つの名前空間の作成) を 2 つのステップに分割する必要はありません。unshare を使用すると、一度に複数の名前空間を作成できます。

unshare の実装では、実際には CLONE_NEWUSER | CLONE_NEWUTS が渡されます。これはおおよそ次のようになります。

共有を解除します(CLONE_NEWUSER | CLONE_NEWUTS);

上記の場合、カーネルは CLONE_NEWUSER が最初に実行されることを確認し、次に残りの CLONE_NEW* を実行します。これにより、ルート ユーザーを使用せずに新しいコンテナを作成できます。このルールはクローン機能にも適用されます。

UIDとGIDのマッピングを理解する

前回のデモでは、ユーザー名前空間間のユーザーのマッピングについて説明しました。今度は同じデモを使用して、マッピングが何であるかを理解しましょう。まず、現在のユーザーの ID とユーザー名前空間を確認しましょう。

次に、unshare --user /bin/bash コマンドを実行して、新しいユーザー名前空間を作成します。今回は -r パラメータがないことに注意してください。

$ unshare --user /bin/bash 

新しいユーザー名前空間では、現在のユーザーは nobody になり、ID は 65534 になります。

これは、親ユーザー名前空間のユーザー ID とグループ ID を子ユーザー名前空間にまだマッピングしていないためです。この手順は、システムが 1 つのユーザー名前空間のユーザーの権限を他のユーザー名前空間で制御できるようにするために必要です (他のユーザー名前空間のプロセスにシグナルを送信したり、他のユーザー名前空間にマウントされたファイルにアクセスしたりするなど)。

マッピングがない場合、getuid() および getgid() を使用して新しいユーザー名前空間のユーザー ID とグループ ID を取得すると、システムはファイル /proc/sys/kernel/overflowuid で定義されたユーザー ID と proc/sys/kernel/overflowgid で定義されたグループ ID を返します。どちらのデフォルト値も 65534 です。つまり、マッピングが指定されていない場合、ID はデフォルトで 65534 にマッピングされます。

次に、新しいユーザー名前空間でのニックネーム ユーザーのマッピングを完了します。

ID をマッピングする方法は、/proc/PID/uid_map ファイルと /proc/PID/gid_map ファイルにマッピング情報を追加することです (ここで、PID は新しいユーザー名前空間のプロセス ID であり、両方のファイルは最初は空です)。これら 2 つのファイル内の構成情報の形式は次のとおりです (各ファイルには複数の構成情報を含めることができます)。

ID-inside-ns ID-outside-ns 長さ

たとえば、構成 0 1000 500 は、親ユーザー名前空間の 1000 ~ 1500 が新しいユーザー名前空間の 0 ~ 500 にマップされることを意味します。

uid_map ファイルと gid_map ファイルの書き込み操作には、厳密な権限制御があります。簡単に言うと、これら 2 つのファイルの所有者は、新しいユーザー名前空間を作成したユーザーであるため、このユーザーと同じユーザー名前空間内の root アカウントは、これらのファイルに書き込むことができます。このユーザーがマップ ファイルに書き込む権限を持っているかどうかは、CAP_SETUID および CAP_SETGID 機能を持っているかどうかによって決まります。注: マップ ファイルにデータを書き込むことができるのは 1 回だけですが、一度に複数のエントリを書き込むことができ、エントリの最大数は 5 です。

開いたばかりのシェル ウィンドウを最初のシェル ウィンドウとして呼び出し、ユーザー マッピング操作 (新しいユーザー名前空間でユーザー ニックネームをルートにマップする) の実行を開始します。

最初のステップは、最初のシェル ウィンドウで現在のプロセスの ID を確認することです。

2 番目のステップは、新しいシェル ウィンドウ (2 番目のシェル ウィンドウと呼ぶ) を開くことです。プロセス 3049 のマッピング ファイルのプロパティを表示します。

ユーザー nick はこれら 2 つのファイルの所有者です。これら 2 つのファイルにマッピング情報を書き込んでみましょう。

自分がファイルの所有者なのに、ファイルに書き込む権限がないのは奇妙に思えます。実際、根本的な理由は、現在の bash プロセスに CAP_SETUID および CAP_SETGID 権限がないことです。

次に、/bin/bash プログラムの関連する機能を設定します。

次のようにコードをコピーします
$ sudo setcap cap_setgid、cap_setuid+ep /bin/bash

$ sudo setcap cap_setgid、cap_setuid+ep /bin/bash

次に bash をリロードすると、対応する機能が表示されます。

次に、マッピング情報をマップ ファイルに書き換えます。

$ エコー '0 1000 500' > /proc/3049/uid_map
$ エコー '0 1000 500' > /proc/3049/gid_map

今回は書き込みが成功しました。後でマッピング情報を手動で書き込む必要はないので、次のコマンドを使用して /bin/bash の機能を元の設定に戻します。

$ sudo setcap cap_setgid,cap_setuid-ep /bin/bash 

ステップ3: 最初のシェルウィンドウに戻る

bash をリロードし、id コマンドを実行します。

現在のユーザーは root (新しいユーザー名前空間の root ユーザー) になりました。現在の bash プロセスの機能を見てみましょう。

0000003fffffffff は、現在実行中の bash がすべての機能を持っていることを意味します。

ステップ4. 最初のシェルウィンドウで

/root ディレクトリのアクセス権限を確認します。

許可なし!ホスト名を変更してみてください:

まだ許可が出ません!この新しいユーザー名前空間のルート ユーザーは、親ユーザー名前空間では機能しないようです。これはまさに、ユーザー名前空間が期待する効果です。他のユーザー名前空間のリソースにアクセスする場合、アクセスを実行するために権限が使用されます。たとえば、root の親ユーザー名前空間に対応するユーザーは nick であるため、システムのホスト名を変更することはできません。

通常ユーザー nick にはホスト名を変更する権限がありません。では、デフォルトユーザー名前空間の root ユーザーをサブユーザー名前空間の root ユーザーにマッピングした後、ホスト名を変更することはできますか?答えはノーです!これは、マッピングがどのように実行されたとしても、子ユーザー名前空間のユーザーが親ユーザー名前空間のリソースにアクセスする場合、そのユーザーが開始するプロセスの機能は空であるため、子ユーザー名前空間のルート ユーザーは親ユーザー名前空間の通常のユーザーと同等になるためです。

ユーザー名前空間と他の名前空間の関係

Linux の各名前空間は、ユーザー名前空間に関連付けられています。このユーザー名前空間は、対応する名前空間が作成されたときにプロセスが属するユーザー名前空間です。これは、各名前空間に所有者 (ユーザー名前空間) があることと同じです。これにより、任意の名前空間での操作がユーザー名前空間の権限によって制御されることが保証されます。これは、変更する uts 名前空間が親ユーザー名前空間に属しており、新しいユーザー名前空間のプロセスには古いユーザー名前空間の機能がないため、子ユーザー名前空間でホスト名を設定すると失敗する理由でもあります。

uts 名前空間を例にとると、uts_namespace 構造体にはユーザー名前空間へのポインターがあり、それが属するユーザー名前空間を指します (私が確認した v4.13 カーネルでは、uts_namespace 構造体の定義は /include/linux/utsname.h ファイルにあります)。

他の名前空間の定義も同様です。

要約する

他の名前空間と比較すると、ユーザー名前空間は少し複雑です。これは機能性によるもので、権限管理に関しては直感的ではない傾向があります。この記事では、ユーザー名前空間の基本的な概念についてのみ紹介しました。他にも興味深い内容が数多くありますので、ぜひご覧ください。

参照:

ユーザー名前空間のマニュアルページ
名前空間の運用、パート 5: ユーザー名前空間
名前空間の運用、パート 6: ユーザー名前空間についてさらに詳しく
Linuxの機能

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Docker の基礎: Linux 名前空間のグラフィック説明

<<:  Vueはボタン切り替え画像を実装します

>>:  MySQL がテーブルを読み取れないエラー (MySQL 1018 エラー) の解決方法

推薦する

MySQL/MariaDB で完全な Unicode をサポートする方法

目次utf8mb4 の紹介UTF8 バイト数超過エラーutf8mb4 サポートデフォルトの文字エンコ...

Vueはタブを切り替えてデータの状態を維持する3つの方法を実装します

Vue でタブ切り替えを実装する 3 つの方法1. v-showはコンテンツの切り替えを制御します1...

reactにおけるstateの略語の詳細な説明

序文国家とは何か私たちは皆、React はステート マシンであると言います。それはどのように反映され...

Mysql5.6.36 スクリプトのコンパイル、インストール、初期化のチュートリアル

概要この記事は、centos7.3 上で mysql5.3.6 を自動的にコンパイルしてインストール...

Linux での umask の使用に関する詳細な説明

私は最近 Linux を学び始めました。Ma Ge の umask に関する Linux コースを読...

Dockerコンテナの紹介

Dockerの概要Docker はオープンソースのソフトウェア展開ソリューションです。 Docker...

CSS スタイル分類入門(基礎知識)

CSSスタイルの分類1. 内部スタイル ---- インラインスタイルスタイルタグの使用 <ス...

1 つ以上のフィールドに基づいて重複データを検索する MySQL SQL ステートメント

SQLはテーブル内の重複レコードをすべて見つけます1. テーブルには id と name の 2 つ...

Gokudōゲームにおけるフロントエンド知識のまとめ

背景日本語を学び始めた当初は、日本語の50音を覚えるのは簡単ではなく、特にカタカナを覚えるのは困難で...

Docker で Let's Encrypt から永久無料 SSL 証明書を取得する方法

1. 原因公式の cerbot は面倒すぎます。野生の成長よりもさらに悪い acme.sh の使用は...

独自の Docker イメージを作成して Dockerhub にアップロードする方法

1. まず、自分のdockerhubアカウントを登録します。登録アドレス: https://hub....

Nginx ドメイン転送の使用シナリオ コード例

シナリオ 1: サーバーの制限により、外部に開かれているポートは 1 つだけですが、別の外部ネットワ...

mysql5.7.18 のインストール時にエントリが見つからない問題の解決方法

mysql5.7.18のインストール時に次の問題が発生しました: プログラム入力ポイントfesetr...

Nginx+Tomcat 負荷分散クラスタのインストールと構成のケースの詳細な説明

目次序文1. Nginx+Tomcat 2. Nginxサーバーを構成する3. Tomcatアプリケ...

CSS 動的読み込みバー効果のサンプルコード

CSS変数の知識を使って、追加したコードとコメントを直接投稿します <!DOCTYPE htm...