- Buffers and Strings
- When It All Goes Wrong
- Dropping Privileges
- Racing the Kernel
- Conclusions
When It All Goes Wrong
No matter how hard you try, you are going to have bugs in your code. The OpenBSD guys say that the only difference between a bug and an exploit is the intelligence of the attacker, and this is true to a large extent.
The key to secure programming is for every part of your program to assume that every other part was written by an idiot. You can check that any incoming pointer is not NULL (although, sadly, C doesn't provide any mechanism for checking that it points to a valid bit of memory). You can check that any other values are in the range you expect. At the end of the day, however, a bug in one part of a process can trample over data—and, in many operating systems, even code—from all of the rest of the process.
Note, however, that it affects only the current process. There's no reason why your program can't use multiple processes. For once, security and speed are working together—using multiple processes makes it easier to take advantage of multiple processors.
By isolating components of your program in separate processes, you limit the amount of damage that one bug can do. A very common example is in the privilege-separation code found in a lot of server programs. Many servers need to run as root, or with elevated privileges. They need this capability in order to bind to privileged ports and perform other actions as root, such as accessing data belonging to multiple users or executing a program as another user.
A good idea for this kind of process is to wrap the code that performs privileged operations in a separate process. For example, if you need to write to different users' mailboxes, you might have a process that runs as root to open a mailbox, write a message to it, and nothing else. This arrangement would check the arguments and perform the write, but do nothing else. In code this simple, it's quite easy to get rid of bugs.
Another use is to isolate code containing sensitive information. The majority of a program doesn't need to know encryption keys or passwords, for example. If you can store this info in a separate process and limit the main program's access to it, you make it more difficult for an attacker to get at that data.