RHELとCentOSのカーネルソースの違い

CentOSはサーバ用OSとして広く使用されていて、何と言っても基本的にはRHELのソースをそのまま利用して提供しているという安心感があります。実運用環境はRHELでも開発環境はCentOSで、とか、DBMS等の商用ソフトを動かすホスト以外は全てCentOSで、いうのは良くある光景ですね。(もっとも、CentOS 6になってからはリリースの遅さが懸念されてますが)
でも、パッケージはRHELと全く同じというわけではないです。Wikiから抜粋します。

1. Why does CentOS exist?
....
CentOS conforms fully with the upstream vendors redistribution policies and aims to be 100% binary compatible. (CentOS mainly changes packages to remove upstream vendor branding and artwork.).
....

http://wiki.centos.org/FAQ/General#head-d29a2b7e61ffc544973098f9dd49fe4663efba50

「具体的にはどう変更されているのだろう? 文面からすると、ロゴとかベンダー名とか、その辺りが違うだけに読めるけど、気になる。」
というわけで、比較的違いが少ないと思われるカーネルのソースを比較して確認してみた時のまとめです。

比較対象について

比較対象としては kernel-2.6.32-71.29.1.el6 を選択。以下の2つのsourceを使用しました。

  1. RedHat提供のkernel-2.6.32-71.29.1.el6.src.rpm
  2. CentOS提供のkernel-2.6.32-71.29.1.el6.src.rpm

ソースの展開について

以下の手順でSRPMからソースを取得しました。RHEL6からは、ソースの配布方法がvanillaからのパッチ累積方法では無くなったので、SOURCES配下がえらくシンプルになっているのが印象的です。

$ rpmdev-setuptree
$ ls ~/rpmbuild/
BUILD RPMS SOURCES SPECS SRPMS

$ rpm -ivh kernel-2.6.32-71.29.1.el6.src.rpm
# これによりSRPMの中身は、~/rpmbuild 配下に以下のように展開される。
# ~/rpmbuild
#  ├/SOURCES ・・・ ソースコード&ソースの差分パッチなど
#  └/SPECS   ・・・ RPMとSRPMの生成手順ファイル(kernel.spec)

比較手順について

SPECファイルと、SOURCES配下のファイル群が比較の対象となります。

まず、大物からということで、SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2 を確認。

$ ls -l rpmbuild_RHEL/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
-rw-rw-r--. 1 root root 66556452 Apr 22  2011 rpmbuild_RHEL/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
$ ls -l rpmbuild_CENT/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
-rw-rw-r--. 1 root root 66556452 Apr 22  2011 rpmbuild_CENT/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2

3つともサイズと日付が一緒。

$ sha1sum rpmbuild_RHEL/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
c609a095be74909b5829a9639bc5b617a50f6c5a  rpmbuild_RHEL/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
$ sha1sum rpmbuild_CENT/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2
c609a095be74909b5829a9639bc5b617a50f6c5a  rpmbuild_CENT/SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2

sha1sumのハッシュ値も同じ。省略するけどcmpの比較でも差分なし。と言うわけで、ソースのメイン部分については展開するまでも無く、同一であることが判りました。

次は、SPECファイルとかのファイル群です。diffを使っても良いけど、今後の差分確認など(バージョンが上がった時に追跡とかしたい)に備えて、mercurialでソースを管理して差分をチェックしてみることにします。やり方は、入門mercurialの「第12章 ソースアーカイブベースの勝手Mercurial化」を参考にしています。

  1. RHEL版のrpmbuild配下で、SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2 を削除。
  2. その後、rpmbuild配下で以下の操作で登録。
$ hg init
$ hg commit -A -m 'RHEL kernel-2.6.32-71.29.1.el6.src (without SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2)'

このリポジトリに対して、CentOSのソースを centos ブランチを作成して入れます。

$ hg branch centos
marked working directory as branch centos
$ hg locate | xargs rm -f
$ cp -rp rpmbuild_CENT/* rpmbuild_RHEL/  # rpmbuild_CENT配下に展開しておいたCentOSソースの内容をそのまま上書きコピー。
$ cd rpmbuild_RHEL/
$ hg commit -A -m 'CentOS kernel-2.6.32-71.29.1.el6.src (without SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2)'  #ここでは、すでにtar.bz2は削除してます。

できたリポジトリは、こんな感じになります。

$ hg branches
centos                         1:4001490134a3
default                        0:e7b3e54f788a (inactive)

$ hg branch
centos

$ hg log
changeset:   1:4001490134a3
branch:      centos
tag:         tip
user:        Kahnn
date:        Tue Nov 22 14:13:13 2011 +0900
summary:     CentOS kernel-2.6.32-71.29.1.el6.src (without SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2)

changeset:   0:e7b3e54f788a
user:        Kahnn
date:        Tue Nov 22 14:01:55 2011 +0900
summary:     RHEL kernel-2.6.32-71.29.1.el6.src (without SOURCES/linux-2.6.32-71.29.1.el6.tar.bz2)

差分の確認

いよいよ比較です。

$ hg diff -r 0 -r 1
diff -r e7b3e54f788a -r 4001490134a3 SOURCES/genkey
--- a/SOURCES/genkey    Tue Nov 22 14:01:55 2011 +0900
+++ b/SOURCES/genkey    Tue Nov 22 14:13:13 2011 +0900
@@ -2,6 +2,6 @@
 %secring kernel.sec
 Key-Type: DSA
 Key-Length: 1024
-Name-Real: Red Hat, Inc.
+Name-Real: CentOS
 Name-Comment: Kernel Module GPG key
 %commit

diff -r e7b3e54f788a -r 4001490134a3 SPECS/kernel.spec
--- a/SPECS/kernel.spec Tue Nov 22 14:01:55 2011 +0900
+++ b/SPECS/kernel.spec Tue Nov 22 14:13:13 2011 +0900
@@ -945,7 +945,7 @@
 if [ -s %{SOURCE19} ]; then
        gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
 fi
-gpg --homedir . --export --keyring ./kernel.pub Red > extract.pub
+gpg --homedir . --export --keyring ./kernel.pub CentOS > extract.pub
 gcc -o scripts/bin2c scripts/bin2c.c
 scripts/bin2c ksign_def_public_key __initdata <extract.pub >crypto/signature/key.h
 %endif
@@ -1654,6 +1654,9 @@
 %endif

 %changelog
+* Mon Jun 27 2011 Karanbir Singh <kbsingh@centos.org> [2.6.32-71.29.1.el6.centos]
+- Roll in CentOS Branding
+
 * Thu Apr 21 2011 Frantisek Hrbata <fhrbata@redhat.com> [2.6.32-71.29.1.el6]
 - [mm] Revert "[mm] pdpte registers are not flushed when PGD entry is changed in x86 PAE mode" (Larry Woodman) [695256 691310]

この結果から、両者間にほぼ差が無い事がわかります。署名用鍵の Real Name をCnetOSに変更して、export 時の uid を対応する名前(CentOS)に変更しているだけですね。
後は一緒です。

まとめ

RHEL6とCentOS6の場合、カーネルソースの違いは、署名用鍵の Real Name を変更しているだけであり、基本的には同じもの。従って、ビルド環境さえ揃えておけば、どちらのソースからでも機能的に等価のバイナリが得られる。

補足というか備忘録

差分の周辺について、SPECS/kernel.specをもう少し見ると、以下のようになっている。

Source11: genkey
....
Source19: extrakeys.pub
....

%if %{signmodules}
cp %{SOURCE19} .
....
gpg --homedir . --batch --gen-key %{SOURCE11}
....
$ if there're external keys to be included
if [ -s %{SOURCE19} ]; then
        gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
fi
gpg --homedir . --export --keyring ./kernel.pub CentOS > extract.pub
gcc -o scripts/bin2c scripts/bin2c.c
scripts/bin2c ksign_def_public_key __initdata <extract.pub >crypto/signature/key.h
%endif

つまり、genkeyファイルの差分は gpg --gen-key を batch モードで実行する際のパラメータファイルで、Real Name を 「Red Hat, Inc.」から「CentOS」に変更している。
これは、実際のバイナリ提供元が Red Hat では無いわけだから、ライセンス上必要な処置という事になるのかな。
実際にgenkeyした直後の公開鍵はこんな感じ。

$ gpg --homedir . --keyring ./kernel.pub --list-keys
./kernel.pub
------------
pub   1024D/90821984 2011-11-22
uid                  CentOS (Kernel Module GPG key)

SOURCE19に用意してあるextrakeys.pubをimportすると、こんな感じ。

$ gpg --homedir . --no-default-keyring --keyring kernel.pub --import extrakeys.pub
gpg: key CD09BEDA: public key "Red Hat Enterprise Linux Driver Update Program <secalert@redhat.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
$ gpg --homedir . --keyring ./kernel.pub --list-keys
./kernel.pub
------------
pub   1024D/90821984 2011-11-22
uid                  CentOS (Kernel Module GPG key)

pub   1024D/CD09BEDA 2010-03-16
uid                  Red Hat Enterprise Linux Driver Update Program <secalert@redhat.com>

実際に export している場面では、genkeyの変更に対応捨て uid を Red から CentOSに変更しているので、extrakeysは無くても良いという事になるのかな。
あと、皆が遅いというgenkey処理は rngd を使用してみろとspecファイルのメッセージにも出てくるけど、カーネルコンパイルできるようにしただけでは入らないので、以下のパッケージが必要。

# yum install rng-tools
# rpm -qf /sbin/rngd
rng-tools-2-8.el6.x86_64