Strumenti per mostrare a quali file accede un programma?


12

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.


7
Con quale sistema operativo?
Jeff Schaller

Potrebbe anche essere utile spiegare che ti aspetti che il programma acceda ai file in che modo - leggere, scrivere, aggiungere, solo ottenere fstat()o lstat()informazioni, ecc.
Sergiy Kolodyazhnyy,

Sia Suse che Ubuntu
Boll19

Non importa quale modo devo sapere, è fstat () o lstat () stanno programmando?
Boll19,

Il commento di Sergiy Kolodyazhnyy in altre parole: se un programma controlla la lunghezza di un file, la data di modifica, le autorizzazioni o altre proprietà ma non accede ai dati del file, lo considerereste "accesso al file" o no?
telcoM,

Risposte:


12

Per Chris Down, è possibile utilizzare strace -pper 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 stracecon il nome dell'eseguibile. L'aggiunta -fgarantisce 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 lsofper 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"
[...]
#

2
opennon è l'unica chiamata di sistema rilevante. Ad esempio è possibile passare descrittori di file tra processi su un socket unix e c'è la openatchiamata di sistema che può anche aprire un file.
Kasperd,

---- SIGUSR1 {si_signo = SIGUSR1, si_code = SI_TKILL, si_pid = 6026, si_uid = 1002} ---- che cos'è
Boll19

kaspers, devo solo cercare 'openat' al comando di output strace?
Boll19,

Il tentativo di aprire un file (ma il file potrebbe non esistere) viene visualizzato anche negli output 'strace'?
Boll19

Boll19, i file che non riescono ad aprirsi a causa di quelli inesistenti vengono felicemente riportati all'interno strace, vedere le righe ENOENT nell'esempio.
steve

5

Puoi usare opensnoopda 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 stracefa.

Puoi anche farlo con strace(potenzialmente con -fper 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].


5

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_filefa:

sudo sysdig proc.name=exe_file

Sysdig ha molti scalpelli, vedi per cose più interessanti che può fare:

Hai anche ottenuto dtraceche 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, stracee dtracehai 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_fileo 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.


aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = open Impossibile caricare l'errore del driver dispositivo di apertura / dev / sysdig0. Assicurarsi di disporre delle credenziali di root e che il modulo sysdig-probe sia caricato.
Boll19

/ * <pre> aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = open Impossibile per caricare l'errore del driver durante l'apertura del dispositivo / dev / sysdig0. Assicurati di avere le credenziali di root e che il modulo sysdig-probe sia caricato. <code> * /
Boll19

@ Boll19 C'è stato un errore, l'ho corretto. Quel messaggio sembra relativo a un sysdigbug (stai usando ARM?), Per favore pubblica una nuova domanda.
Rui F Ribeiro,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.