Don't be shy. A kernel stripped down to the bare essentials is a happy kernel.
Picture the typical day in the life of a system administrator. Your mission, if you choose to accept it, is to achieve the impossible. Today, you're expected to:
Although there are many ways to go about this, the most efficient way is to strip down the kernel to its bare-bones essentials. Having this ability gives an administrator of an open source system a distinct advantage over his closed source counterparts.
The first advantage to stripping the kernel is an obvious security boost. A vulnerability can't affect an option the kernel doesn't support. The second is a noticeable improvement in speed and performance. Kernels are loaded into memory and must stay in memory. You may be wasting precious memory resources if you're loading options you have no intention of ever using.
If you've never compiled a kernel or changed more than one or two kernel options, I can hear you groaning now. You're probably thinking, "Anything but that. Kernels are too complicated to understand." Well, there is a lot of truth in the idea that you haven't really used an operating system until you've gone through that baptism of fire known as kernel compiling. However, you may not have heard that compiling a kernel isn't all that difficult. So, grab a spare afternoon and a test system; it's high time to learn how to hack a BSD kernel.
I'll demonstrate on a FreeBSD system, but you'll find resources for other systems at the end of this hack.
Before you start, double-check that you have the kernel source installed. On an Intel FreeBSD system, it lives in /usr/src/sys/i386/conf. If that directory doesn't exist, become the superuser and install it:
# /stand/sysinstall Configure Distributions spacebar [ ] src to select it spacebar [ ] sys to select it tab to OK
Next, navigate into that directory structure and check out its contents:
# cd /usr/src/sys/i386/conf # ls ./ GENERIC.hints OLDCARD gethints.awk ../ Makefile PAE GENERIC NOTES SMP
Two files are important: the original kernel configuration file, GENERIC, and NOTES. Note that NOTES is instead called LINT on 4.x FreeBSD systems.
6.2.1 Customizing Your Kernel
Customizing a kernel is a very systematic process. Basically, you examine each line in the current configuration file, asking yourself, "Is this applicable to my situation?" If so, keep it. Otherwise, remove it. If you don't know, read NOTES for that option.
I always customize my kernel in several steps. First, I strip out what I don't need. Then, I use buildkernel to test my new configuration file. If it doesn't build successfully, I know I've inadvertently removed something essential. Using the error message, I go back and research that missing line.
If the build succeeds, I read through NOTES to see if there are any options I wish to add to the kernel. If I add anything, I'll do another buildkernel, followed by an installkernel if the build is successful. I find it much easier to troubleshoot if I separate my deletions from my additions.
Let's copy over GENERIC and see about stripping it down:
# cp GENERIC STRIPPED # vi STRIPPED # # GENERIC -- Generic kernel configuration file for FreeBSD/i386 # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES.
188.8.131.52 CPU options
The first thing you'll notice is that this file is very well commented. It's also divided into sections, making it easier to remove things such as ISA NIC, SCSI, and USB support. The first section deals with CPU type:
machine i386 cpu I486_CPU cpu I586_CPU cpu I686_CPU ident GENERIC
Whenever you come across a section you're not sure about, look for that section in NOTES. Here, I'll search for CPU:
# grep CPU NOTES
Your output will include a few pages worth of CPU information. The first few lines describe which CPUs belong with the I486, I586, and I686 entries. Once you find your CPU, remove the two entries that don't apply. If you're not sure what type of CPU is installed on the system you're configuring, try:
# grep CPU /var/run/dmesg.boot CPU: Intel(R) Pentium(R) III CPU 1133MHz (1138.45-MHz 686-class CPU) acpi_cpu0: <CPU> port 0x530-0x537 on acpi0
Since a Pentium III is considered to be an I686_CPU, I'll remove the I486_CPU and I586_CPU lines from this system's configuration file.
The rest of the output from grep CPU NOTES contains extra lines that can be added to the kernel. Read through these to see if any apply to your specific CPU and the needs of the machine you are configuring. If so, make a note to try adding these later.
184.108.40.206 System-specific options
The next section contains a heck of a lot of options. If this is your first kernel, most of your research will be deciding which options you need for your particular system. I find the handbook most helpful here, as it lists the pros and cons of nearly every option. I always keep these options on all of my systems:
options SCHED_4BSD # 4BSD scheduler options INET # InterNETworking options FFS # Berkeley Fast Filesystem options COMPAT_FREEBSD4 # Compatible with FreeBSD4 options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
Note that that last listed option tells you to keep it. Do keep anything that contains such a comment.
The rest of the options are specific to that system's needs. For example, does it need to support IPv6? Do you wish to use softupdates or the new MAC framework? Does this system need to be an NFS server or NFS client? Does this system have a CD-ROM attached or any SCSI devices?
Does the system have multiple processors? If so, uncomment the next two lines; otherwise, you can safely remove them:
# To make an SMP kernel, the next two are needed #options SMP # Symmetric MultiProcessor Kernel #options APIC_IO # Symmetric (APIC) I/O
220.127.116.11 Supported buses and media devices
The next section deals with devices. First, we start with the buses:
device isa device eisa device pci
If you grep device NOTES, you'll see that you can also add the agp and mca buses if your system requires them. If your system doesn't use the isa or eisa buses, you can remove those lines.
If you wish to disable floppy support on your server, removing these lines will do it:
# Floppy drives device fdc
Next, does your server use IDE or SCSI devices? If it uses IDE, the next section applies:
# ATA and ATAPI devices device ata device atadisk # ATA disk drives device atapicd # ATAPI CDROM drives device atapifd # ATAPI floppy drives device atapist # ATAPI tape drives options ATA_STATIC_ID # Static device numbering
Remember, you can remove the CD-ROM, floppy, and tape lines to suit your requirements. However, keep the other lines if you use an IDE hard drive. Conversely, if your system is all SCSI, delete the ATA lines and concentrate on this section:
# SCSI Controllers device ahb # EISA AHA1742 family device ahc # AHA2940 and onboard AIC7xxx devices <snip>
Keep the entries for the SCSI hardware your system is using, and remove the entries for the other devices. If your system doesn't have SCSI hardware, you can safely delete the entire SCSI section.
The same logic applies to the following RAID section:
# RAID controllers interfaced to the SCSI subsystem device asr # DPT SmartRAID V, VI and Adaptec SCSI RAID device ciss # Compaq Smart RAID 5* device dpt # DPT Smartcache III, IV - See NOTES for options! device iir # Intel Integrated RAID device mly # Mylex AcceleRAID/eXtremeRAID
and for the SCSI peripherals and RAID controllers sections:
# SCSI peripherals device scbus # SCSI bus (required) device ch # SCSI media changers <snip> # RAID controllers device aac # Adaptec FSA RAID device aacp # SCSI passthrough for aac (requires CAM) <snip>
18.104.22.168 Peripheral support and power management
The next few entries are usually keepers as it's always nice to have a working keyboard, unless you're using a headless system [Hack #26] .
# atkbdc0 controls both the keyboard and the PS/2 mouse device atkbdc # AT keyboard controller device atkbd # AT keyboard
The next line depends on whether you're using a serial or a PS/2 mouse:
device psm # PS/2 mouse
You'll probably want to keep your video driver:
device vga # VGA video card driver
However, you'll probably remove the splash device, unless you plan on configuring a splash screen [Hack #24] .
device splash # Splash screen and screen saver support
You'll have to choose a console driver. It can be either the default SCO driver or the pcvt driver (see the handbook for details):
# syscons is the default console driver, resembling an SCO console device sc # Enable this for the pcvt (VT220 compatible) console driver #device vt #options XSERVER # support for X server on a vt console #options FAT_CURSOR # start with block cursor
The next options refer to power management on laptops, as well as laptop PCMCIA cards. Unless your server is a laptop, you can remove these:
# Power management support (see NOTES for more options) #device apm # Add suspend/resume support for the i8254. device pmtimer # PCCARD (PCMCIA) support # Pcmcia and cardbus bridge support device cbb # cardbus (yenta) bridge #device pcic # ExCA ISA and PCI bridges device pccard # PC Card (16-bit) bus device cardbus # CardBus (32-bit) bus
Do you plan on using your serial and parallel ports? If not, the next section allows you to disable them:
# Serial (COM) ports device sio # 8250, 1650 based serial ports # Parallel port device ppc device ppbus # Parallel port bus (required) device lpt # Printer device plip # TCP/IP over parallel device ppi # Parallel port interface device #device vpo # Requires scbus and da
22.214.171.124 Interface support
Now it's time to support your system's NICs. Here's one way to find out the device names of your interfaces:
# grep Ethernet /var/run/dmesg.boot rl0: Ethernet address: 00:05:5d:d2:19:b7 rl1: Ethernet address: 00:05:5d:d1:ff:9d ed0: <NE2000 PCI Ethernet (RealTek 8029)> port 0x9800-0x981f irq 10 at device 11.0 on pci0
Once you know which interfaces are in your system, remove the NICs that aren't. If your system doesn't contain any ISA or wireless NICs, you can safely remove those entire sections.
Do make note of this comment, though:
# PCI Ethernet NICs that use the common MII bus controller code. # NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! device miibus # MII bus support device dc # DEC/Intel 21143 and various workalikes <snip>
Any NICs underneath that comment require that miibus entry. If you forget it, your kernel won't build. Fortunately, the error message will have the word miibus in it.
Next come the pseudodevices. If you plan on using encryption, keep the random device. You'll probably also need to keep the loop and ether devices.
If you use an analog modem to connect to your service provider, keep the ppp and tun devices. Otherwise, remove them, along with the slip device.
Several applications including emacs, xterm, script, and the notorious telnet require the pty device. Depending upon the use of your server, you may be able to remove that device. If it breaks needed functionality, you can always recompile it back into your kernel.
Are you planning on using memory disks? If not, you can remove md. If you're not sure, try reading man mdmfs.
If you previously removed IPv6 support with options INET6, you might as well remove these two devices as well:
device gif # IPv6 and IPv4 tunneling device faith # IPv6-to-IPv4 relaying (translation)
The next device has some security implications, as it is required in order to run a packet sniffer such as tcpdump. However, it's also required if your system is a DHCP client. If neither applies, remove the bpf device:
# The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! device bpf # Berkeley packet filter
126.96.36.199 USB support
Does your system have any USB devices? If so, you need a host controller as well as USB bus support. First, determine which type of USB host controller you have. man uhci and man ohci describe which hardware goes with which controller. Once you've found your hardware, keep the appropriate interface entry:
# USB support device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface
Also, don't forget to keep that USB bus line:
device usb # USB Bus (required)
Are you confused about the next three USB options? Fortunately, each has a manpage. Try man udbp, man ugen, and man uhid to see if any apply to your particular situation.
#device udbp # USB Double Bulk Pipe devices device ugen # Generic device uhid # "Human Interface Devices"
Next, keep the devices you have installed and remove the rest. Again, note that USB NICs need that miibus entry we saw earlier. Also, some entries require device scbus and device da. Double-check your SCSI sections. If you removed these devices earlier and need them, add them to this section.
device ukbd # Keyboard device ulpt # Printer device umass # Disks/Mass storage - Requires scbus and da device ums # Mouse device urio # Diamond Rio 500 MP3 player device uscanner # Scanners # USB Ethernet, requires mii device aue # ADMtek USB ethernet device axe # ASIX Electronics USB ethernet device cue # CATC USB ethernet device kue # Kawasaki LSI USB ethernet
Finally, the only option group left is Firewire support. If you need it, keep the entire section, and double-check that you have a device scbus and device da entry somewhere in your configuration file. If you don't need Firewire support, remove the entire section:
# FireWire support device firewire # FireWire bus code device sbp # SCSI over FireWire (Requires scbus and da) device fwe # Ethernet over FireWire (non-standard!)
Whew. We finally made it through the configuration file. Congratulations! You now have a much better idea of the hardware on your system and can rest easily in the knowledge that soon no extra drivers will be wasting memory resources. Not only that, your next kernel configuration will go much more quickly as you've already researched the possibilities.
6.2.2 Building the New Kernel
Now comes the moment of truth. Will the configuration file actually build? To find out:
# cd /usr/src # make buildkernel KERNCONF= STRIPPED
Replace STRIPPED with whatever name you called your kernel configuration file. If all goes well, you should just get your prompt back after a period of time, which varies depending upon the speed of your CPU. If you instead get an error message, you probably forgot miibus, scbus, or da, and the message will reflect that. Add the missing line and try again.
Occasionally you'll get a kernel that just refuses to build, even when you're sure the configuration file is fine. If that's the case, try building GENERIC. If that fails, you have a hardware issue.
I once inherited a system with a flaky motherboard. I tried a few kernel compiles, which took forever before finally resulting in an error code 1. Fortunately, I use removable drives, so I simply inserted the drive into another system, successfully compiled the kernel, and then returned the drive to the flaky system for the actual kernel install.
6.2.3 Keeping Track of Your Options
Once I have a successful build, I like to document what I removed from the original kernel. This is easily done:
# echo "These are the lines I deleted" > changes.txt \ & diff GENERIC STRIPPED >> changes.txt
The diff utility will list the differences between the original and my version of the kernel configuration file. Note that I used >> to append those differences without removing my previously echoed comment. See [Hack #92] for more examples that use diff.
Before installing the kernel, read through NOTES to see if there are any lines you wish to add. Additionally, if you wish to take advantage of memory addresses over 4 GB, carefully read through PAE and its section in the handbook to see if it is appropriate for your situation.
If you add any lines, repeat the make buildkernel command when you are finished. I also like to append my additions to my changes.txt file:
# echo "And these are the lines I added" >> changes.txt \ & diff GENERIC STRIPPED >> changes.txt
Note that this time it is very important I remember to append both my comment and the output of diff by using two > characters.
6.2.4 Installing the New Kernel
Now, let's install the kernel:
# cd /usr/src # make installkernel KERNCONF=STRIPPED
This process is much quicker than building the kernel. However, the kernel won't actually be loaded into memory until you reboot. Before you do that, it's always a good idea to print out the "If Something Goes Wrong" page of the FreeBSD Handbook, just in case something goes wrong. See http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-trouble.html#KERNELCONFIG-NOBOOT.
It's rare that a kernel will install but not boot, but it never hurts to be prepared ahead of time.
6.2.5 See Also