2011年12月9日金曜日

prelink されたバイナリの "rpm -V" での検証は無問題

寒くなってまいりましたが、いかがお過ごしでしょうか。お疲れ様です、サイオス 那賀です。

今どきの Red Hat 系のシステムでは、デフォルトで prelink が有効になっているんですね。下記のように、cron から起動されています。

$ ls /etc/cron.daily/prelink
/etc/cron.daily/prelink*
$ grep PRELINKING /etc/sysconfig/prelink
PRELINKING=yes

定期的に prelink をしなおしているので、バイナリが書き換わっています。"libxml2" の持つ "/usr/lib64/libxml2.so.2.6.26" を見てみます。下記は、RPM のシステムが保持している MD5 値です。

$ pkg=libxml2
$ file=/usr/lib64/libxml2.so.2.6.26
$ rpm -q --dump $pkg | grep ^$file | cut -d' ' -f1,4
/usr/lib64/libxml2.so.2.6.26 0cb304449951396925c1ad4e84930a22

ファイルから直接に MD5 値を取得すると、当然 prelink が書きかえた分だけ違います。

$ md5sum $file
1dd15c495edb654f0a55c366bf39bdf7  /usr/lib64/libxml2.so.2.6.26

ところが、"rpm -V" で verify しても、何も言われないんですよね。

$ rpm -V libxml2

なぜだろうかと思ったのですが、ミソは、以下のファイルでした。

$ rpm -qf /etc/rpm/macros.prelink
prelink-0.4.0-2.el5
$ cat /etc/rpm/macros.prelink
# rpm-4.1 verifies prelinked libraries using a prelink undo helper.
#       Note: The 2nd token is used as argv[0] and "library" is a
#       placeholder that will be deleted and replaced with the appropriate
#       library file path.
%__prelink_undo_cmd     /usr/sbin/prelink prelink -y library

"rpm -V" の verify をする際に RPM は、上記マクロのコマンドを内部で呼んで、prelink による改変前のバイナリのダイジェスト値で比較して、それ以外の改変の有無を判断しています。手実行して、RPM が内部で保持している MD5 値と一致することを確認してみます。

$ prelink --verify --md5 $file
0cb304449951396925c1ad4e84930a22  /usr/lib64/libxml2.so.2.6.26

OK でした。なお、prelink の処理は可逆です。元に戻すための情報は、ELF のバイナリファイルに追加されるセクション ".gnu.prelink_undo" 内に保持されています。

$ readelf --section-headers $file | grep --after-context=1 prelink
  [27] .gnu.prelink_undo PROGBITS         0000000000000000  0013baf0
       0000000000000798  0000000000000001           0     0     8

元に戻してみます。

$ sudo prelink --undo $file
$ md5sum $file
0cb304449951396925c1ad4e84930a22  /usr/lib64/libxml2.so.2.6.26

今度は、直接 MD5 値を取っても、RPM の内部値と一致しています。

処理まで追おうとして力つきましたので、今日はこのへんで。では。

追記 (Mon Dec 12 2011)

RHEL6 系からは、ダイジェスト値が SHA1 の 256 ビットに変更されています。

$ pkg=libxml2
$ file=/usr/lib64/libxml2.so.2.6.26
$ rpm -q --dump $pkg | grep ^$file | cut -d' ' -f1,4
/usr/lib64/libxml2.so.2.7.6 2b7ae1cbfd796e3ce32a0a836d801bfcc0feefad284705c572d9bb5528f387af
$ sha256sum $file
292596e8550d3167df658b03578654337c26c99d37fc10beb0771385b33d426e  /usr/lib64/libxml2.so.2.7.6
$ prelink --verify $file | sha256sum
2b7ae1cbfd796e3ce32a0a836d801bfcc0feefad284705c572d9bb5528f387af  -

ダイジェスト値はパッケージを作成した時点で埋めこまれます。rpm-*/build/files.c:genCpioListAndHeader() あたりを見ると分かりますが、%_binary_filedigest_algorithm マクロが得られなければ、デフォルトで MD5 になるようになっていますので、明示的に SHA256 が指定されているはずです。これは、redhat-rpm-config パッケージに含まれる /usr/lib/rpm/redhat/macros で指定されています。

...
# Use SHA-256 for FILEDIGESTS instead of default MD5
%_source_filedigest_algorithm 8
%_binary_filedigest_algorithm 8
...

0 件のコメント:

コメントを投稿