Does anyone know a simple way to monitor root process spawn

Solution 1:

This sounds like a perfect job for auditd. Once you have auditd running, a default service on modern RedHat based systems, you can craft a rule that will do exactly what you want by executing

auditctl -a task,always -F uid=0

Breaking this command rule down, making excessive use of the man page, we find that:

   -a list,action
          task       Add  a  rule to the per task list. This rule list is used
                     only at the time a task is created -- when fork() or
                     clone() are called by the parent task. When using this
                     list, you should only use fields that are known at task
                     creation time, such as the uid, gid, etc.
          always     Allocate an audit context, always fill it in at syscall 
                     entry time, and always write out a record at syscall exit
                     time.

So always write out a record for this action whenever a fork or clone system call exits.

The final option can be thought of as a filter string, in our use -F uid=0 simply restricts us to cases where the uid of the process owner is 0.

Note that this rule can be executed at run time by making sure that auditd is properly configured, and adding the rule
-a task,always -F uid=0
into the relevant file for your distribution, most likely /etc/audit/audit.rules

Just keep in mind that this will be pretty dang noisy, and whomever is doing your log reviews will need to be prepared for it.

Solution 2:

I don't think there's a clean way to do this without recompiling your kernel with CONFIG_PROC_EVENTS and/or CONFIG_KPROBES (although I'd love to know if there is a way of doing it, so I've upvoted your question).

I did have an idea of using iwatch/inotify for directory creation inside /proc but it didn't seem to work, neither did auditctl. It looks like your best choice, although dirty, is to continually parse ps for a change from a script. The following Perl code would do it, although would be prone to miss some and ignores ps (as it would otherwise trigger itself):

perl -e 'my %pids; while(1) { my @pids = `ps -U root -u root`; foreach (@pids) { next if /ps$/; ($pid) = /^\s*(\d+)\D/; if (!$pids{$pid}) { $pids{$pid}++; print "Process $pid created (" . `cat /proc/$pid/cmdline` . ")\n"; } } }