RHEL: Building a custom kernel on RHEL 6

RHEL: Building a custom kernel on RHEL 6

# Tested on RHEL 6.4 i386
# Notes mainly from http://wiki.centos.org/HowTos/Custom_Kernel


# WARNING: Please note that customizing kernel is not supported by Red Hat Support Services

# NOTE: It is advisable to build packages as a non-root user as the instructions for
#       building a given tarball may silently and invisibly change a shared library, and
#       cause much damage to a system.



# Build preparations
# ------------------------------------------------------------------------------------------

# As a non-root user, create a build tree based on a ~/rpmbuild/ directory:

user@myhost:/home/user#> mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}

user@myhost:/home/user#> echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros


# As root, install following needed packages:

root@myhost:/#> yum install rpm-build redhat-rpm-config asciidoc hmaccalc \
           perl-ExtUtils-Embed xmlto audit-libs-devel binutils-devel elfutils-devel \
           elfutils-libelf-devel newt-devel python-devel zlib-devel


# Obtain the kernel source rpm package and install it as a non-root user. For instance,
# for my RHEL 6 i386:

user@myhost:/home/user#> rpm -q kernel
kernel-2.6.32-358.el6.i686

user@myhost:/home/user#> rpm -i kernel-2.6.32-431.20.3.el6.src.rpm


# Unpack and prepare the source files:

user@myhost:/home/user#> cd ~/rpmbuild/SPECS

user@myhost:/home/user/rpmbuild/SPECS#> rpmbuild -bp --target=$(uname -m) kernel.spec
   Building target platforms: i686
   Building for target i686
   Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.RsE9ro
   + umask 022
   + cd /home/user/rpmbuild/BUILD
   + LANG=C
   + export LANG
   + unset DISPLAY
   + patch_command='patch -p1 -F1 -s'
   + '[' '!' -d kernel-2.6.32-431.20.3.el6/vanilla-2.6.32-431.20.3.el6/ ']'
   + rm -f pax_global_header
   + cd /home/user/rpmbuild/BUILD
[...]
   + gcc -o scripts/bin2c scripts/bin2c.c
   + scripts/bin2c ksign_def_public_key __initdata
   + cd ..
   + exit 0


# The kernel source tree will now be found under the ~/rpmbuild/BUILD/kernel*/linux*/
# directory.


# If you have any kernel patches to add, copy them now to ~/rpmbuild/SOURCES/ directory.

# Otherwise, if needed, you can create your own kernel patch following this procedure:

# Copy the source tree to preserve the original tree while making changes to the new one

user@myhost:/home/user/#> cd ~/rpmbuild/BUILD

user@myhost:/home/user/rpmbuild/BUILD#> cp -pr kernel-2.6.32-431.20.3.el6 kernel-2.6.32-431.20.3.el6.new

# Make necessary modifications to your custom kernel. Me, for instance, I'm just modifying
# a single commentary line in following file:

user@myhost:/home/user/rpmbuild/BUILD#> vi ./kernel-2.6.32-431.20.3.el6.new/linux-2.6.32-431.20.3.el6.i686/kernel/time.c

# After the .new source tree is modified, generate the patch. To generate the patch,
# run diff against the entire .new and original source trees with the following command:

user@myhost:/home/user/rpmbuild/BUILD#> diff -uNrp kernel-2.6.32-431.20.3.el6 kernel-2.6.32-431.20.3.el6.new > ../SOURCES/mypatch.patch


# Now, edit the patch file to remove the leading directory, this is required because
# the kernel spec file applies patches with '-p1' only.

user@myhost:/home/user/rpmbuild/BUILD#> vi ~/rpmbuild/SOURCES/mypatch.patch

# For example, change the following:

--- kernel-2.6.32-431.20.3.el6/linux-2.6.32-431.20.3.el6.i686/kernel/time.c     2014-06-06 23:42:44.000000000 +0200
+++ kernel-2.6.32-431.20.3.el6.new/linux-2.6.32-431.20.3.el6.i686/kernel/time.c 2014-09-25 17:27:06.955461886 +0200

# To:

--- linux-2.6.32-431.20.3.el6.i686/kernel/time.c     2014-06-06 23:42:44.000000000 +0200
+++ linux-2.6.32-431.20.3.el6.i686/kernel/time.c     2014-09-25 17:27:06.955461886 +0200

# My new patch is ready



# Configure the kernel
# ------------------------------------------------------------------------------------------

# Change directory to ~/rpmbuild/BUILD/kernel-*/linux-*/ and copy into this directory,
# as .config, following file:

user@myhost:/#> cd ~/rpmbuild/BUILD/kernel-*/linux-*/

user@myhost:/#> cp configs/kernel-2.6.32-`uname -m`.config .config


# First run 'make oldconfig'

user@myhost:/#> make oldconfig
   scripts/kconfig/conf -o arch/x86/Kconfig
   #
   # configuration written to .config
   #

# Now you should run 'make menuconfig' and do the necessary selections. Once complete,
# remember to save your changes.

# make menuconfig is one of five similar tools that can configure the Linux kernel source,
# a necessary early step needed to compile the source code. 'make menuconfig', with a
# menu-driven user interface, allows the user to choose the features of the Linux kernel
# (and other options) that will be compiled. It is normally invoked using the command
# 'make menuconfig', 'menuconfig' is a target in the Linux kernel Makefile.

# 'make menuconfig' was not in the first version of the Linux kernel. The predecessor tool
# is a question-and-answer-based utility ('make config', 'make oldconfig'). A third tool
# for Linux configuration is 'make xconfig', which requires Qt. There is also
# 'make gconfig', which uses GTK+, and 'make nconfig', which is similar to 'make menuconfig'.


user@myhost:/#> make menuconfig
scripts/kconfig/mconf arch/x86/Kconfig
   #
   # configuration written to .config
   #

   *** End of Linux kernel configuration.
   *** Execute 'make' to build the kernel or try 'make help'.



# If you have installed the full kernel source to build a kernel module, you should do
# it at this point.

# Next, add a line that contains the commented out equivalent of the hardware platform to
# the top of the configuration file (equivalent to the output returned by a 'uname -i'
# command) just before you copy it back to the configs/ directory. This will either be
# "i386" for the 32-bit architecture or "x86_64" for the 64-bit architecture. It needs
# to be commented out with a "#" and must be the first line of the file. Note that there
# must be a space between the hash symbol and the hardware platform descriptor.

user@myhost:/#> vi .config

# Add, as the first line of the .config file, either:

# i386

# - or -

# x86_64

# Copy the .config file back to the configs/ directory:

user@myhost:/#> cp .config configs/kernel-2.6.32-`uname -m`.config

# The final step is to copy the entire contents of the configs/ directory to the
# ~/rpmbuild/SOURCES/ directory.

user@myhost:/#> cp configs/* ~/rpmbuild/SOURCES/



# Modifying the kernel specification file
# ------------------------------------------------------------------------------------------

# The kernel specification file should now be modified.

user@myhost:/#> cd ~/rpmbuild/SPECS/
user@myhost:/#> cp kernel.spec kernel.spec.distro

user@myhost:/#> vi kernel.spec

# At line 18, the definition of buildid is commented out. This must be uncommented and
# given a value to avoid a conflict with your currently installed kernel. Change the line
# in a similar manner to the example below:

%define buildid .mykernel

# There should be no space between the "%" and the word "define".


# If you have any patches to apply, you need to make reference to them in two places:

# 1.- Just before line 613 (which reads "# empty final patch file to facilitate testing of
# kernel patches"), add your declaration starting with the number 40000, so that your
# patch is not in any danger of conflicting with the RHEL kernel patch space. Example:

Patch40000: mypatch.patch

# 2.- Just before line 935 (which reads, "ApplyOptionalPatch linux-kernel-test.patch"),
# add a line to apply your patch. For example:

ApplyOptionalPatch mypatch.patch


# Replace line 929:

cp $RPM_SOURCE_DIR/config-* .

# with:

cp $RPM_SOURCE_DIR/kernel-*.config .


# Comment out line 933:

#make -f %{SOURCE20} VERSION=%{version} configs



# Build the new kernel
# ------------------------------------------------------------------------------------------

# WARNING: Pay attention to the free space on the filesystem you are building the new
#          kernel. For me it took about 7GB:
#
# user@myhost:/home/user/rpmbuild#> #> du -hs .
# 6.9G    .



# Start the build:

user@myhost:/#> cd ~/rpmbuild/SPECS/

user@myhost:/#> rpmbuild -bb --target=`uname -m` kernel.spec 2> build-err.log | tee build-out.log
   Building target platforms: i686
   Building for target i686
   Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.Ua66Tz
   ###
[...]
   Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.8SaeUj
   BUILDING A KERNEL FOR i686...
   USING ARCH=i386
   3f47dc2f8a3f1f9fc4205205cdf132ebb09545ce
   2b3af23cd31109682bf94574bed4f13ff25b4c35
   abc7b98eb5ff6aaa3cafa8d3c37e7a12428ff496
   5b1d6b49a129f51f9db7f96c5ce0160ef02dd17e
   cb36c6d75b023a9ad75d5475b2960dd2cbd09a4f
   cb36c6d75b023a9ad75d5475b2960dd2cbd09a4f
[...]
   Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/user/rpmbuild/BUILDROOT/kernel-2.6.32-431.20.3.el6.mykernel.i386
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-headers-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-debuginfo-common-i686-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/python-perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/python-perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-debug-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-debug-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Wrote: /home/user/rpmbuild/RPMS/i686/kernel-debug-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.R5KFyB


# For kernels >= 2.6.18-53.el5, you can add some useful options to the rpmbuild command by
# using the --with and/or --without flags and associated arguments. The main options are:

   --with baseonly
   --with xenonly
   --without up
   --without xen
   --without debug
   --without debuginfo
   --without fips
   --without kabichk



# When the build completes, your custom kernel rpm files will be found in the
# ~/rpmbuild/RPMS/`uname -m`/ directory. Make sure that you install those files, as root,
# using an 'rpm -ivh kernel-*.rpm' command.

# Note: If you have built a kernel version that is older than a currently installed
# version you will also have to use the --oldpackage flag with the rpm command.

# UNDER NO CIRCUMSTANCES use an 'rpm -Uvh' command to install your kernel as this will
# update (overwrite) the currently installed version. Hence if you have a problem with
# your custom kernel, you will not be able to revert to the previous, working, version.


root@myhost:/#> cd /home/user/rpmbuild/RPMS/`uname -m`

root@myhost:/home/user/rpmbuild/RPMS/i686#> ll
   total 628924
   -rw-rw-r-- 1 user group  26844728 Sep 19 04:49 kernel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group  27460356 Sep 19 05:02 kernel-debug-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group 261491476 Sep 19 05:11 kernel-debug-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   9221168 Sep 19 05:02 kernel-debug-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group 255223848 Sep 19 05:01 kernel-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group  40208252 Sep 19 04:51 kernel-debuginfo-common-i686-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   9181032 Sep 19 04:52 kernel-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   2996324 Sep 19 04:49 kernel-headers-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   3067580 Sep 19 04:51 perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   3673100 Sep 19 04:51 perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   2292360 Sep 19 04:51 python-perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
   -rw-rw-r-- 1 user group   2338372 Sep 19 04:51 python-perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm

root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv <rpms>


# Note: Starting from kernel-2.6.32-358.el6, if "bfa-firmware" package is already installed on the system,
# then it has to be above a certain version, otherwise the installation of kernel will cause a conflict:
#
#        bfa-firmware < 3.2.21.1-2 conflicts with kernel-2.6.32-431.20.3.el6.mykernel.i686
#
# If bfa-firmware is not required for other packages, we can remove it from our system

root@myhost:/#> rpm -q --whatrequires bfa-firmware
no package requires bfa-firmware

root@myhost:/#> rpm -e bfa-firmware


# Apart from that I'm running into problems because kernel requires a newer version of kernel-firmware
# This is the message I'm receiving:
#
#        kernel-firmware >= 2.6.32-431.20.3.el6.mykernel is needed by kernel-2.6.32-431.20.3.el6.mykernel.i686
#
# so I decided to rebuild the kernel adding the option --with firmware in order to generate the
# kernel-firmware package too


# Connected as our non-root user:

user@myhost:/#> cd ~/rpmbuild/SPECS/

user@myhost:/home/user/rpmbuild/SPECS#> rpmbuild -bb --target=`uname -m` --with firmware kernel.spec 2> build-err2.log | tee build-out2.log


# As root

root@myhost:/#> cd /home/user/rpmbuild/RPMS/`uname -m`

root@myhost:/home/user/rpmbuild/RPMS/i686#> ll kernel-firmware*
-rw-rw-r-- 1 user group 13627368 Sep 25 03:47 kernel-firmware-2.6.32-431.20.3.el6.mykernel.i686.rpm


# Now, we can start installing packages normally


root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-firmware-2.6.32-431.20.3.el6.mykernel.i686.rpm
Preparing...                ########################################### [100%]
        file /usr/share/doc/kernel-firmware-2.6.32/WHENCE from install of kernel-firmware-2.6.32-431.20.3.el6.mykernel.i686 conflicts with file from package kernel-firmware-2.6.32-358.el6.noarch

root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm --replacefiles -ihv kernel-firmware-2.6.32-431.20.3.el6.mykernel.i686.rpm
Preparing...                ########################################### [100%]
   1:kernel-firmware        ########################################### [100%]


root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-debug-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-debuginfo-common-i686-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-debug-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-debug-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv kernel-devel-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm --replacefiles -ihv kernel-headers-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv python-perf-2.6.32-431.20.3.el6.mykernel.i686.rpm
root@myhost:/home/user/rpmbuild/RPMS/i686#> rpm -ihv python-perf-debuginfo-2.6.32-431.20.3.el6.mykernel.i686.rpm


# Verify/modify grub's grub.conf file to add new custom kernel:

title CentOS (2.6.32-431.20.3.el6.mykernel.i686)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-431.20.3.el6.mykernel.i686 ro root=/dev/mapper/rootvg-lv_root rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=fr LANG=en_US.UTF-8 rd_LVM_LV=rootvg/lv_swap rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=rootvg/lv_root rd_NO_DM quiet
        initrd /initramfs-2.6.32-431.20.3.el6.mykernel.i686.img
0 (0)
Article Rating (No Votes)
Rate this article
Attachments
There are no attachments for this article.
Comments
There are no comments for this article. Be the first to post a comment.
Full Name
Email Address
Security Code Security Code
Related Articles RSS Feed
How to Configure ‘FirewallD’ in RHEL/CentOS 7 and Fedora 21
Viewed 10222 times since Wed, Oct 9, 2019
HOWTO: Use SSL/port 465 in smarthost stunnel
Viewed 3607 times since Fri, Sep 28, 2018
Linux Kernel /etc/sysctl.conf Security Hardening
Viewed 23328 times since Fri, Aug 3, 2018
Migrate a Linux System from Red Hat Enterprise to CentOS
Viewed 10169 times since Fri, May 15, 2020
RHEL: Back-up/Replicate a partition table
Viewed 3184 times since Sun, May 27, 2018
3 Ways to Check Linux Kernel Version in Command Line
Viewed 11394 times since Fri, Apr 19, 2019
Oracle Linux 7 – How to audit changes to a trusted file such as /etc/passwd or /etc/shadow
Viewed 2787 times since Wed, Jul 25, 2018
What is OS Watcher Utility and How to use it for Database Troubleshooting ?
Viewed 29802 times since Thu, Jun 21, 2018
Linux - How to monitor memory usage
Viewed 2910 times since Fri, Jun 8, 2018
A Quick and Practical Reference for tcpdump
Viewed 12324 times since Fri, Jul 27, 2018