Kernel Alteration with config(8)


While sysctl will let you perform minor tweaks on the kernel, it won't let you change certain values hard-coded into the kernel binary. Some of these values are used to create initial data structures within the kernel and cannot be changed once the kernel is up and running. Others relate to device drivers. The sysctl interface simply cannot handle these sorts of changes; you need to edit the existing kernel file and reboot, allowing the system to start over from scratch and set things up as you want them. That's where config(8) comes in.

What Is Config(8)?

The config(8) program has two completely separate functions. The first builds a kernel compilation directory from a text configuration file, which we'll look at in Chapter 12. The function we're interested in now is to edit an existing kernel binary, allowing the sysadmin to tweak the kernel in any number of ways even after it's built.

Preparation

Before you make any changes to your working kernel, no matter how minor, be utterly sure you make a backup copy! In the worst case, you want to be absolutely certain that you have a kernel that will boot. The kernel is just a file, /bsd by default. Copy that to another file. I recommend naming backup kernels after the kernel configuration they were built from. The default OpenBSD kernel configuration is named GENERIC, as you see when the system boots.

 # cp /bsd /bsd.GENERIC 

Always keep a known-good kernel on your system. A bad kernel can prevent a computer from booting, and if you don't have a reliable one on hand your computer will need to be partially or completely reinstalled. (A bad kernel can also damage your data, your file system, or anything else on your computer, which means you'll be reinstalling anyway, but that's fairly rare.) You can boot off this backup kernel by following the instructions back in Chapter 6. Kernel bugs can take weeks or months to show up, so keep a default GENERIC kernel on hand forever.

Also, the OpenBSD boot loader will look for /bsd.old if it has problems loading /bsd. You can keep backup kernels here. On those occasions when I must customize my kernel I often use /bsd as my test kernel, /bsd.old as a proven custom kernel, and /bsd.GENERIC as the provided GENERIC kernel. That way, the system has a better chance of actually booting should I make a mistake with the kernel.

Device Drivers and Config

Most of the hard-coded information in the kernel relates to device drivers, especially device drivers for older ISA cards. If you've been using a computer for a long time you probably remember manually setting IRQs and memory port addresses on your first network card. The kernel uses these bits of information to identify each card. Essentially, the kernel consults an internal list of IRQs and port numbers, compares it to what it found on its hardware probe, and assigns the drivers appropriately. "This card answers at IRQ 10 and memory port 0x300? Well, it must be a NE2000-compatible network card then! Let me assign that driver to it." (It's more complicated than this, of course, but this probe and table is a vital part of the process.) If you want OpenBSD to recognize such a card, you need to tell the kernel which driver to assign to the IRQ and memory port.

Note

In the appendix, I discuss the various device drivers available in OpenBSD and how to find documentation about them. For now, when I say that a particular device driver works on a particular piece of hardware, just nod and smile and go along with it.

Editing the Kernel with config

When editing kernels with config, there are three command-line options you need to worry about. The "-e" flag tells config that you're editing a kernel binary; none of the examples in this section will use if you omit that flag. Then you need one of either "-f" or "-o". The "-f" flag tells config(8) to edit the kernel file in place — that is, if you're editing the kernel file /bsd, when you're finished the edited copy will still be /bsd. As a rule, I do not recommend doing this. The "-o" flag lets you specify another location to write your edited kernel. The last argument config(8) requires is the name of the kernel binary to be edited. In the following example, we're editing the file /bsd and writing our edited copy to the file /bsd.test.

 # config -e -o /bsd.test /bsd OpenBSD 3.1 (GENERIC) #59: Sat Apr 13 15:28:52 MDT 2002     deraadt@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC Enter 'help' for information ukc> 

The first two config(8) commands you should become familiar with are "help" and "list." The help command lists all the commands available inside the config kernel editor. We will walk through all of these later in the section, but it's good to have a reminder close at hand.

The list command gives a complete list of all the devices configured inside the kernel, one screen at a time.

 ukc> list   0 audio* at sb0|sb*|gus0|pas0|sp0|ess*|wss0|wss*|ym*|eap*|eso*|sv*|neo*|cmpci*| clcs*|clct*|auich*|autri*|auvia*|fms*|uaudio*|maestro*|esa*|yds*|emu* flags 0x0   1 midi* at sb0|sb*|opl*|opl*|opl*|opl*|ym*|mpu*|autri* flags 0x0   2 nsphy* at aue*|xe*|ef*|gx*|stge*|bge*|nge*|sk*|ste*|sis*|sf*|wb*|tx*|tl*|vr*| ne0|ne1|ne2|ne*|ne*|ne*|dc*|dc*|rl*|fxp*|fxp*|xl*|xl*|ep0|ep0|ep0|ep*|ep*|ep*|ep*| ep* phy -1 flags 0x0 ... 

Hit ENTER to see the next screen. On an OpenBSD 3.1 system, the standard kernel has 278 entries. Most entries are for hardware that isn't on any one particular system but that OpenBSD supports out of the box.

What Entries Mean

Let's consider a few lines from the kernel configuration editor.

   0 1 audio* at 2 sb0|sb*|gus0|pas0|sp0|ess*|wss0|wss*|ym*|eap*|eso*|sv*|neo*| cmpci*|clcs*|clct*|auich*|autri*|auvia*|fms*|uaudio*|maestro*|esa*|yds*| 3 emu* 4 flags 0x0 

Line 0 shows the kernel's support for the 1 audio(4) device driver. OpenBSD's audio driver attaches to any of a variety of cards, shown here separated by pipe symbols. The list ranges from 2 sb0 (SoundBlaster device zero) to 3 emu* (any Creative Labs SBLive! card, at any device number). At the end of the line, we have 4 flags that are given to the driver. Flags tweak a driver's behavior. We'll see examples of how flags work later in this chapter. While this line is quite long, all it really means is that the audio driver is installed, it will attach to any of a wide variety of sound cards, and it has the default flag settings.

 141 1 ne0 at 2 isa0 3 port 0x240 size 0 iomem -1 iosiz 0 4 irq 9 drq -1 drq2 -1 flags 0x0 

Line 141 is the driver for an old-fashioned 1 NE2000 ISA network card. This driver will check 2 ISA bus number zero driver for a card at 3 memory address 0x240 and 4 irq 9. It runs with the default flags. (Other characteristics shown are very, very unlikely to change, and these days most people won't even remember what they are.)

 255 1 pf 2 count 1 ( 3 pseudo device) 

This is a device driver for a 3 pseudo-device. Pseudo-device drivers give the system some device-like functionality, but there is no actual hardware. This example, 1 pf, is the kernel's public interface for its packet-filtering engine, PF (see Chapter 17). The kernel can support one instance of PF at any given time.

Finally, you'll see several lines like this:

 248 free slot (for add) 

This is an empty space for the system administrator to add additional devices to the kernel. We'll see how to take advantage of these in "Adding Devices," later in this chapter.

Configuring Existing Device Drivers

Suppose you have an old-fashioned ISA NE2000 network card. Many NE2000 cards were quite durable and are still lying around support supply rooms even today. If you're using an older system to learn OpenBSD on, it's not unlikely that you'll have to deal with one of these unruly beasts. (On the other hand, it's also quite possible that some component of this system is cooked from years of abuse, and you'll find yourself suffering from unexplained crashes and errors.) The card is hard-configured to use IRQ 11 and memory port 0x280. As many of these cards could only be configured via a proprietary driver from a DOS boot disk, it's probably easier to edit your OpenBSD kernel configuration than to reconfigure the card.

The first step is to identify which NE2000 drivers are in our existing kernel. We do that with the "find" command, giving the name of the device driver. You can find a list of device drivers for various sorts of hardware in Appendix A, or on the OpenBSD web page for your architecture (i.e., http://www.OpenBSD.org/i386.html). The "ne" driver, per both of these resources, supports NE2000 cards.

 ukc> find ne  91 1 ne* at 2 pci* dev -1 function -1 flags 0x0  92 ne* at 3 pcmcia* function -1 irq -1 flags 0x0 141 ne0 at 4 isa0 5 port 0x240 size 0 iomem -1 iosiz 0 6 irq 9 drq -1 drq2 -1 flags 0x0 142 ne1 at isa0 port 0x300 size 0 iomem -1 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 143 7 ne2 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 9 drq -1 drq2 -1 flags 0x0 204 ne* at 8 isapnp0 port -1 size 0 iomem -1 iosiz 0 irq -1 drq -1 flags 0x0 ukc> 

Line 91 is a 1 NE2000 card, but is attached to the 2 PCI bus. ISA cards don't attach to the PCI bus without using a hammer and a saw, so this probably isn't what we want. The asterisk indicates that the kernel will change the device number as needed, to the first available number. We'll see later that ne0, ne1, and ne2 are hard-coded into the kernel, so the first PCI NE2000 card the kernel finds will be called ne3.

Line 92 is a 3 PCMCIA card for a laptop. This also isn't what we want.

Line 141 is attached to the 4 ISA bus and has a memory address of 5 0x240 and an 6 IRQ of 9. These are fairly standard values. If our card were set to these values, it would "just work." (We could probably rewire our card to use these values, but then we wouldn't learn how to use the kernel configuration tool, now would we?)

Lines 142 and 143 are other ISA NE2000 cards, but neither has the correct IRQ and memory port. Remember, on these old cards, both the IRQ and the memory port must be set correctly for the card to be recognized. Line 143 is close, with the correct memory port but an incorrect IRQ.

Line 204 is an 8 ISA plug-and-play card, with no IRQ or memory port configured. If your card is hard-coded to a particular IRQ or memory port, this entry won't work. If your card were a plug-and-play ISA NE2000, well, you wouldn't have to worry about this process. (Instead, you would be worrying about plug-and-play, and gaining a deeper appreciation for PCI's autoconfiguration features.)

Of all the existing NE2000 drivers in the kernel, 7 line 143 is the closest to what we need. Let's modify it to match our card. We do this with the "change" command, and either the device driver name or the line number. Because many devices can use the same device driver, it's simplest to use the exact line number. If you give a device driver name, the change command will walk you through every line with that device name until you find the one you want.

 ukc> change 143 143 ne2 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 9 drq -1 drq2 -1 flags 0x0 change [n] 

Yes, this is the one we want to change. Enter "y" at the prompt.

 port [0x280] ? 

The port is correct. Hit ENTER to leave the value unchanged. Similarly, hit ENTER for the size, iomem, and iosiz questions. Stop when you reach the IRQ.

 size [0] ? iomem [-1] ? iosiz [0] ? irq [9] 11 

We want IRQ 11, so enter "11" and hit ENTER. You'll have a chance to change the device driver flags, which you want to ignore. Finally, you'll see the whole line for the card.

 flags [0] ? 143 ne2 changed 143 ne2 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 11 drq -1 drq2 -1 flags 0x0 ukc> 

The kernel now will attach the ne2 driver to an ISA card at memory port 0x280 and IRQ 11. The next time we reboot, the kernel should do the right thing with this card.

Note

This might seem like a lot of work just to change an IRQ. Why not use sysctls for port and IRQ addresses? By the time the system is running enough to read /etc/sysctl.conf, the kernel has already finished probing the hardware and has attached every device it found to what it thinks is an appropriate device driver. You need to catch this early, very early — perhaps even before the system has found all of its hard drives. There are ISA SCSI cards, after all!

Adding Devices

Suppose you have a system with four of these ISA NE2000 cards in it. Such a system would be more than adequate for a T1 firewall with several different security zones behind it. Our kernel only has three entries for ISA NE2000 cards, however. You want to use the "add" command to create a new device driver instance.

 ukc> add ne3 Clone Device (DevNo, 'q' or '?') ? 

The "add" command might be more appropriately called the "copy" command. You cannot add an instance of a device that is not compiled into the kernel; you can only copy an existing driver. If you enter "q", you'll cancel the add command and go back to the ukc prompt. If you enter a line number, the configuration tool will copy that line into one of the blank slots reserved for adding device drivers. If you, like me, cannot remember which line number you wanted to copy, entering a question mark will make the add command list every device that's related to the device you want to add.

 Clone Device (DevNo, 'q' or '?') ? ?  91 ne* at pci* dev -1 function -1 flags 0x0  92 ne* at pcmcia* function -1 irq -1 flags 0x0 1 141 ne0 at isa0 port 0x240 size 0 iomem -1 iosiz 0 irq 9 drq -1 drq2 -1 flags 0x0 2 142 ne1 at isa0 port 0x300 size 0 iomem -1 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 3 143 ne2 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 11 drq -1 drq2 -1 flags 0x0 205 ne* at isapnp0 port -1 size 0 iomem -1 iosiz 0 irq -1 drq -1 flags 0x0 Clone Device (DevNo, 'q' or '?') ? 

We can choose to copy any of the lines for ISA network cards: 1 line 141, 2 line 142, or 3 line 143. I'm choosing 143. It doesn't matter which line we copy, as by the time we have four of these cards in the system we're almost certainly madly shuffling memory ports and IRQs to try to fit everything in.

 Insert before Device (DevNo, 'q' or '?') ? 144 

You can decide where in the kernel's device driver list you want your copied device to appear. I'd like this card to appear next to the other NE2000 drivers. If I insert this device driver before line 144, everything after line 144 will be shifted down by one.

At this point you should be back at the ukc prompt. To be sure that your copy worked correctly, view all the "ne" devices.

 ukc> find ne  91 ne* at pci* dev -1 function -1 flags 0x0  92 ne* at pcmcia* function -1 irq -1 flags 0x0 141 ne0 at isa0 port 0x240 size 0 iomem -1 iosiz 0 irq 9 drq -1 drq2 -1 flags 0x0 142 ne1 at isa0 port 0x300 size 0 iomem -1 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 1 143 ne2 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 11 drq -1 drq2 -1 flags 0x0 2 144 ne3 at isa0 port 0x280 size 0 iomem -1 iosiz 0 irq 11 drq -1 drq2 -1 flags 0x0 206 ne* at isapnp0 port -1 size 0 iomem -1 iosiz 0 irq -1 drq -1 flags 0x0 ukc> 

Our new line 2 144 is a copy of line 1 143, except for the device number. We must change the IRQ and memory port to make this card work, but we now have the appropriate number of instances of device drivers for this card in the kernel.

Finding Conflicts

So, some old device doesn't work? It might be the classic IRQ/port conflict. Many old devices can only be identified by their memory port and IRQ. If OpenBSD thinks that something is running on IRQ 10 and tries to attach the wrong driver to it, you will have trouble. You might want to pull conflicting devices from your kernel.

For example, suppose your network card has IRQ 10, but isn't being detected on boot or doesn't work properly. See what your kernel thinks is running on IRQ 10 with the "show" command.

 ukc> show irq 10 142 ne1 at isa0 port 0x300 size 0 iomem -1 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 1 146 we1 at isa0 port 0x300 size 0 iomem 0xcc000 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 3 161 sp0 at pss0 port 0x530 size 0 iomem -1 iosiz 0 irq 10 drq 0 flags 0x0 4 162 wss0 at isa0 port 0x530 size 0 iomem -1 iosiz 0 irq 10 drq 0 drq2 -1 flags 0x0 ukc> 

Line 142 shows your ne200 card. Line 1 146 is a "we0." Running "man 4 we" tells us that this is a SMC EtherEZ. Line 3 162 is wss0, or the Windows Sound System driver according to the man pages. Line 4 161 is difficult, as there's no man page for "sp"! The sp device is attached to the pss0 device, however, and "man 4 pss" tells us that sp0 is the sound port attached to the Personal Sound System driver.

At this point, you need to rely upon your own knowledge of your hardware. What is actually installed in your computer? My first suspect in this case would be the other network card driver, but any of these drivers could conceivably interfere with your system. You might need to change the IRQ your card is using to make it work with your other hardware; if two pieces of hardware both try to claim IRQ 10, no amount of kernel configuration will help!

In this case I know that none of these other pieces of hardware exist on this computer. I can safely disable everything else that thinks it should attach to IRQ 10, using the "disable" command.

 ukc> disable we1 146 we1 disabled ukc> disable sp0 161 sp0 disabled ukc> disable wss0 162 wss0 disabled ukc> 

Show everything attached to IRQ 10 in your kernel now.

 ukc> show irq 10 142 ne1 at isa0 port 0x300 size 0 iomem -1 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 146 we1 at isa0 1 disable port 0x300 size 0 iomem 0xcc000 iosiz 0 irq 10 drq -1 drq2 -1 flags 0x0 161 sp0 at pss0 1 disable port 0x530 size 0 iomem -1 iosiz 0 irq 10 drq 0 flags 0x0 162 wss0 at isa0 2 disable port 0x530 size 0 iomem -1 iosiz 0 irq 10 drq 0 drq2 -1 flags 0x0 ukc> 

Note the keyword 1 "disable" in each of the entries we turned off.

You can also search and display kernel device driver entries by memory port numbers, DRQ values, iomem, iosiz, and any other hardware characteristic.

Changing Non-Device Driver Information

In addition to all the nifty things you can do with device drivers, the config program allows you to change several of the most important kernel configuration options. These are the things that sysadmins most commonly need to change in a kernel, so the OpenBSD folks have made it as easy as possible to alter them.

Each of these kernel options has a simple numerical value. You can view the value by just entering the term in the ukc editor. For example, the number of NMBCLUSTERS that is available in the kernel is shown under the nmbclust command.

 ukc> nmbclust nmbclusters = 2048 ukc> 

This kernel has 2,048 nmbclusters. To change the number allocated, just give the new value after the option name. Here, we change NMBCLUSTERS to be 4,096.

 ukc> nmbclust 4096 nmbclusters = 4096 ukc> nmbclust nmbclusters = 4096 ukc> 

Without further ado, here are the kernel options that can be modified with config(8) in OpenBSD 3.3. These may be slightly different in your version of OpenBSD.

timezone

This is the time zone of the kernel, in minutes west. For example, Eastern Standard Time is five hours ahead of Greenwich Mean Time. That's 600 minutes. Mind you, there are easier ways to correct your system time than mucking about in the kernel, such as using any of the time-keeping programs.

nmbclust

nmbclust controls the number of NMBCLUSTERS in the kernel. This is the amount of memory reserved for networking operations. Increase this if you start to see errors on the console or in /var/log/messages like "mclpool limit reached."

cachepct

This adjusts the BUFCACHEPERCENT kernel option. BUFCACHEPERCENT is the percentage of physical memory dedicated to the buffer cache.

nkmempg

This controls the value of NKMEMPAGES in the kernel. NKMEMPAGES is the number of pages of memory dedicated to the kernel. If you start getting panics with an error message of "out of space in kmem_map," increase this value.

shmseg

This is equivalent to the SHMSEG kernel option. SHMSEG controls the number of segments of System V-style shared memory segments available to each process. Many programs, databases in particular, require large amounts of shared memory. If your programs start having difficulty allocating shared memory in large programs, you may need to increase this.

shmmaxpgs

This manages the SHMMAXPGS kernel option. SHMMAXPGS gives the total number of shared memory segments available on the system. If your programs complain that they cannot allocate shared memory, you may need to increase this.

Completing Config

When you've made all your changes, be certain you finish running config(8) in the correct manner. The "exit" command discards all the changes you made and leaves the editor, making it easy to start over. The "quit" command saves your changes and writes them to a kernel file. Do not confuse these commands! There's nothing quite as mortifying as finally getting everything configured exactly the way you want it and then discarding all your work by typing four wrong letters.

Installing Your Edited Kernel

Your edited kernel is just a file. If you used "config -e -f" to edit your kernel, your edited kernel has overwritten your original kernel file [1], and you don't need to do anything to install your new kernel. If you used "config -e -o," your edited kernel is a file with the name you specified. To most easily boot off of this, you want to move your original kernel /bsd to somewhere else and rename your new kernel /bsd. As always, be absolutely sure you have a known good kernel before renaming or deleting anything!

The next time you boot, your computer will use whatever kernel is in /bsd.

[1]You're also a braver person than I am.




Absolute Openbsd(c) Unix for the Practical Paranoid
Absolute OpenBSD: Unix for the Practical Paranoid
ISBN: 1886411999
EAN: 2147483647
Year: 2005
Pages: 298

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