The Linux kernel is distinctive among major commercial UNIX variants in that the complete source code for the kernel is available and freely included in most major Linux distributions. If you are curious about a particular Linux implementation detail, you can have a look at the source. If you have a special need that requires modification of the kernel, you apply your patch and build your own special version of Linux.
This is not to say that building a kernel is a required step in the administration of a Linux system. There is no application used anywhere in this text that mandates a kernel with special features; the generic kernel put down by the installer has everything required. While older Linux implementations commonly required custom kernels (especially in the days before kernel modules), recent improvements in Linux have obviated much of the need for such system customization. A linux administrator who insists upon a custom kernel is behind the times.
However, security vulnerabilities were found in the 2.2.5 kernel shortly after Red Hat Linux 6.0 was released. Any production Linux installation on the 2.2 kernel series should upgrade to a patched kernel. This can be done with a complex set of steps involving RPM, or by building a new kernel as outlined below.
It is more important to build custom kernels for servers with Internet exposure than workstations. It is also easier, since servers generally do not have sound cards or other hardware that increases kernel complexity.
The Linux kernel is usually stored in a file called vmlinuz
in the root directory of the system. However, Red Hat Linux 6.0 puts the
kernel in the /boot directory, under a different name
(such as vmlinuz-2.2.5-15). The kernel is loaded at boot
time. As it boots, the kernel will probe the system and configure basic
hardware settings, then load a program called init which
continues the boot process; the boot sequence is not documented in this
text. While portions of the kernel can be loaded or removed at will, the
only way to switch to a completely different kernel image is to reboot.
Throughout this text, there has been an implicit understanding that the i386 architecture is in use. We now make that assertion explicit: the slight differences in preparing and booting kernels for Alpha and Sparc architectures are not discussed here.
The Linux kernel is written in C and requires a C compiler in the
development environment. A copy of the kernel source (version 2.2.11) is
included on the
CD-ROM in the /linux directory. It is encoded with the bzip2
compression utility. This bzip2 utility is not installed by default, but an RPM
package which will install it is available in the standard distribtion of
Red Hat Linux 6.0.
If you do not know how to install such packages, you are definately
not ready to build a new kernel - read the RPM section of Chapter 1 in this
text.
It is very easy to make a mistake in building a kernel that will prevent a system from booting. Kernel builds are not for the inexperienced. An emergency boot disk, created at installation time, is a manditory item. For an inexperienced administrator, it is not a question of if a future kernel build will render the system incapable of booting, but when.
Assuming that the CD-ROM included with this text is mounted on the
/cdrom directory, the kernel source could be unpacked with
the following sequence of commands:
cd /usr/src rm -f linux bzip2 -cd /cdrom/linux/linux-2.2.11.tar.bz2 | tar xvf - chown -R root.root linux cd linux
Once the 2.2.11 kernel source is installed, check for newer versions of the kernel on-line. Two popular Linux kernel sites are http://www.kernel.org and http://www.kernelnotes.org. If there are new kernel versions available, just download and apply the patch files to bring the kernel source up-to-date. Documentation for applying the patches can be found on these sites. It should not be necessary to download the entire kernel source package. Use the patches as they are much smaller and accomplish the same effect.
The kernel source is also available in RPM format in the standard Red Hat distribution, but the use of the Linux kernel source RPMs is specifically not recommended. The RPM versions do not include the entire source distribution. Source patches will commonly fail to work properly with these versions.
FTP access to kernel.org is facilitated by the use of country codes.
For example, administrators in the United States should use the
ftp.us.kernel.org address to download kernel patches from the
/pub/linux/kernel/v2.2 directory. Users in the United Kingdom
should use ftp.uk.kernel.org, Canadians should use ftp.ca.kernel.org, etc.
There is one valuable piece of advice for users considering the use of
the make config command to configure the kernel -
don't!
The make config command has been supplanted by the much
easier make menuconfig, which is the most flexible of the
kernel build configuration utilities. make xconfig is also
useful, but since it requires X-Windows, it will not be covered in this
text.
Enter the following command to configure the build options for the Linux kernel:
make menuconfig
A menu similar to the following will appear:
Linux Kernel v2.2.11 Configuration ***************************************************************************** ******************************** Main Menu ******************************** * Arrow keys navigate the menu. <Enter> selects submenus --->. * * Highlighted letters are hotkeys. Pressing <Y> includes, <N> excludes, * * <M> modularizes features. Press <Esc><Esc> to exit, <?> for Help. * * Legend: [*] built-in [ ] excluded <M> module < > module capable * * *********************************************************************** * * * Code maturity level options ---> * * * * Processor type and features ---> * * * * Loadable module support ---> * * * * General setup ---> * * * * Plug and Play support ---> * * * * Block devices ---> * * * * Networking options ---> * * * * SCSI support ---> * * * * Network device support ---> * * * * Amateur Radio support ---> * * * * IrDA subsystem support ---> * * * * ISDN subsystem ---> * * * * Old CD-ROM drivers (not SCSI, not IDE) ---> * * * * Character devices ---> * * * * Filesystems ---> * * * * Console drivers ---> * * * * Sound ---> * * * * Kernel hacking ---> * * * * --- * * * * Load an Alternate Configuration File * * * * Save Configuration to an Alternate File * * * *********************************************************************** * *************************************************************************** * <Select> < Exit > < Help > * ***************************************************************************
Each menu option above composes a major subsection of the kernel configuration parameters. Within these subsections, individual options that can be enabled or disabled. For most options, as they are enabled, they cause extra code to be compiled into the kernel, which makes the binary kernel image larger.
Most of these options can be built in two ways. They can either be compiled directly into the kernel binary, or they can be built as modules which can be loaded and removed from the kernel at will. Some configuration options cannot be prepared as modules, and others can only be used as modules, but most can be used either way.
The greatest pitfall, however, are the storage options which include
drivers for SCSI
(Small Computer Systems Interface)
and IDE (Integrated Drive Electronics).
If the kernel is loaded from a SCSI drive, the driver
for the SCSI controller must be available to the kernel, or the
system will not boot because it does not know how to manipulate the SCSI
hardware. The best way to prepare a kernel for a SCSI system
is to compile the driver for the SCSI controller directly into the kernel
image. This is not a reasonable solution, however, for the generic kernel
provided by the installation process. In this generic kernel,
the SCSI drivers are provided as
modules, since drivers compiled directly into the kernel would make the
kernel image very, very large. If the modules are stored on the SCSI hard
drive, a chicken-and-egg situation develops. The generic kernels use an
initial ramdisk to solve this problem. The initrd
image holds copies of all the SCSI modules. The initrd image
is loaded by LILO (or whatever loader is in use) and is available as the
kernel boots. In any case, initrd images are inconvenient
and it is best if custom kernels do not rely upon them.
In addition to the basic ability to access the hard drive, a few other
configurations will result in a system that will not boot. Failure to provide
support for ext2fs (Second Extended File System support)
will clobber a system quite handily, since ext2fs is the
native file system used in Red Hat Linux at this time (this situation may
change with the inclusion of the XFS journaling file system in the anticipated
Linux 2.4 kernel). Improper device configuration
options passed as arguments to the kernel can commonly lead to a quick
death at boot time. It is not difficult to find a long list of things that
can go wrong, so ensure a contingency plan is in place (relating to LILO
and an emergency boot diskette).
Before building a kernel, an approach to modules must be decided. When building a kernel to be used on a large number of machines, it is very convenient to disable modules and (carefully) select drivers for all required hardware to compile directly into the kernel. Copy the kernel as a single file to a remote system, run LILO, then reboot in the new kernel environment. If such a static kernel is used, it will be advisable to comment out the entry in /etc/cron.d/kmod, otherwise hourly status messages will be generated by cron concerning module manipulation failures. In any case, static kernels are much more convenient from an administration standpoint than kernels that use modules. However, there are size limitations on the kernel binary image, and some features must be compiled as modules. If circumstances demand it, use modules and be glad for them.
Before beginning a kernel configuration, it might be appropriate to examine
the output of the lsmod command. lsmod will list
all loaded modules in the active kernel image. Such a list will both confirm
planned kernel features and list hardware drivers that might have been
neglected or forgotten. Obviously, lsmod will fail if a static
kernel is in use.
Not every kernel configuration option can be covered here. Being aware of the specific problem areas, the administrator must build a kernel, boot with it, then test to see if all required functionality is still available. If something important doesn't work anymore (i.e., network routing, the CD-ROM drive, etc.), then it is likely that the kernel wasn't built with everything it needed.
Now, a brief synopsis of the options in make menuconfig
(help is available on any option through the menus):
/lib/modules, and kernel features that support it can be
loaded as dynamic modules. Enable the kernel module loader if modules
are enabled (so the old kerneld module loader isn't
required).
If modules aren't enabled, remember to comment out the entry in
/etc/cron.d/kmod, otherwise
hourly status messages will be generated by cron concerning module
manipulation failures.
initrd command and it is also useful in
writing CD-ROMs, so it should be built into
the kernel if at all possible.
initrd image will be required.
/proc filesystem is virtually
required - its lack will break many programs. NFS client and server
support can be found under the Network File Systems menu
- NFS server support requires experimental driver support in
the Code Maturity menu.
kernel/redhat.config on the CD-ROM included with this
text. It can be loaded with the above menu options. This configuration
requires an initrd, so modify the SCSI configuration
to compile a driver for your SCSI controller directly into the
kernel if possible.
When all options have been properly configured, exit the menu. A prompt will ask if the changes to the kernel configuration should be abandoned; answer no if everything is correct.
Once the kernel configuration is complete, run the following two commands to clean the source tree and generate the dependency files:
make dep make clean
At this point, one way to generate a new kernel is with the following command:
make zlilo
This command will generate the files /vmlinuz (the zipped
kernel image) and /System.map (a table of symbols from the kernel).
However, because Red Hat Linux installs the kernel in the /boot
directory, this new kernel will not boot. One way to use this new kernel
is to modify LILO to boot from /vmlinuz. Below is an example
of a stock /etc/lilo.conf which is configured to boot a kernel
in the Red Hat Way. This LILO configuration is from an IDE
system which does not use an initrd.
boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=50 image=/boot/vmlinuz-2.2.5-15 label=linux root=/dev/hda5 read-only other=/dev/hda1 label=dos table=/dev/hda
The above /etc/lilo.conf can be modified to boot
/vmlinuz. The label describing the kernel in the boot
directory is renamed to linuxold (the label
is the keyword typed at the LILO boot prompt which selects the operating
system to boot). Then, a new image
stanza is added, describing /vmlinuz.
boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=50 image=/vmlinuz label=linux root=/dev/hda5 read-only image=/boot/vmlinuz-2.2.5-15 label=linuxold root=/dev/hda5 read-only other=/dev/hda1 label=dos table=/dev/hda
Once the file is reconfigured, run /sbin/lilo
to reconfigure the LILO boot manager with the new kernel.
Some other operating systems place kernel images place the kernel image
in a completely separate file system, such as /stand. Refrain
from this behavior in Red Hat Linux.
There are two main reasons why you might not want to use make zlilo in this way. Either you want to follow the Red Hat convention of placing the kernel image in the boot directory, or the make zlilo failed, complaining that the kernel image was too large.
If the image is too large, it can be compressed further by using make bzImage which uses the bzip2 compression format. However, you should make certain that all unnecessary drivers have been removed from the kernel image.
After a successful run of make bzImage, a copy of the
compressed kernel will be stored in
/usr/src/linux/arch/i386/boot/bzImage and a System.map will be
placed in /usr/src/linux. Move these files to the desired
positions (either the root directory or /boot and reconfigure
LILO accordingly).
Do not reboot the system until the modules and the initrd
(if required) are installed. After booting and satisfactory testing of
the new kernel, the generic kernel in /boot can be removed. Use caution, and
do not delete the files required by LILO; do not touch boot.b
or map in the /boot directory.
If modules are enabled in the kernel configuration, they must be
generated in a procedure separate from the kernel preparation. Enter
the following command from /usr/src/linux:
make modules
Once the modules have been compiled, they can be installed with:
make modules_install
This command installs the modules under /lib/modules,
in a directory that has the same name as the kernel release. When moving
the kernel to another Linux system, this set of directories must be
moved also, and they must be placed in the same location on the target
system.
If you are using a SCSI system and you have made the (unwise) decision
to prepare support for your SCSI adapter as a module, an initrd
will be required. Generate it with the following command:
mkinitrd initrd 2.2.11
Below is an example /etc/lilo.conf demonstrating the use of an
initrd. Note further that the generic kernel put down by the
Red Hat installer has been preserved:
boot=/dev/sda map=/boot/map install=/boot/boot.b prompt timeout=50 image=/vmlinuz label=linux root=/dev/sda1 initrd=/initrd read-only image=/boot/vmlinuz-2.2.5-15smp label=linuxold root=/dev/sda1 initrd=/boot/initrd-2.2.5-15smp.img read-only image=/boot/vmlinuz-2.2.5-15 label=linux-up root=/dev/sda1 initrd=/boot/initrd-2.2.5-15.img read-only
If you don't want to go to the trouble of building your own kernel, you can apply errata kernels that are posted by Red Hat. At the time of the publication of this text, the latest version of the kernel that Red Hat would like you to use is 2.2.5, build 22. This version replaces 2.2.5, build 15, which has a bug that allows remote users to crash it.
Red Hat, in previous Linux distributions, included a single kernel RPM, compiled for an 80386 processor, in the Red Hat Linux installation. Starting in Red Hat Linux 6.0, Red Hat now includes several kernels for different types of machines. Following are the kernel packages in the errata:
Red Hat has a long list of steps to upgrade your kernel, but it really isn't that hard. We will assume that a uni-processor Pentium system is to be upgraded. You could enter the following set of commands:
/sbin/modprobe loop.o rpm -ivh kernel-2.2.5-22.i586.rpm /sbin/mkinitrd /boot/initrd-2.2.5-22.img 2.2.5-22
If you are really brave (or crazy), you can use the Uvh option of RPM, which will destroy your present kernel, and prevent LILO from booting the system unless it is reconfigured:
/sbin/modprobe loop.o rpm -Uvh kernel-2.2.5-22.i586.rpm /sbin/mkinitrd /boot/initrd-2.2.5-22.img 2.2.5-22
The Uvh option is probably more realistic for IDE, rather
than SCSI users. If, for some reason, the loopback device is not available,
the mkinitrd will fail.
In either case, before you attempt either of these commands, make sure that you have your boot disk handy. Lost your boot disk? You can create another, before your upgrade, with the following command:
mkbootdisk --device /dev/fd0 2.2.5-15
If I have to tell you that /dev/fd0 is the A: drive on
your PC, you probably aren't ready to be doing a kernel upgrade. You
should also be advised that if you use the Uvh option to
the RPM kernel upgrade command, the loop.o kernel module won't
be available
on your boot disk (if the system crashes).
You could get it out of an older RPM, though. In any case, don't use
the Uvh option unless you're sure that you can get
it right the first time, and you might set aside a copy of loop.o
from your old kernel before you start (it lives in the /lib/modules
directory).
The above mkinitrd command isn't really that important on
IDE systems, but it is deadly important on SCSI systems. Without
the kernel modules in the initrd, the system will not boot.
Once the new kernel is installed, the system is in a precarious state.
LILO should be reconfigured immediately. A reboot between the kernel upgrade and
LILO reconfiguration could range from inconvenient to disasterous. Upgrades
for an IDE system are usually as simple as changing the name of the kernel
image in /etc/lilo.conf:
boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=50 image=/boot/vmlinuz-2.2.5-22 label=linux root=/dev/hda5 read-only other=/dev/hda1 label=dos table=/dev/hda
Alternately, if the Uvh option was not used, the old kernel could be set up as a backup:
boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=50 image=/boot/vmlinuz-2.2.5-22 label=linux root=/dev/hda5 read-only image=/boot/vmlinuz-2.2.5-15 label=linuxold root=/dev/hda5 read-only other=/dev/hda1 label=dos table=/dev/hda
This alternate configuration lets LILO boot the new kernel if linux is entered at the prompt, and the old kernel if linuxold is entered instead (in addition to the dos entry).
A SCSI system is a bit trickier, as the initrd must also
be set:
boot=/dev/sda
map=/boot/map
install=/boot/boot.b
prompt
timeout=50
image=/boot/vmlinuz-2.2.5-22
label=linux
root=/dev/sda1
initrd=/boot/initrd-2.2.5-22.img
read-only
image=/boot/vmlinuz-2.2.5-15
label=linuxold
root=/dev/sda1
initrd=/boot/initrd-2.2.5-15.img
read-only
Once the new /etc/lilo.conf file has been written, don't
forget to run the following command:
/sbin/lilo
Forgetting to rerun LILO before the reboot is a major cause of terror for Linux administrators, which nabs IDE and SCSI users alike.
If you haven't been frightened away at this point, the odds are that you are about to change your kernel. Good luck! Make sure your boot disk is good, and may your LILO never fail you!