1

Linux で名前空間を試しているので、debootstrap で作成された Debian Wheezy 環境を分離する小さな C プログラムを書いています。

sysv-init を正常に起動してログイン プロンプトを表示できましたが、システムをシャットダウンするか -9 init を強制終了して分離環境を閉じると、端末は制御端末がシェルに接続されていないように見える状態のままになります。具体的には、sudo を開始すると、端末が存在しないと不平を言います。

sudo の失敗ポイントを次のステートメントに絞り込みました。

open("/dev/tty", O_RDWR|O_NOCTTY);

エラーENXIO(つまり、「そのようなデバイスまたはアドレスはありません」)。

なぜこれが起こるのかを理解しようとしています.initのsetsid()システムコールに関連していると感じていますが、正確なシナリオを再現できなかったため、適切なテストケースを提供できません.

私にとって本当に奇妙に思えるのは、init (フォークされたプロセス、したがってシェルの子) が現在の端末から切り離されるだけでなく、GUI 端末までのプロセスのすべての階層が tty からも切り離されることです。それがどのように起こるのか理解できないようです。

さらに、異なるコマンド間にはいくつかの矛盾があります。

➜  namespaces  tty
/dev/pts/19
➜  namespaces  sudo -s
sudo: no tty present and no askpass program specified
➜  namespaces  ls -l /proc/$$/fd
total 0
lrwx------ 1 paris paris 64 gen 15 23:24 0 -> /dev/pts/19
lrwx------ 1 paris paris 64 gen 15 23:24 1 -> /dev/pts/19
lrwx------ 1 paris paris 64 gen 15 23:24 10 -> /dev/pts/19
lrwx------ 1 paris paris 64 gen 15 23:24 2 -> /dev/pts/19
➜  namespaces  

この状況についての手がかりは高く評価されます。

編集:「/dev/tty」のカーネル ソース コードを見ると、問題はカーネル側の char デバイスの参照カウントに関連していると思います。実際、「/dev/{console|tty0|tty1}」出力を現在の pty にリダイレクトするために、シェルの制御端末をコンテナーのマウントされた dev 内のデバイス ファイルにバインド マウントしました。

EDIT:Linuxカーネルでは、「tty_open_current_tty()」関数のこのステップでエラーが報告されているようです:

static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{
     struct tty_struct *tty;
     int retval;

     if (device != MKDEV(TTYAUX_MAJOR, 0))
         return NULL;

     tty = get_current_tty();
     if (!tty)
         return ERR_PTR(-ENXIO);
     ...
}

編集: 問題は、制御 tty を「盗む」という概念に関連しているようです。これは、TIOCSCTTY をコマンドとして、1 をパラメーターとして使用して、CAP_SYS_ADMIN機能およびioctl()tty ファイル記述子の呼び出しの下で実行できます ( tty_ioctl(4)を参照)。これを確認し、報告するためにテスト ケースを書きます。

4

2 に答える 2

1

さて、私は問題をうまく追跡することができました。

実際のコード例については、この要点を参照してください (コマンド/dev/pts/17の出力に置き換えてくださいtty)。

この問題は、sysvinitspawn()関数の次のステップに関連しています。

(void)ioctl(f, TIOCSCTTY, 1);

ioctl()私の場合、現在のプロセスの/dev/consoleバインドマウントである制御ttyを実際に盗んでいます。pty

于 2015-01-21T15:40:08.593 に答える