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 -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"
[...]
#
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.
strace, vedere le righe ENOENT nell'esempio.
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].
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.
sysdigbug (stai usando ARM?), Per favore pubblica una nuova domanda.