Non sto cercando strumenti complicati come la modalità di reclamo di AppArmor, ho bisogno di strumenti facili per dirmi quali file sono accessibili da un programma specifico.
fstat()
o lstat()
informazioni, ecc.
Non sto cercando strumenti complicati come la modalità di reclamo di AppArmor, ho bisogno di strumenti facili per dirmi quali file sono accessibili da un programma specifico.
fstat()
o lstat()
informazioni, ecc.
Risposte:
Per Chris Down, è possibile utilizzare strace -p
per esaminare un processo già in esecuzione , per vedere quali file apre da ora fino al momento in cui si termina la strace o il processo stesso termina.
Se vuoi vedere i file aperti per l' intera durata di un processo, fin dall'inizio, usa strace
con il nome dell'eseguibile. L'aggiunta -f
garantisce che vengano segnalati anche tutti i processi secondari biforcati. Esempio
# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#
Utilizzo lsof
per vedere quali file sono attualmente aperti da un processo
# lsof -p $(pidof NetworkManager)
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
NetworkMa 722 root cwd DIR 253,0 224 64 /
NetworkMa 722 root rtd DIR 253,0 224 64 /
NetworkMa 722 root txt REG 253,0 2618520 288243 /usr/sbin/NetworkManager
NetworkMa 722 root mem REG 253,0 27776 34560 /usr/lib64/libnss_dns-2.17.so
[...]
#
Se si dispone di SystemTap, è possibile monitorare l'intero host alla ricerca di file aperti.
[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#
open
non è l'unica chiamata di sistema rilevante. Ad esempio è possibile passare descrittori di file tra processi su un socket unix e c'è la openat
chiamata di sistema che può anche aprire un file.
strace
, vedere le righe ENOENT nell'esempio.
Puoi usare opensnoop
da BCC, che utilizza eBPF sotto il cofano:
# ./opensnoop -p 1576
PID COMM FD ERR PATH
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd 9 0 /proc/diskstats
1576 snmpd 9 0 /proc/stat
1576 snmpd 9 0 /proc/vmstat
[...]
Questo è abbastanza performante poiché usa kprobes invece di dover riavviare syscalls, come strace
fa.
Puoi anche farlo con strace
(potenzialmente con -f
per seguire i figli del processo tracciato), ma il suo modo di operare, che prevede il riavvio di syscalls come parte di ptrace , rallenterà in qualche modo la tua applicazione:
# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]
È inoltre possibile avviare l'applicazione in questo modo, se lo si desidera, utilizzando strace [executable]
o strace -f [executable]
.
Il mio strumento preferito per monitorare quali file apre un'applicazione è il potente framework di monitoraggio sysdig
.
Per monitorare tutti i file aperti aperti da un programma chiamato exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Monitoraggio di tutti i file aperti nel server:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Creazione di un file di traccia che conterrà solo eventi di scrittura nelle home directory (che possiamo esaminare in seguito con sysdig -r writetrace.scap.gz
):
sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz
Vedendo tutto a livello di syscall un processo chiamato exe_file
fa:
sudo sysdig proc.name=exe_file
Sysdig ha molti scalpelli, vedi per cose più interessanti che può fare:
Hai anche ottenuto dtrace
che non è molto usato in Linux, ma è ancora molto usato con i sistemi operativi * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
Inoltre sysdig
, strace
e dtrace
hai anche ltrace
, che registra / intercetta segnali / librerie dinamiche / chiamate di sistema che sono chiamate / ricevute da un processo:
ltrace
è un programma che esegue semplicemente il comando specificato fino alla sua uscita. Intercetta e registra le chiamate della libreria dinamica che vengono chiamate dal processo eseguito e i segnali che vengono ricevuti da quel processo. Può anche intercettare e stampare le chiamate di sistema eseguite dal programma.
$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>
time(0) = 1508018406
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0) = 0
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo") = 28
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0) = 0x2d8ddbe1
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 3
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 4
+++ exited (status 0) +++
Se il programma è piccolo, potresti anche considerare di smontarlo objdump -d exe_file
o disassemblarlo / decompilarlo Hopper
, per vedere tutti i file di cui si occupa.
Per maggiori dettagli, vedi: Comprendere cosa sta facendo un binario Linux
Come primo approccio, farei anche:
strings exe_file
È un approccio a basso costo e, per fortuna, alcuni dei nomi dei file potrebbero essere presenti in modalità ASCII nel file binario per fortuna.
Vedi anche la risposta correlata Perché il vero e il falso sono così grandi?
Se i file binari / i file forniti con la distribuzione sono anche in grado di recuperare i sorgenti dai repository dei sorgenti della distribuzione o dai repository ufficiali dell'utilità effettiva.
Come ultima risorsa, puoi sempre utilizzare strumenti come gdb o rr per eseguire il debug del file binario in tempo reale.
sysdig
bug (stai usando ARM?), Per favore pubblica una nuova domanda.