It’s about time I post a detailed explanation about how my tpe-lkm module is able to enforce its security policy. This post is very technical, readers beware. Note that this writeup is based on the code as it was the latest commit, which was of this writing, was the one on Dec 10th, 2011. I’ll keep all the links relative to that date.
The other day I threw together a check_snmp_time.pl script that simply checks the remote’s time against the monitor host’s time. It’s fairly straight forward, and will alert you when host’s time drift too much, indicating that your ntpd configuration is bad. I had to do some custimizations to it, because not all hosts have the HOST-RESOURCES-MIB::hrSystemDate.0 option. For hosts that don’t it falls-back to the UCD-SNMP-MIB::versionCDate.0 option.
This evening I wasted a bunch of time on what turned out to be a simple problem. I really hate it when that happens.
I fixed a bug in tpe-lkm where users weren’t seeing all of their processes, and updated my servers with the new module. Suddenly, my phone starts buzzing off the desk; nagios was complaining that some daemons were down. This data is retrieved via snmp, and upon further investigation, I noticed that the daemons were in-fact up.
So it was a snmp problem.
This evening I implemented the optional hardcoded_path feature for tpe-lkm. It’s a way to be very strict on what on the system can be executed. When set, anything outside of the given path can’t be executed, regardless of permissions or ownership. This includes shared libraries, so use this feature with caution. Read the entry in the FAQ about it.
This evening I wrote a chunk of code that, given a PID, goes and does the chdir() and chroot() calls on it to a given directory. That process suddenly finds itself isolated while it’s running. It’s kind of like pulling the carpet pulled out from under it, but so quickly it doesn’t notice.
In other words, I’m kidnapping a process, and stuffing it into a chroot.
Since I already had my hands in the tpe-lkm code yesterday, I decided to spend my lunch break coding a feature I’ve been meaning to add in for a while now.
I added a new ps extras feature. Since it doesn’t have to do with the “trusted path”, I added it to the “extras” in the configuration. It’s similar to grsecurity’s “Proc restrictions” where “the permissions of the /proc filesystem will be altered to enhance system security and privacy”. Basically, non-root users won’t be able to view the processes they don’t own.
It also introduces a new sysctl entry, log_max, as to prevent logs from getting filled up horizontally. I set the default to 50, seemed high enough without giving an attacker too much leverage on spewing junk into the log file should they get the chance, yet low enough to catch the full process tree of you basic exploit attempt.
I’ve discovered my first denial-of-service bug in the linux kernel. I’m a bit teary eyed, not because the bug was in my own code, but it marks the first bug I’ve found in linux kernel code.
Not worth of a CVE or anything, because I still haven’t declared the code stable, and I don’t imagine many people use this thing just yet. But in the interest of full disclosure, here is information about the bug.
Since I’m on a nagios and snmp kick this week, here’s a nagios snmp plugin I wrote to check memory and swap. The real difference between this script and the standard nagios plugins for memory / swap, is it takes buffered and cached memory into account, giving the real % free.
Here is the check_snmp_memory.pl script, and it’s usage is pretty simple: