Using a GrSecurity Kernel


A logical order exists for implementing a kernel with Grsec. If you've compiled your own kernel before, some of these steps aren't necessary. Truthfully, some of the steps within this section aren't fully required either, but I'll go through them to lessen the chance of something going wrong during the process of getting up to speed with Grsec.

Downloading Grsec and a Fresh Kernel

Both GrSecurity and a fresh kernel need to be downloaded from their respective Internet sites. The kernel source can be downloaded in a few different archive formats with bzip2 being the smallest in download size. Download the kernel source from http://www.kernel.org/. The kernel.org site will contain a few versions of the kernel right on the main home page. I'd recommend using the kernel labeled with a phrase such as "the latest stable kernel." Figure 13.2 contains a look at the kernel.org home page so that you can see the area to which I'm referring. The kernel can be downloaded by clicking on the link labeled "F" (which is an abbreviation for "Full").

Figure 13.2. The kernel.org site. You should look for the latest stable kernel.


The kernel source will take a few minutes to a few hours to download, depending on the speed of your Internet connection. It will be downloaded in a bzip2-formatted tar archive.

Grsec is downloaded from the GrSecurity website at http://www.grsecurity.net/. Grab the latest stable Grsec patch. This file will download very quickly because it's just a patch containing the differences between it and the main kernel that you just downloaded.

Compiling Your First Kernel

Before you apply the Grsec patch, it will be helpful for you to get a working customized version of the kernel going on the computer. After the new kernel is up and running, I'll show how to apply the patch. This section examines how to compile a kernel from the vanilla source.

A good place to start when considering how to approach your first kernel compile is the Kernel-HOWTO or the Kernel Rebuild Guide. The Kernel-HOWTO is located at http://www.tldp.org/HOWTO/Kernel-HOWTO/index.html; the Kernel Rebuild Guide is currently located at http://www.digitalhermit.com/~kwan/kernel.html. These documents provide valuable insight and tips for first-time kernel compilers.

The first thing to do is to unpack the kernel sources into the right place. Normally Linux kernel source files are stored in /usr/src within a directory called linux. When you unpack the kernel source, it'll be named something like linux-N.N.NN. I'll show you how to create a symbolic link (it's like a shortcut in Windows) to link that directory to /usr/src/linux.

Copy the source files that you downloaded into /usr/src. For example, for kernel 2.6.4 the command is this:

 cp linux-2.6.4.tar.bz2 /usr/src 

Unpack the Linux kernel source using a combination of bzip2 and tar, like this (don't forget to change into the /usr/src directory):

 bunzip2 -c linux-2.6.4.tar.bz2 | tar -x 

You'll now have a directory containing the uncompressed Linux kernel source code. Traditionally the source code is stored in /usr/src/linux but the kernel source was unpacked to /usr/src/linux-2.6.4. To solve this problem, make a symbolic link, sometimes called a symlink:

 ln -s linux-2.6.4 linux 

Now there will be a symlink in the traditional spot that you can cd into:

 cd /usr/src/linux 

Or just use this:

 cd linux 

When you attempt to run the ln command, you may receive an error saying that the file linux already exists. If this is the case, it appears that you already have kernel source lying around in the directory. For example, in SUSE if you install the kernel source during initial installation, it will be unpacked to a directory within /usr/src, and then a symlink is created to /usr/src/linux. The symlink can safely be removed so that you can re-create it for linking to your kernel source. If you received the error about linux already existing when you attempted to create the symlink, delete the old one with the command (from within /usr/src):

 rm linux 

There are three primary methods for configuring the options to include with the customized kernel, and all three are based on the options presented in the Linux kernel Makefile. When configured, the options you choose (and don't choose) are stored in a file called .config within the Linux kernel source-code directory:

 make config make menuconfig make xconfig 

Additionally, there's a method called oldconfig to update the configuration to a new version by using an old version of the config file. This function is quite helpful for upgrading between minor versions of the kernel without having to start from a vanilla configuration and possibly forgetting to compile in some vital bits here or there. The oldconfig method assumes that you have the old configuration already located in the kernel source directory (/usr/src/linux in the examples here) and that the configuration file is called .config within that directory. You can update to the new kernel with the oldconfig method by typing this:

 make oldconfig 

The method you choose to configure the kernel is at least somewhat a matter of personal preference, but the result of the computer's configuration as well. You can't use xconfig if you don't have X Windows installed. Likewise, menuconfig requires some ncurses libraries that are usually, but not always, installed. The standard config option for compiling a kernel will always work, but it's also the most cumbersome, especially for newcomers.

All things considered, I recommend menuconfig as the option to use for configuration of the kernel. Menuconfig can be used regardless of whether the computer has X Windows, and it can be used through a remote SSH connection as well. However, if you have an existing version of a configuration file, I recommend using oldconfig first and then using menuconfig to further tune the configuration options.

You should spend some time determining the hardware in the computer as well as the kernel driver responsible for that hardware's operation. The program /sbin/lspci will show the current PCI hardware configuration, which you can then use to find out which drivers are necessary to run that hardware. Also, examine /proc/cpuinfo using a pager such as less or more or another program such as cat:

 cat /proc/cpuinfo 

This will tell you the type of processor you have so that you can choose the appropriate architecture in that area of the kernel config. Keep track of this information and use a tool such as Google to determine the appropriate Linux drivers that correspond to the hardware in the computer.

You can frequently find a copy of the kernel configuration for the current kernel within the /boot directory. For example, in SUSE the file will be located in /boot and named vmlinuz.config. To incorporate this configuration as a starting point for your new kernel, copy this file into the /usr/src/linux directory:

 cp -i /boot/vmlinuz.config /usr/src/linux/.config 

If the command runs correctly, you won't receive any feedback; silence indicates success. However, if you receive a question asking whether to overwrite an existing .config, cancel out of the copy operation and find out why there is an existing configuration file in /usr/src/linux. This might be caused if you didn't delete the symlink to a previous kernel in /usr/src/linux or if you've already run one of the make options for a kernel. When you run make for a kernel, it will save a new copy of the .config file, so if you've already run a kernel compile process, chances are you don't want to overwrite that configuration file with a default one.

After you've copied the default configuration file over, it's wise to run the oldconfig process on the config file to update it to the new version of the kernel. From within the /usr/src/linux directory, run the following:

 make oldconfig 

You'll be asked several questions, based on the differences between the existing (default) configuration file that you just copied over and the new configuration options available with this version of the kernel. The oldconfig process is accomplished through a text-based interface, so you'll see things like this:

 Kernel support for ELF binaries (CONFIG_BINFMT_ELF) [Y/m/n/?] Kernel support for MISC binaries (CONFIG_BINFMT_MISC) [M/n/y/?] Select task to kill on out of memory condition (CONFIG_OOM_KILLER) [N/y/?] (NEW) 

As each new feature is encountered within the new kernel, you'll be asked whether you'd like to include the feature in the new kernel. It's almost always safe to assume the defaults by just pressing Enter for these options, unless you're looking for some specific functionality with the new kernel.

After you get through all the oldconfig process, you'll be placed back at the command prompt within /usr/src/linux. You've now reached another fork in the road. If you'd like, you can jump into the menuconfig interface (make menuconfig) to further customize the drivers and features included in your kernel. If you'd like to try compiling the kernel without that additional customization, you can do so right now as well. I strongly recommend that you do go into the menuconfig process to ensure that the correct drivers are included for your hardware. If you choose to skip the menuconfig process, the chances of a failed boot increase.

If you choose to enter into the menuconfig process, you'll have a chance to further customize the kernel through a friendlier interface than the oldconfig process. The menuconfig interface makes it easier to access help for the various kernel options as well.

Within the menuconfig interface, walk through each of the options by pressing Enter; using the keyboard arrows; using Tab to move among Select, Exit, and Help; using the spacebar to select or deselect; and pressing Esc to back up. Be careful not to press Esc too many times because that's also how you exit. While you're configuring through the menuconfig interface, look specifically for drivers that relate to your hardware and make sure that they are included in the kernel, as indicated by an asterisk (*). For example, I have a network card that's based off of the AMD PCNet32 driver, so I need to include this in the kernel. I navigate to Network Device Support; then Ethernet (10 or 100Mbit); and then EISA, VLB, PCI and On Board Controllers; and then make sure that AMD PCnet32 PCI Support is checked by pressing the spacebar.

When you're ready to begin the actual build process, there are three primary commands used to build the kernel. Actually, for now, most likely four commands will be used because I'm going to assume that modules are included in the default kernel that you're building. Eventually, when you disable modules for added security, you won't have to run the final make command that I'll show because it's just used to build the modules.

The first build step generates the dependencies. From within the /usr/src/linux directory, type the following:

 make dep 

This command should run relatively quickly. Continue the build process by typing this:

 make clean 

The make clean step is also somewhat fast, obviously depending on the available resources. Finally, create the kernel itself by typing this:

 make bzImage 

The bzImage option compresses the kernel using bzip2. Another alternative used on systems without bzip2 is make zImage, which uses gzip instead of bzip2. Because you have bzip2 on this system (you had to in order to uncompress the kernel source), you can use bzImage.

The kernel will now compile. This process will take a varying amount of time depending on a couple factors. First and foremost, the speed of and load on the processor(s) and available RAM will be the biggest factors that will determine the amount of time that the kernel will take to compile. On a hardly used dual-Intel Xeon processor machine with 1GB RAM, the kernel takes less than five minutes to compile. On the other hand, an Intel Pentium 60 with 24MB RAM will take many hours to compile the kernel. The second factor in determining the amount of time a kernel takes to compile is the number of options you included with the kernel. Adding SMP code and many (possibly unnecessary) drivers will cause the compile time to increase.

Sit back and relax or go do something else while the kernel is compiling. Now is a good time to read the kernel HOWTO that I recommended earlier, that is, if you haven't already read it. Hopefully the kernel compile won't fail with an error, though this does sometimes happen. Usually it's due to a troublesome driver or a conflict between two drivers. You'll know that the compile failed if the kernel stops compiling and you're left with something like this on the screen:

 Error 1 ***[make]*** Error 2 

If this happens, examine the last few lines above the errors to see whether you can discern in which portion of the kernel compile the error occurred. Many times the name of the file that was compiling is shown within the text on the screen. Also, examine the end of the file config.log within /usr/src/linux to see whether there is any information in there. If necessary, copy the contents of any error messages into a search engine like Google to see whether someone else has encountered the problem. One of the biggest strengths of open-source software is the availability of help online within forums and Google for just this sort of thing.

If the kernel compile fails with an error, you'll need to trace down the troublesome driver(s) or area of the kernel and deselect the drivers or exclude them. When you believe you've found the cause of the error, the first task is to clean up the environment and start over. Countless compiles of software fail because the administrator didn't clean up the source tree after a failed compile. Before undertaking this process, you should copy the existing .config configuration file to a safe location. The clean up process will delete the .config file, so if you've made customizations they'll be lost.

To clean up the kernel source tree, type the following:

 make mrproper 

The environment will now be clean just as if you had unarchived fresh kernel source. Start the process over from the beginning by copying the existing configuration file (usually in /boot) into the kernel source tree and follow the steps as before. This time, however, go into the menuconfig interface and deselect the troublesome drivers or other parts of the kernel that you believe caused the failure.

Whew. Hopefully nothing goes wrong! If the kernel stops compiling and you didn't receive any errors, you'll see something close to this on the screen (your text will vary):

 tools/build -b bbootsect bsetup compressed/bvmlinux.out CURRENT >bzImage Root device is (8, 2) Boot sector 512 bytes. Setup is 4769 bytes. System is 1086 kB warning: kernel is too big for standalone boot from floppy make[1]: Leaving directory `/usr/src/linux-2.4.25/arch/i386/boot' 

Congratulations, the kernel compiled. Because this is your first kernel and you've used the default configuration file, the kernel that's compiling most likely requires modules in order to run. As you become more comfortable with compiling kernels, I recommend that you compile a monolithic kernel rather than including modules for server environments.

There's less of a chance of an attacker injecting his own code into the kernel if the capability to use modules isn't even included in the kernel. However, the reality of the situation is that modular kernels are the de facto standard for installed kernels today. Therefore, you'll need to compile and install the modules as part of the kernel build process.

After you compile the necessary drivers into the kernel rather than including them as modules, the module-related steps will no longer be necessary as part of the kernel build process. After the kernel itself compiles successfully, the next step is to compile the modules. This is accomplished with the following command:

 make modules 

The module compile process will take a varying amount of time depending on the factors discussed earlier for kernel compile time. The same caveat and troubleshooting steps also apply in relation to the module compile as well. If the module compile fails with an error, track down the troublesome module code and deselect it, or, if it's necessary for your system to run, try including it within the kernel itself rather than including it as a module.

The module compile process will complete without much fanfare, probably something like this:

 make[1]: Entering directory `/usr/src/linux-2.4.25/arch/i386/lib' make[1]: Nothing to be done for `modules'. make[1]: Leaving directory `/usr/src/linux-2.4.25/arch/i386/lib' 

If you see anything resembling the word Error, the module compile didn't complete successfully.

Assuming that the modules compiled, install the modules by typing this:

 make modules_install 

Now it's time to install the new kernel. The kernel is installed within an architecture-independent directory structure. Allow me to assume that the architecture you're using is an Intel x86-based type of computer. If that's the case, your kernel is located in /usr/src/linux/arch/i386/boot. Because you should already be in the /usr/src/linux directory, you can copy the new kernel to its home in /boot with the command as follows, substituting the kernel version for <version>:

 cp -i arch/i386/boot/bzImage /boot/vmlinuz-<version> 

For example, to copy a compiled kernel version 2.4.25, you'd type this:

 cp -i arch/i386/boot/bzImage /boot/vmlinuz-2425 

When using a modularized kernel, the computer frequently requires an initial ramdisk, known as initrd, to successfully preload modules required for the computer to boot. This is often the case when disk or disk controller drivers are included as modules rather than compiled directly into the kernel. If you're using a modular kernel, you'll also need to create the initial ramdisk before attempting to boot. The initial ramdisk is created with the mkinitrd program. The use of the mkinitrd program is slightly different with various flavors of Linux.

Assume that you've compiled a modularized kernel version 2.4.25, compiled the modules, and installed them. Now it's time to create an initrd for that kernel. The new kernel has been copied to /boot/vmlinuz-2425. There's also an existing kernel named /boot/vmlinuz. In SUSE, you'd accomplish this task with the following command:

 mkinitrd -k "vmlinuz vmlinuz-2425" -i "initrd initrd-2425" 

The initrd files will be created in /boot and named initrd and initrd-2425 for the existing and new kernels respectively.

The next step depends entirely on whether your version of Linux uses the Lilo or Grub boot loader. I'll include instructions for both Lilo and Grub, but you only have to follow the one that applies to your computer.

Here's how to tell which loader you're using. Find out whether you're running Lilo by typing this command:

 ls /etc/lilo.conf 

If you receive an error similar to the following, you're probably running Grub:

 ls: /etc/lilo.conf: No such file or directory 

NOTE

It's possible to have both Lilo and Grub installed, so finding lilo.conf does not 100% guarantee that you are using Lilo. If you're in doubt, most boot loaders such as Lilo and Grub will identify themselves when you boot the system.


First I'll handle adding the new kernel to the Grub menu for boot. Edit the Grub menu file, usually /boot/grub/menu.lst, in your favorite text editor. Within the menu.lst file, you'll see sections relating to the current kernel. Simply copy and paste one of those existing sections. Be careful so as not to alter any of the existing lines in the file. For example, you might add the following lines:

 title customlinux    kernel (hd0,1)/boot/vmlinuz-2425 root=/dev/sda2    initrd (hd0,1)/boot/initrd-2425 

Note that your hd and root devices will probably be different. Look at what's there already and simply copy it. For Grub, that's all you need to do. You can reboot the computer by typing reboot or shutdown -r now.

The process is similar for Lilo. Edit the file /etc/lilo.conf, find an existing section related to the current kernel, copy the section, and paste it back in, being careful not to alter any existing lines of the Lilo configuration file. An example in the Lilo configuration file might be something like this:

 image=/boot/vmlinuz         label=Linux         read-only 

One additional step is necessary after you're done editing the Lilo configuration file, and that's to run the Lilo program. This step is overlooked by many an administrator. At the command prompt, simply type this:

 lilo 

You'll see output similar to the following:

 Added Linux * Added LinuxOLD 

The asterisk (*) indicates the kernel that will load by default. Now you can reboot the computer by typing reboot.

WHAT HAPPENS IF THERE'S A PROBLEM?

When you've compiled a kernel, there is always a chance that the computer won't boot when you attempt to reboot using the new kernel. This will be evidenced by a few different error conditions, the end result of which will be that the computer won't get booted fully into Linux. You may receive an error on the console such as this:

 Kernel panic:  Unable to mount root fs 

If this happens, don't spend too much time worrying. Write down the error message along with key words from lines preceding the error. Power down the computer and start it again, this time selecting the old kernel when presented with the Lilo or Grub prompt. The computer will boot as it did before.

Another problem that's not as noticeable is when the computer boots but some functionality is missing. This occurs frequently when the incorrect network drivers are compiled into the kernel and the networking won't work, but many other driver-related issues might show up as well.

Unfortunately, if you do get a kernel panic or choose an incorrect driver, it means that you'll end up having to start the kernel compile process over. Use your troubleshooting skills to try to determine the problem or, in other words, what wasn't included in the kernel that should've been.

There's no magic bullet to fix the new kernel. It will take your solid troubleshooting skills along with patience. Again, people who are experienced in working with the kernel can still have problems with the first kernel on a new computer. So don't feel bad if it happens to you!

Improving the Kernel Build

If everything has gone according to plan, the new kernel will be booted and devices such as networking will work correctly. You can confirm the kernel that the computer is using with the following command:

 uname -a 

If the version reported doesn't match the version that you compiled in the previous steps, verify that you placed the kernel in the correct place in the Grub configuration or that you chose the right kernel to boot from either the Lilo or the Grub prompt. Also, if you're running Lilo, did you remember to run the lilo command after editing the Lilo configuration file? It's a frequent oversight.

From here, it's up to you whether you want to improve the kernel compile to add further customization for the computer. From both server administration and security standpoints, improving the kernel compile is a good idea.

As starting points, I recommend removing support for modules and compiling the necessary drivers directly into the kernel. You'll probably find that many of the drivers compiled in as modules are actually unnecessary. Again, a monolithic kernel reduces the attack paths available by making it impossible for an attacker to inject a trojaned module.

I also recommend using a minimum set of drivers that match the computer's hardware and role. For example, is printer support really necessary on a Linux server that acts solely as a web server? Probably not. Therefore, these drivers can be removed from the kernel. Not only will the kernel be smaller and use less resources, but the attack path through those drivers will also be removed.




Linux Firewalls
Linux Firewalls: Attack Detection and Response with iptables, psad, and fwsnort
ISBN: 1593271417
EAN: 2147483647
Year: 2005
Pages: 163
Authors: Michael Rash

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net