Soluzione 1:
Sembra un lavoro perfetto per auditd. Dopo aver eseguito auditd, un servizio predefinito sui moderni sistemi basati su RedHat, puoi creare una regola che farà esattamente quello che vuoi eseguendo
auditctl -a task,always -F uid=0
Rompendo questa regola di comando, facendo un uso eccessivo della pagina man, troviamo che:
-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.
Quindi scrivi sempre un record per questa azione ogni volta che termina una chiamata di sistema fork o clone.
L'ultima opzione può essere considerata come una stringa di filtro, nel nostro uso -F uid=0
ci limita semplicemente ai casi in cui l'uid del proprietario del processo è 0.
Si noti che questa regola può essere eseguita in fase di esecuzione assicurandosi che auditd sia configurato correttamente e aggiungendo la regola
-a task,always -F uid=0
nel file pertinente per la tua distribuzione, molto probabilmente /etc/audit/audit.rules
Tieni solo presente che questo sarà piuttosto rumoroso e chiunque stia effettuando le tue revisioni del registro dovrà essere preparato per questo.
Soluzione 2:
Non penso che ci sia un modo pulito per farlo senza ricompilare il kernel con CONFIG_PROC_EVENTS e/o CONFIG_KPROBES (anche se mi piacerebbe sapere se c'è un modo per farlo, quindi ho votato a favore della tua domanda).
Avevo l'idea di utilizzare iwatch/inotify per la creazione di directory all'interno di /proc ma non sembrava funzionare, né auditctl. Sembra che la tua scelta migliore, sebbene sporca, sia analizzare continuamente ps per una modifica da uno script. Il seguente codice Perl lo farebbe, anche se tenderebbe a perderne alcuni e ignorare ps
(poiché altrimenti si attiverebbe da solo):
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"; } } }