So recently I wrote a Linux Security Module (LSM) which would deny execution of commands, unless an extended attribute existed upon the filesystem belonging to the executables.
The whitelist-LSM worked well, but it soon became apparent that it was a little pointless.  Most security changes are pointless unless you define what you're defending against - your "threat model".
In my case it was written largely as a learning experience, but also because I figured it seemed like it could be useful. However it wasn't actually as useful because you soon realize that you have to whitelist too much:
- The redis-serverbinary must be executable, to theredis-user, otherwise it won't run.
- /usr/bin/gitmust be executable to the- gituser.
In short there comes a point where user alice must run executable blah.  If alice can run it, then so can mallory.  At which point you realize the exercise is not so useful.
Taking a step back I realized that what I wanted to to prevent was the execution of unknown/unexpected, and malicious binaries How do you identify known-good binaries? Well hashes & checksums are good. So for my second attempt I figured I'd not look for a mere "flag" on a binary, instead look for a valid hash.
Now my second LSM is invoked for every binary that is executed by a user:
- When a binary is executed the sha1hash is calculated of the files contents.
- If that matches the value stored in an extended attribute the execution is permitted.
- If the extended-attribute is missing, or the checksum doesn't match, then the execution is denied.
 
In practice this is the same behaviour as the previous LSM - a binary is either executable, because there is a good hash, or it is not, because it is missing or bogus. If somebody deploys a binary rootkit this will definitely stop it from executing, but of course there is a huge hole - scripting-languages:
- If /usr/bin/perlis whitelisted then/usr/bin/perl /tmp/exploit.plwill succeed.
- If /usr/bin/pythonis whitelisted then the same applies.
Despite that the project was worthwhile, I can clearly describe what it is designed to achieve ("Deny the execution of unknown binaries", and "Deny binaries that have been modified"), and I learned how to hash a file from kernel-space - which was surprisingly simple.
(Yes I know about
IMAandEVM- this was a simple project for learning purposes. Public-key signatures will be something I'll look at next/soon/later. :)
Perhaps the only other thing to explore is the complexity in allowing/denying actions based on the user - in a human-readable fashion, not via UIDs.  So www-data can execute some programs, alice can run a different set of binaries, and git can only run /usr/bin/git.
Of course down that path lies apparmour, selinux, and madness..
Tags: kernel-programming, linux-security-module, lsm, security 2 comments
https://vincent.bernat.im/en
Hey!
Wouldn't your security module easily be circumvented if a user just execute anything through the dynamic linker? /lib64/ld-linux-x86-64.so.2 /bin/ls