No voy por herramientas complicadas como el modo de queja AppArmor, necesito herramientas fáciles para decirme a qué archivos accede un programa específico.
fstat()
o lstat()
información, etc.
No voy por herramientas complicadas como el modo de queja AppArmor, necesito herramientas fáciles para decirme a qué archivos accede un programa específico.
fstat()
o lstat()
información, etc.
Respuestas:
Según Chris Down, puede usar strace -p
para examinar un proceso que ya se está ejecutando , para ver qué archivos se abre desde ahora hasta el momento en que termina la secuencia o el proceso termina.
Si desea ver los archivos abiertos durante todo el proceso, desde el principio, utilícelos strace
con el nombre del ejecutable. Agregar -f
asegura que cualquier subproceso bifurcado también sea reportado. Ejemplo
# 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 +++
#
Utilizando lsof
para ver qué archivos tiene abierto actualmente un proceso
# 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
[...]
#
Si tiene SystemTap, puede monitorear todo el host en busca de archivos abiertos.
[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
no es la única llamada al sistema relevante. Por ejemplo, es posible pasar descriptores de archivo entre procesos a través de un socket Unix, y existe la openat
llamada al sistema que también puede abrir un archivo.
strace
, vea las líneas ENOENT en el ejemplo.
Puede usar opensnoop
de BCC, que usa eBPF bajo el capó:
# ./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
[...]
Esto es bastante eficiente ya que usa kprobes en lugar de tener que reiniciar las llamadas al sistema, como lo strace
hace.
También puede hacer esto con strace
(posiblemente -f
para seguir los elementos secundarios del proceso rastreado), pero su forma de operar, que implica reiniciar syscalls como parte de ptrace , ralentizará un poco su aplicación:
# 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
[...]
También puede iniciar su aplicación de esta manera si lo desea, usando strace [executable]
o strace -f [executable]
.
Mi herramienta favorita para monitorear qué archivos abre una aplicación es el poderoso marco de monitoreo sysdig
.
Para monitorear todos los archivos abiertos abiertos por un programa llamado exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Supervisión de todos los archivos abiertos en el servidor:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Crear un archivo de rastreo que solo contendrá eventos de escritura en directorios de inicio (que podemos inspeccionar más adelante 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
Al ver todo a nivel de syscall, un proceso llamado exe_file
hace:
sudo sysdig proc.name=exe_file
Sysdig tiene muchos cinceles, vea más cosas interesantes que puede hacer:
También tiene dtrace
que no se usa mucho en Linux, pero todavía se usa mucho con los sistemas operativos * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
Además sysdig
, strace
y dtrace
también tiene ltrace
, qué graba / intercepta señales / bibliotecas dinámicas / llamadas al sistema que son llamadas / recibidas por un proceso:
ltrace
es un programa que simplemente ejecuta el comando especificado hasta que sale. Intercepta y registra las llamadas a la biblioteca dinámica que son llamadas por el proceso ejecutado y las señales que recibe ese proceso. También puede interceptar e imprimir las llamadas al sistema ejecutadas por el programa.
$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) +++
Si el programa es pequeño, también puede considerar desarmarlo objdump -d exe_file
o desarmarlo / descompilarlo Hopper
, para ver todos los archivos con los que trata.
Para obtener más detalles, consulte: Comprender qué está haciendo un binario de Linux
Como primer enfoque, también haría:
strings exe_file
Es un enfoque de bajo costo, y con suerte, algunos de los nombres de los archivos podrían estar presentes en modo ASCII en el archivo binario con suerte.
Ver también la respuesta relacionada ¿Por qué son tan verdaderos y falsos tan grandes?
Si los archivos binarios / archivos que vienen con la distribución también puede buscar las fuentes de los repositorios de fuentes de la distribución, o los repositorios oficiales de la utilidad real.
Como último recurso, siempre puede usar herramientas como gdb o rr para depurar el binario en tiempo real.
sysdig
error (¿está utilizando ARM?), Publique una nueva pregunta para él.