新しいLinuxユーザーネームスペースの最初のプロセスはsetuid()を呼び出す必要がありますか?

新しいLinuxユーザーネームスペースの最初のプロセスはsetuid()を呼び出す必要がありますか?

私はLinuxユーザーの名前空間について学んでいますが、完全に明確ではない奇妙な動作を観察しました。

初期ユーザー名前空間に一連のUIDを作成し、newuidmapコマンドを使用して子ユーザー名前空間のUIDをこれらのUIDにマップすることができました。私の設定は次のとおりです。

$ grep '^woky:' /etc/subuid
woky:200000:10000
$ id -u
1000

次に、新しいユーザー名前空間を作成し、そのUIDスコープを親ユーザー名前空間[0-10000)にマップしてみました。[200000-210000)

  • 最初の端末:

    $ PS1='% ' unshare -U bash
    % echo $$
    1337
    % id
    uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
    
  • ターミナル2:

    $ ps -p 1337 -o uid
      UID
     1000
    $ newuidmap 1337 0 200000 10000
    $ ps -p 1337 -o uid
      UID
     1000
    
  • 最初の端末:

    % id
    uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
    

したがって、正常に完了しても、newuidmap新しいユーザーの名前空間の内側と外側のUIDは変更されません。

それから以下のような文を見つけました http://www.itinken.com/blog/2016/Sep/exploring-unprivileged-containers/これが私の目を開いた。以前のシナリオを試しましたが、test-unshare.pyコマンドの代わりに次のスクリプト(記事からインポートして少し変更しました)を使用しましたunshare

#!/usr/bin/python3
import os
from cffi import FFI
CLONE_NEWUSER = 0x10000000
ffi = FFI()
ffi.cdef('int unshare(int flags);')
libc = ffi.dlopen(None)

libc.unshare(CLONE_NEWUSER)
print("user id = %d, process id = %d" % (os.getuid(), os.getpid()))
input("Press Enter to continue...")
# The uid must be set to 0 to avoid loosing capabilities when creating the shell.
os.setuid(0)
os.execlp('/bin/bash', 'bash')
  • 最初の端末:

    $ python3 ./test-unshare.py
    user id = 65534, process id = 1337
    Press Enter to continue...
    
  • ターミナル2:

    $ ps -p 1337 -o uid
      UID
     1000
    $ newuidmap 1337 0 200000 10000
    $ ps -p 1337 -o uid
      UID
     1000
    
  • 最初の端末:

    <Enter>
    bash: /home/woky/.bashrc: Permission denied
    bash-4.4# id
    uid=0(root) gid=65534(nobody) groups=65534(nobody)
    
  • ターミナル2:

    $ ps -p 1337 -o uid
      UID
    200000
    

今、最初に予想したのと同じように見えます。ここで、最初の例では、UIDが変更されていない理由の私の理論は次のとおりです。

unshare呼び出された実行を最初に呼び出すexecve(2)必要はありません。これで、シェルは前述のようにすべての機能を失い、UIDを65534から変更することはできません。 2番目のケースでは、プロセスはUIDを0に変更し、Linuxはそれを新しい200000以上にマップします。ユーザーの名前空間(作成したとおり)。/bin/bashsetuid(2)user_namespaces(7)/proc/1337/uid_mapnewuidmapこれは、新しいユーザー名前空間の最初のプロセスがsetuid(START_UID)を呼び出す必要があることを意味します。それ以外の場合は65534以降に停止しますexecve(2)

そうなんですか?

この記事では、最初の例(最初の例のPythonコードと同じ)を紹介し、次のように読みます。

試してみると、シェルが実行される前にuidマッピングが設定されているため、実際にはうまく機能しないことがわかります。

ただし、マニュアルページの情報はこれらの結論を導くことができず、マニュアルページはsetuid(2)新しいユーザーネームスペースの最初のプロセスで呼び出されるべきであることを明示的に明示していません。

ただし、この場合、新しいユーザー名前空間のプロセスを呼び出す必要はありませんが、setuid(2)そのUIDが変更されました。

  • 最初の端末:

    $ PS1='% ' unshare -U bash
    % echo $$
    1337
    % id
    uid=65534(nobody) gid=65534(nobody) groups=65534(nobody)
    
  • ターミナル2:

    $ ps -p 1337 -o uid
      UID
     1000
    $ echo '500000 1000 1' >/proc/1337/uid_map
    $ ps -p 1337 -o uid
      UID
     1000
    
  • 最初の端末:

    % id
    uid=500000 gid=65534(nobody) groups=65534(nobody)
    

すべての状況を詳しく説明してください。

/etc/subuid私の旅は、このファイルの目的を理解しようとしたときに始まりました。 DockerとLXCはそれを使用しますが、それを説明する文書はほとんどありません。長すぎて話してすみません。理解するのに長い時間がかかりましたが、まだ完全に理解できていないので、私が知っている内容をここに集めてみました。

ボーナス:/etc/subuidユーザーの名前空間とどのように関連するのか、DockerとLXCがこれを必要とする理由、そしてLinuxディストリビューションで共通のインターフェースである理由を説明してください。マニュアルページは簡単で、インターネット上の記事はほとんどLXC / Dockerで何かを実行する方法を文書化します。 (実際の説明は にありますnewuidmap(1)。)

ベストアンサー1

見ているhttps://unix.stackexchange.com/a/110245/301641

この回答を見ると、一部のUIDがマッピングされていないため利用できないことがわかります。

ケース1:「(65534)nobody inside、1000(woky)outside」が初期値として使用されます。 newuidmap以降もマップは取得されません([outside200000、Outside210000)のみがマップされますが、Outside1000はマップされなければなりません。範囲外です。)だから何も変わらなかった。

ケース2:「(65534)nobody inside、1000(woky)outside」が初期値として使用されます。 newuidmap以降もマップは取得されません([outside200000、Outside210000)のみがマップされますが、Outside1000はマップされなければなりません。範囲外です。しかし、マップをインポートした後にsetuid(inside0)を設定すると(注:uid_mapに書き込む前にsetuidを設定できません)、マップにあるため、UIDはオーバーフロー値から通常のマッピング値(outside200000、inside0)に変更されますになります。

ケース 3: newuidmap がマッピングされた後 (outside1000 がマッピングされている) 初期値として「(65534)noy inside, 1000(woky) Outside」なので、UID はオーバーフロー値から一般マッピング値 (outside1000, inside500000) に変更されます。

おすすめ記事