Folks, First off let me say a big thanks to the people who told me this crazy idea was good. Especially thanks to Jason R Fink for doing the hard yards and helping me out in thrashing this into the shape it is currently in. I feel this code is ready enough to be useful but there are some aspects that can be improved on. (for the people who have seen the below on tech-security, be aware new info has been added) For those that are not aware of what verified exec does, it is a modification to the exec path of the kernel. When an executable is requested to be exec'ed, the kernel performs checks to ensure the target is a valid thing to execute. We have added another check that evaluates a cryptographic hash (either md5 or sha1 at the moment) of the on disk file and compares this hash to an in kernel list of hashes that was loaded at boot time. If the two hashes match then the file has not been tampered with and the execution is permitted to proceed. If the hashes do not match or there is no hash for the binary then the execution is denied. This does not just apply to binaries - any file that is exec'ed such as shell scripts can be verified in this manner. Also, as an extension, a flag can be set so that a binary may be used as a script interpreter (ie in the #! at the top of a shell script) but is not allowed to be invoked from the command line - this means you can have a powerful script interpreter binary that can be used for approved (and validated) scripts but cannot be used to run unauthorised scripts. The verified exec scheme can also fingerprint arbitrary files and prevent the open of a file that has been modified or tampered with - this is used to allow the protection of shared libraries, preventing a trojan being inserted into a shared library. Though protecting the shared libraries was the main aim, the upshot is that any file on the system may be protected from tampering. This scheme is not perfect, it is not going to magically make the system totally secure. What it does do prevent a number of common attacks from working and thus "raises the bar" significantly. This scheme also paves the way (I am NOT saying this will be done but simply that it will be possible) for the NetBSD project to release a kit that contains the bootloader, kernel, fingerprint loader and fingerprint list with a signature on it. The package can be downloaded and the signature on it verified independently of the target system. The contents can then be loaded onto the target system and the machine booted. If care is taken doing this then the system will then be automatically validated and trust in the binaries on the machine established. Given the current trend of trojaned distributions I feel this may be a desirable thing to do. Note that verified exec is not something that would be desirable on every machine, indeed, it is a major pain in the arse for a user's workstation because updates to the system can only be done in single user mode. This scheme is more intended for those infrastructure type machines (firewalls, routers, servers) where it is important that the correct operation of the machine is ensured in a hostile environment. Over the years there have been some recurring questions asked when I have talked about this scheme, here are some of them: Q: How do I build a kernel with this feature? A: Look for the GENERIC_VERIEXEC kernel config for a template on how to configure your kernel. As of this moment I have only done this for i386 but all this should be machine independent. Q: How are the fingerprints loaded into the kernel? A: They are passed into the kernel via a pseudo-device (/dev/veriexec) by a loader app called verifiedexec_loader Q: So, how do you stop the list being updated later? A: by using securelevel - the fingerprints can only be loaded at securelevel == 0. The full effect of the verified exec is in effect at securelevel > 2 (i.e. 3 onwards), at this point warnings about invalid/missing fingerprints become fatal errors, before this they were merely warnings. Q: Why not embed the fingerprints in the binary somehow? A: two reasons 1) my idea was to cause the minimal amount of change to the system as possible, embedding fingerprints would mean special tools and other complications. 2) shell scripts would not be covered. Q: How do I generate the fingerprints? A: You could look at the verifiedexec_load man page for the signature file format. Or you can check out some simple minded scripts in /usr/share/example/verifiedexec_load that do a full scan of your system and generate the fingerprints for you. Q: Does this blow demand paging out of the water? A: yes and no. Yes, the first time an executable is loaded the whole file will be read thus demand paging goes out the window. If the executable is then re-run, demand paging works because the result of the previous evaluation of the fingerprint was cached in the file's vnode, as long as the vnode sticks in memory the fingerprint will not be re-evaluated. Q: So, you trust the file on the disk... what if someone overwrites it? A: Any fingerprinted file is automatically made read-only. If the file is moved/removed and a new one put in it's place there will not be a fingerprint in the kernel list for the new file so it will not be used. Even if the file did have the same inode if the contents are modified then the fingerprint will not match anyway. Q: What if I have my files on a SAN? I cannot trust that my files will not be modified by another machine! A: Previously I would have said "tough, don't do that" but now we have cgd(4) in NetBSD-current you have the option of encrypting the file system on the SAN thus preventing unauthorised tampering. Q: Is there a performance decrease? A: Not that I could realistically measure. Yes, theoretically there should be a performance hit because there is a lot of work involved in evaluating the fingerprint. The real world impact is not as great due to the caching of the fingerprint comparison result. Since most machines execute the same set of binaries over and over there is little overhead added. Q: Have you seen the unofficial signed exec OpenBSD patch (aka TrojanProof)? A: Yes. My work predates it by a long while. Version 1 of TrojanProof was pretty simple. It evaluated the signature each time thus killing both demand paging and performance. In version 2 it looks like the TrojanProof author has used some of my ideas to improve performance, giving me due credit which was good. Q: What hash are you using? A: either md5 or sha1, it can be selected on a file by file basis Q: You know that md5 is broken? A: yes. The two algorithms are there to demonstrate the framework for adding different hashes. The internals have been done to try and make it easier to "bolt on" new crytographic hashes with a minimum of fuss - having two different hashes is supposed to show how to do this. Q: Doesn't chflags(1) do all this already? A: Not really. It can be used to do some of the work but there are some things it cannot do like prevent a file from being executed nor can it give any confidence that what you are executing has not been tampered with. Q: Is this finished? A: not by a long shot. The basic system works at protecting the executables and files but there is work that needs to be done to strengthen the protection offered during the early stages of the boot process.