VirtualBox + CentOS でログイン画面が表示されない時の対処法

はじめに

実務にて、macOS + VirtualBox の CentOS を起動するとログイン画面が表示されず YouTube のグルグルのような感じで永遠に読み込み中の状態になってしまった、それを解決した情報になります。

下記画像は読み込み中画面にて 、又は esc キー押下後のブートシーケンスです。

発生していたエラーは下記の 6 点です。

  1. [FAILED] Failed to start Login Service.
  2. [FAILED] Failed to start Authorization Manager.
  3. [DEPEND] Dependency failed for Dynamic System Tuning Daemon.
  4. [FAILED] Failed to start Accounts Service.
  5. [FAILED] Failed to start Modem Manager.
  6. [FAILED] Failed to start RealtimeKit Scheduling Policy Service.

ssh コマンドによるログインは失敗する、且つ CentOS のカーネルバージョンを切り換えて起動しても現象は発生する状態です。

環境

解説

結論から言うと、SELinux(Security-Enhanced Linux)を無効にすることで解決しました。

初めに、GRUB(Grand Unified Bootloader)メニューにて e キーを押下して設定ファイル(/boot/grub2/grub.cfg)を開きます。

GRUB とは ブートローダー のことです。ブートローダーとは BIOS(Basic Input/Output System)が 補助記憶装置 から呼び出す OS(Operating System)を動かすプログラムのことです。

…厳密に説明すると長くなっちゃうので省略しますね、下記画像が GRUB メニューです。

e キーを押下すると下記のような画面が表示されます。

キーを入力して下方にカーソルを移動させると行頭で linux16 /vmlinuz-... と書かれた行があるので、行末に rw init=/bin/sh と書き加え control + x キーを押下して シングルユーザーモード を起動します。

= は隣にある ^ キーを押下すると入力できます。

rw init=/bin/sh

下記のような Bourne Shell を実行できる画面が表示されます。

vi コマンドで SELinux の設定ファイルを編集します。

vi /etc/selinux/config

i キーで入力モードに切り替えて、赤枠の SELINUX の設定値を disabled に書き換えます。スペルミスや大文字入力、SELINUXTYPE の行と間違えないようにしましょう、設定を間違えると カーネルパニック が発生する可能性があります。

次は esc キーでコマンドモードに切り換え :wq コマンドを実行して上書き保存して vi を終了します。

私の場合は SELINUXdisables に設定されていたのでエラーが発生していました。d をつけろよデコ助野郎!

最後に exce コマンドで /sbin/init をオーバーレイします。

exec /sbin/init

これでログイン画面が表示されると思います、ssh コマンドでログインもできるようになりました。

それでも解決しない場合は、下記の対処法で解決できるかもしれません。

  1. 仮想マシンの設定画面からストレージタブを選択して、ストレージデバイスを確認すると CentOS の iso をマウントしたままになっていたので割り当てを除去する。
  2. 仮想マシンの設定画面からディスプレイタブを選択して、グラフィックスコントローラーで VMAVGA を選択する。

また、SELinux の設定ファイルに書き間違いがあった場合は下記の状態でフリーズすることがあります。

因みに、今回のような現象が発生する場合は監査ログ(/var/log/audit/audit.log)を調査すると原因を特定することができます。

ausearch -m avc コマンドを実行すると監査ログの AVC 拒否メッセージを確認することができます。AVC(Access Vector Cache)とは SELinux のアクセスに対する判断のキャッシュのことです。

ausearch -m avc

例えば、下記のようなメッセージが記録されています。

type=AVC msg=audit(1635956322.813:137):
avc:  denied  { read } for  pid=1399
comm="lpqd"
name="cups.sock"
dev="tmpfs"
ino=16199
scontext=system_u:system_r:smbd_t:s0
tcontext=system_u:object_r:cupsd_var_run_t:s0
tclass=sock_file permissive=1

各フィールドの値を簡単に説明します。

  • type=AVC : レコードの種類です。
  • msg=audit(1635956322.813:137) : UNIX時間 です。
  • avc: denied : AVC 拒否しています。
  • { read } : パーミッションは read(読み取り)です。
  • for pid=1399 : プロセス ID です。
  • comm="lpqd" : 使用コマンドです。
  • name="cups.sock" : システムコールに引数として cups.sock を渡しています。
  • dev="tmpfs" : デバイスです。
  • ino=16199 : inode 番号です。
  • scontext=system_u:system_r:smbd_t:s0 : アクセス元のプロセスのコンテキストです。ユーザー(system_u)、ロール(system_r)、タイプ(smbd_t)に区切られています。
  • tcontext=system_u:object_r:cupsd_var_run_t:s0 : アクセス先のオブジェクトのコンテキストです。
  • tclass=sock_file : アクセス先のオブジェクトのクラスは sock_file です。

要約すると lpqd による cups.sock への読み取りアクセスを拒否しているということです。

root ユーザーでログインして find コマンドで inode 番号を指定して検索すると関連するファイルを見つけることができるかもしれません。

例えば、下記のコマンドは ino=16199 を検索します。

find / -inum 16199

また、audit2allow コマンドを利用して監査ログから拒否理由、解決方法などを出力することもできます。例えば、下記のコマンドは lpqd の AVC 拒否メッセージの解決方法を表示します。

ausearch -m avc | audit2allow -M lpqd

SELinux=permissive(SELinux ポリシーを強制しないが監査ログに記録してアクセスを許可するモード)に切り換えると現象が発生する場合は、SELinux ポリシーを削除している可能性があります。

シングルユーザーモードから rpm -qa | grep selinux コマンドを実行することで selinux-policy の存在を確認することができます。

selinux-policy が存在しない場合は、誰かが SELinux ポリシーを削除しちゃったかもしれないですね。

具体的な解決例については、本題よりも文章が多くなってしまうので別の記事で纏められればと思います。

以上です。

おわりに

SELinux は不正侵入による情報漏洩の被害を抑える素敵なセキュリティ標準機能ですが、一般ユーザーの利便性に欠ける部分があってとりあえず無効化、又は Permissive モードに設定されていることがあります。

確かに有効化するのが理想的だけど、SELinux が絶対に必要でない、且つ過剰セキュリティが慣れていない開発者の時間をたくさん奪うのであれば無効化で良いと思います。