CentOS 7: カーネルを再ビルドする

CentOS 7のカーネルのsrc.rpmを使って、カーネルコンフィグとソースコードを変更して、カーネルを再ビルドする手順を記載します。

 

1 カーネルのビルドに必要なパッケージのインストール

yumでカーネルのビルドに必要なパッケージをインストールします。

$ sudo yum-builddep -y kernel
$ sudo yum install -y pesign

2 カーネルのsrc.rpmのダウンロード

カーネルのsrc.rpmをダウンロードします。

$ yumdownloader --source kernel
$ rpm -i kernel-*.src.rpm
$ cd rpmbuild

3 バージョンの変更

specファイルのbuildid変数に値を設定します。これによりrpmのファイル名だけでなく、カーネルのファイル名も変更されます。

$ diff -uprN SPECS/kernel.spec{.org,}
--- SPECS/kernel.spec.org       2016-05-28 05:09:48.825520275 +0900
+++ SPECS/kernel.spec   2016-05-28 05:10:13.376316809 +0900
@@ -3,7 +3,7 @@

 Summary: The Linux kernel

-# % define buildid .local
+%define buildid .local

 # For a kernel released for public testing, released_kernel should be 1.
 # For internal testing builds during development, it should be 0.

4 カーネルコンフィグの変更

rpmbuild -bpでソースコードの展開とパッチの適用を実行します。コンフィグファイル先頭にCPUアーキテクチャを入れる必要があります。

$ rpmbuild -bp SPECS/kernel.spec
$ cd BUILD/kernel-*/linux-*
$ make menuconfig # Change config
$ echo "# x86_64" > ~/kernel-*-x86_64.config
$ cat .config >> ~/rpmbuild/SOURCES/kernel-*-x86_64.config

ここではCONFIG_RELOCATABLEを無効にします。

$ diff -uprN SOURCES/kernel-3.10.0-x86_64.config{.org,}
--- SOURCES/kernel-3.10.0-x86_64.config.org     2016-05-29 04:27:16.779380876 +0900
+++ SOURCES/kernel-3.10.0-x86_64.config 2016-05-29 05:10:24.144476432 +0900
@@ -1,7 +1,7 @@
 # x86_64
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 3.10.0 Kernel Configuration
+# Linux/x86 3.10.0 Kernel Configuration
 #
 CONFIG_64BIT=y
 CONFIG_X86_64=y
@@ -527,7 +527,7 @@ CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y
 CONFIG_CRASH_DUMP=y
 CONFIG_KEXEC_JUMP=y
 CONFIG_PHYSICAL_START=0x1000000
-CONFIG_RELOCATABLE=y
+# CONFIG_RELOCATABLE is not set
 CONFIG_PHYSICAL_ALIGN=0x1000000
 CONFIG_HOTPLUG_CPU=y
 CONFIG_BOOTPARAM_HOTPLUG_CPU0=y

5 カーネルソースコードの変更

rpmbuild -bpでソースコードの展開とパッチの適用を実行します。ソースコードの変更はパッチファイルにする必要があるので、カーネルツリーのコピーを作成してパッチを作成します。

$ rpmbuild -bp SPECS/kernel.spec
$ cd BUILD/kernel-*
$ cp -a linux-3.10.0-327.22.2.el7.local.x86_64{,.org}
# Change linux-3.10.0-327.22.2.el7.local.x86_64
# diff -uprN linux-3.10.0-327.22.2.el7.local.x86_64{.org,}

ここではRAMディスク実行前に"Hello, World"という文字列を表示します。

$ cat SOURCES/hello.patch
diff -uprN linux-3.10.0-327.18.2.el7.local.x86_64.org/init/main.c linux-3.10.0-327.18.2.el7.local.x86_64/init/main.c
--- linux-3.10.0-327.18.2.el7.local.x86_64.org/init/main.c    2016-04-08 17:33:21.000000000 +0900
+++ linux-3.10.0-327.18.2.el7.local.x86_64/init/main.c        2016-05-27 15:46:43.271577474 +0900
@@ -892,6 +892,8 @@ static int __ref kernel_init(void *unuse

        flush_delayed_fput();

+       printk("Hello, World\n");
+
        if (ramdisk_execute_command) {
                if (!run_init_process(ramdisk_execute_command))
                        return 0;

"hello.patch"というパッチのエントリをspecファイルに追加します。

$ diff -uprN SPECS/kernel.spec{.org,}
--- SPECS/kernel.spec.org       2016-05-28 06:11:02.452648537 +0900
+++ SPECS/kernel.spec   2016-05-28 06:09:39.284293579 +0900
@@ -380,6 +380,7 @@ Patch999999: linux-kernel-test.patch
 Patch1000: debrand-single-cpu.patch
 Patch1001: debrand-rh_taint.patch
 Patch1002: debrand-rh-i686-cpu.patch
+Patch2000: hello.patch

 BuildRoot: %{_tmppath}/kernel-%{KVRA}-root

@@ -691,6 +692,7 @@ ApplyOptionalPatch linux-kernel-test.pat
 ApplyOptionalPatch debrand-single-cpu.patch
 ApplyOptionalPatch debrand-rh_taint.patch
 ApplyOptionalPatch debrand-rh-i686-cpu.patch
+ApplyOptionalPatch hello.patch

 # Any further pre-build tree manipulations happen here.

6 カーネルのビルド

–withoutオプションでビルドするrpmパッケージを絞ります。–withoutオプションありだと1時間ほど掛かります。–withoutオプションなしだと3時間ほど掛かります。

$ rpmbuild -ba --without debug --without doc --without perf \
--without tools --without debuginfo --without kdump \
--without bootwrapper SPECS/kernel.spec
$ ls RPMS/x86_64/
kernel-3.10.0-327.18.2.el7.local.x86_64.rpm
kernel-devel-3.10.0-327.18.2.el7.local.x86_64.rpm
kernel-headers-3.10.0-327.18.2.el7.local.x86_64.rpm

7 動作確認

"Hello, World"と表示されました。

[    0.719104] rtc_cmos 00:00: setting system clock to 2016-05-28
14:58:30 UTC (1464447510)
[    0.719567] Freeing unused kernel memory: 1620k freed
[    0.719722] Hello, World
[    0.721348] systemd[1]: systemd 219 running in system mode. (+PAM
+AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP
+GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
[    0.721362] systemd[1]: Detected virtualization kvm.

カーネルのバージョンも.localが付きました。

$ uname -r
3.10.0-327.18.2.el7.local.x86_64

コンフィグファイルでCONFIG_RELOCATABLEが無効になっています。

$ grep -nr "CONFIG_RELOCATABLE" /boot/config-3.10.0-327.18.2.el7.local.x86_64
529:# CONFIG_RELOCATABLE is not set