RHEL10の仮想コンソールでsudo su -したときに、LANG=ja_JP.UTF-8になる

こんにちは、tukapiyoです。

RHEL10を導入後、仮想コンソール(TERM=linux)でsudo su -をした際に、LANG=ja_JP.UTF-8になってしまうことが分かりました。
仮想コンソールは標準では日本語が表示できないので、各種メッセージが文字化けしてしまいます。

RHEL9では問題なかったことから原因を調査したところ、原因が特定できたので結果をまとめておきます。

環境

  • RHEL 10.0 Coughlan
  • localectlの結果
    $ localectl
    System Locale: LANG=ja_JP.UTF-8
    VC Keymap: jp
    X11 Layout: jp
    X11 Model: microsoftpro
    X11 Options: terminate:ctrl_alt_bksp
    

発生事象

当該サーバの状況(RHEL10)

  • 仮想コンソール(TERM=linux)で一般ユーザにログイン
    LANG=en_US.UTF-8 (想定通り)
  • そのままsudo su -でrootにスイッチ
    LANG=ja_JP.UTF-8 (想定外)

この状態で例えばnmtuiを実行してみると、たくさん豆腐が見えます。

他サーバの状況(RHEL9)

  • 仮想コンソール(TERM=linux)で一般ユーザにログイン
    LANG=en_US.UTF-8 (想定通り)
  • そのままsudo su -でrootにスイッチ
    LANG=en_US.UTF-8 (想定通り)

そもそもなぜLANG=en_US.UTF-8になっているか

localectlではLANG=ja_JP.UTF-8に設定されているのに、なぜLANG=en_US.UTF-8になるのでしょうか。
実はSSHで接続した場合はLANG=ja_JP.UTF-8になります。

この件は過去に調査したことがあり、以下の記事でも説明しています。

記事内のこの部分が該当の説明です。

ログイン時に/etc/profileが読み込まれます(詳細は割愛)。
その中でさらに、/etc/profile.d/*を読み込むようになっていました。

/etc/profile.d/の中には複数のシェルスクリプトが含まれていますが、そのうちlang.shを参照するとLANG=en_US.UTF-8を設定している行が見つかります。
$TERMlinux(コンソール)の場合に、LANG=en_US.UTF-8を設定するようになっていますね。
おそらく、コンソールでは日本語等の文字が表示できない(文字化けする)ため、あえて英語ロケールへ変更するようにしているのでしょう。

ということで、仮想コンソールの場合はLANG=en_US.UTF-8となるのが想定通りなのです。

原因調査

lang.sh

最も怪しいlang.shについては、RHEL9もRHEL10も差分はありませんでした。
そこで、中身をもう少し見てみることにします。

以下のコードは、lang.shの抜粋です。
ちょうどLANG=en_US.UTF-8に書き換える処理の部分になります。

# The ${LANG} manipulation is necessary only in virtual terminal (a.k.a. console - /dev/tty*):
if [ -n "${LANG}" ] && [ "${TERM}" = 'linux' ] && /usr/bin/tty | /usr/bin/grep --quiet -e '/dev/tty'; then
    if /usr/bin/grep --quiet -E -i -e '^.+\.utf-?8$' <<< "${LANG}"; then
        case ${LANG} in
            ja*)    LANG=en_US.UTF-8 ;;
(..snip..)

2行目を読むと以下の3つの条件でLANG=en_US.UTF-8に設定されることが分かります。

  1. $LANGが設定されている
  2. TERM=linuxである
  3. ttyコマンドの結果が/dev/ttyを含む

1つめ、2つめは問題ないことがこれまでの結果から判明しています。
3つめがまだ確認できていませんので、確認をしてみます。

tty

ttyコマンドは、今使っている端末が何かを表示します。
仮想コンソールの場合は、/dev/tty0~が使われます(そのうち、X Window Systemは、/dev/tty7~を使います)。
端末アプリケーションやSSHなどは、疑似端末(pseudo-terminal)の/dev/pts/0~が使われます。

つまり、「ttyコマンドの結果が/dev/ttyを含む」というのは仮想コンソールであることを示します。

では実際に仮想コンソールからttyコマンドの結果を確認してみましょう。

RHEL10のtty

  • 仮想コンソール(TERM=linux)で一般ユーザにログインし、ttyコマンドを実行
    /dev/tty1
  • そのままsudo su -でrootにスイッチし、ttyコマンドを実行
    /dev/pts/2
  • 一般ユーザに戻って、sudo ttyコマンドを実行
    /dev/pts/2

RHEL9のtty

  • 仮想コンソール(TERM=linux)で一般ユーザにログインし、ttyコマンドを実行
    /dev/tty1
  • そのままsudo su -でrootにスイッチし、ttyコマンドを実行
    /dev/tty1
  • 一般ユーザに戻って、sudo ttyコマンドを実行
    /dev/tty1

おや、RHEL10ではsudoした際のttyが疑似端末の/dev/pts/2という扱いになってしまいました。
これが怪しそうです。

そこで次はsudoについて調べてみます。

sudo

RHEL10側のマニュアルを色々と確認していると、sudoers(5)のマニュアルに気になる記載を見つけました。

use_pty

If set, and sudo is running in a terminal, the command will be run in a new pseudo-terminal. If the sudo process is not attached to a terminal, use_pty has no effect.

A malicious program run under sudo may be capable of injecting commands into the user’s terminal or running a background process that retains access to the user’s terminal device even after the main program has finished executing. By running the command in a separate pseudo-terminal, this attack is no longer possible. This flag is on by default for sudo 1.9.14 and above.

“If set, and sudo is running in a terminal, the command will be run in a new pseudo-terminal.”と書かれています。
意訳するとuse_ptyを使うと、sudoは疑似端末(pseudo-terminal)で実行されるということです。
挙動を踏まえるに、このオプションは最重要容疑者です。

もっと注目すべき点は、”This flag is on by default for sudo 1.9.14 and above.”という記載。
つまりsudo 1.9.14以上ではデフォルトで設定されるよ、とのこと。
おっとー?バージョンで挙動変わるなんて、より怪しい匂いがプンプンするぜ。

ということで、バージョンを確認してみましょう。

RHEL10のsudo

$ sudo -V
Sudo バージョン 1.9.15p5

RHEL9のsudo

$ sudo -V
Sudo バージョン 1.9.5p2

はい、RHEL10でバージョンが1.9.15p5(1.9.14以上)になっています。
この違いが、ttyの差、ひいては$LANGの差に繋がっている可能性が高いですね。

解決

原因の目星は付きました。
sudouse_ptyを無効にして様子を確認してみます。

sudoersの設定を変更するにあたって、/etc/sudoersファイルを編集しても良いですが、今回は/etc/sudoers.d/配下にファイルを作成する形にします。
以下の様に/etc/sudoers.d/use_ptyを作成しつつ、use_ptyを無効にします。

# visudo -f /etc/sudoers.d/use_pty
Defaults !use_pty

この状態で、改めて仮想コンソールから状況を確認してみましょう。

このように、sudoをしてもttyが仮想コンソール(/dev/tty1)になり、LANG=en_US.UTF-8が設定されるようになりました。
まさしくuse_ptyが原因だったようです。

まとめ

今回の事象は、sudoのデフォルトの挙動が変わったことが原因でした。
マニュアルにも書かれているとおり、セキュリティの理由でデフォルト値が変わっていることもありますので、セキュリティとのトレードオフを検討した上で設定を変更するようにして下さい。

おすすめ

コメントを残す

Amazon プライム対象