Login
Immutable PageDiscussionInfoAttachments
ytoku/daily-record/2011-03-06

MMA

ping: IDN encoding of 'hostname' failed with error code 9

新たにインストールしたScientif Linux 6環境では/etc/sysconfig/i18nLANG="ja_JP.eucJP"と設定を変更してあるが、 この設定でping hostnameコマンドを実行すると

-bash-4.1$ ping nest
ping: IDN encoding of 'nest' failed with error code 9

というエラーが返ってくる。rendaさんが調べてみたところ

と言うことがわかった。エラーメッセージで検索するとrpms/iputils/devel iputils-20070202-idn.patch, NONE, 1.1 iputils.spec, 1.46, 1.47のパッチで追加された部分がエラーを出しているようだ。ping6が動作するのはIDNの処理がpingにしか追加されていないからだとわかった。

-bash-4.1$ ldd /bin/ping
        linux-gate.so.1 =>  (0x0076c000)
        libidn.so.11 => /lib/libidn.so.11 (0x0063e000)
        libc.so.6 => /lib/libc.so.6 (0x00a5d000)
        /lib/ld-linux.so.2 (0x00a3b000)
-bash-4.1$ ldd /bin/ping6
        linux-gate.so.1 =>  (0x007cc000)
        libc.so.6 => /lib/libc.so.6 (0x00a5d000)
        /lib/ld-linux.so.2 (0x00a3b000)

エラーが出ているのはidna_to_ascii_lzIDNA_ICONV_ERRORを返している (存在しないホスト名でも同じエラーが出るのでidna_to_unicode_lzlzではない)からなので、 libidnのソースを追いかけてみるとstringprep_locale_to_utf8NULLを返しているようだ。 普通に_LIBCは定義されている環境のはずなのでstringprep_locale_charsetnl_langinfo(CODESET)で置き換えられて"EUC-JP"が返るはず1である。 よってstr_iconv(str, "EUC-JP", "UTF-8")の実行結果が返ることがわかった。

ではstr_iconvに問題があるのかとlibidnのソースにあったテストコードに追記をして実行をしてみたのだが動いてしまった。 全体を./configure --disable-csharp --disable-static --libdir=/libして libidn-1.18/lib/gltestsに対して次のコードを追加、 make test-striconv./test-striconv && echo okで行った。

  /* Test conversion from EUC-JP to UTF-8 with no errors.  */
  {
    static const char input[] = "\xa4\xdb\xa4\xb2";
    static const char expected[] = "\xe3\x81\xbb\xe3\x81\x92";
    char *result = str_iconv (input, "EUC-JP", "UTF-8");
    ASSERT (result != NULL);
    ASSERT (strcmp (result, expected) == 0);
    free (result);
  }

どうしたものかとpingコマンドをstraceしてみたところ

-bash-4.1$ strace ping nest 2>&1 | less
...
open("/usr/lib/gconv/EUC-JP.so", O_RDONLY) = 3
...
open("$ORIGIN/tls/i686/sse2/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/tls/i686/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/tls/sse2/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/tls/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/i686/sse2/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/i686/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/sse2/libJIS.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("$ORIGIN/libJIS.so", O_RDONLY)     = -1 ENOENT (No such file or directory)
...

などという出力が得られた。何じゃこりゃ。ファイルパスの中に$ORIGINなどと紛れ込んでいたらそれは見つからないわ。 このファイル自体はEUC-JP.soと同じディレクトリにあるので$ORIGIN/usr/lib/gconvに展開されれば良いのだろう。 先ほどの動作したテストコードを実行してみても

-bash-4.1$ strace ./test-striconv 2>&1 | less
...
open("/usr/lib/gconv/EUC-JP.so", O_RDONLY) = 3
...
open("/usr/lib/gconv/libJIS.so", O_RDONLY) = 3
...

と同じディレクトリにあるlibJIS.soを発見できるのが正常であることがわかる。

$ORIGINという文字列は確かにEUC-JP.soの中にあるようだ。

-bash-4.1$ strings /usr/lib/gconv/EUC-JP.so | grep ORIGIN
$ORIGIN

このファイルはどこのパッケージからやってきたかというとglibcであった。

-bash-4.1$ rpm -qf /usr/lib/gconv/EUC-JP.so
glibc-2.12-1.7.el6_0.3.i686

そこで次はglibcのsrc.rpmから追いかけてみることにする。 specファイルを眺めていると

* Mon Oct 18 2010 Andreas Schwab <schwab@redhat.com> - 2.12-1.7.el6_0.2
- Never expand $ORIGIN in privileged programs (#643821)

あー……pingってsuid-bitが立ってるんだったよねーたしか。

-bash-4.1$ ls -l /bin/ping
-rwsr-xr-x 1 root root 42136 11月 23 18:49 2010 /bin/ping

ああー……バグ報告ですか。これは。

RedHadのBugzillaでは非公開になっているが、Fedora側の情報によるとCVE-2010-3847とある。 GNU C Library Dynamic Linker Privilege Escalation Weaknesses (Secunia Advisory SA41795) Partially Fixedですかそうですか……

しかし、動作しているFedoraにも同様の修正が施されているので、 Fedoraから適切なパッチをバックポートしてくれば動くのではないだろうか。 どこのパッケージに施されたかをどうやって探そう。 Fedora14のglibcは2.13に更新されているので、これのせいで直ったとかいうことだと困るな……

  1. なお、nl_langinfo(CODESET)の動作実験で最初setlocale(LC_ALL, "")をしていなかったためにANSI_X3.4-1968などという出力が得られた。 (1)

ytoku/daily-record/2011-03-06 (last edited 2011-06-03 22:47:26 by ytoku)