Ferramentas para mostrar quais arquivos são acessados ​​por um programa?

12

Não estou procurando ferramentas complicadas, como o modo de reclamação do AppArmor, preciso de ferramentas fáceis para me dizer quais arquivos são acessados ​​por um programa específico.

Boll19
fonte
7
Em que sistema operacional?
Jeff Schaller
Também pode ser útil explicar que você espera que o programa acesse os arquivos de que maneira - ler, escrever, anexar, obter fstat()ou obter lstat()informações, etc.
Sergiy Kolodyazhnyy
O Suse e o Ubuntu
Boll19
Não importa o que eu tenho que saber, é fstat () ou lstat () está programando?
precisa saber é o seguinte
Comentário de Sergiy Kolodyazhnyy em outras palavras: se um programa verifica o tamanho, data de modificação, permissões ou outras propriedades de um arquivo, mas não acessa os dados do arquivo, você o considera como "acessando o arquivo" ou não?
Telcom

Respostas:

12

Por Chris Down, você pode usar strace -ppara examinar um processo já em execução , para ver quais arquivos ele abre a partir de agora até o momento em que você encerra o rastreio ou o processo em si termina.

Se você deseja ver os arquivos abertos por toda a duração de um processo, use desde o início stracecom o nome do executável. A adição -fgarante que qualquer subprocesso bifurcado também seja relatado. Exemplo

# 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 +++
#

Usando lsofpara ver quais arquivos um processo está aberto no momento

# 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 você possui o SystemTap, pode monitorar o host inteiro em busca de arquivos que estão sendo abertos.

[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"
[...]
#
Steve
fonte
2
opennão é a única chamada de sistema relevante. Por exemplo, é possível passar descritores de arquivo entre processos em um soquete unix, e há a openatchamada do sistema que também pode abrir um arquivo.
precisa saber é
---- SIGUSR1 {si_signo = SIGUSR1, si_code = SI_TKILL, si_pid = 6026, si_uid = 1002} ---- o que é esse
Boll19
Kaspersky, só preciso procurar por 'openat' no comando strace output?
precisa saber é o seguinte
Tentando abrir um arquivo (mas o arquivo pode não existir) também é exibido nas saídas 'strace'?
precisa saber é o seguinte
Boll19, os arquivos que falham em abrir devido à inexistência deles são relatados com satisfação strace, consulte as linhas ENOENT no exemplo.
31518 Steve steve
5

Você pode usar o opensnoopBCC, que usa o eBPF sob o 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
[...]

Isso tem um bom desempenho, pois usa o kprobes em vez de ter que reiniciar o syscalls, como stracefaz.

Você também pode fazer isso com strace(potencialmente com -fpara seguir os filhos do processo rastreado), mas sua maneira de operar, envolvendo a reinicialização de syscalls como parte do ptrace , torna o aplicativo um pouco mais lento:

# 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
[...]

Você também pode iniciar seu aplicativo dessa maneira, se desejar, usando strace [executable]ou strace -f [executable].

Chris Down
fonte
5

Minha ferramenta favorita para monitorar quais arquivos um aplicativo abre é a poderosa estrutura de monitoramento sysdig.

Para monitorar todos os arquivos abertos abertos por um programa chamado exe_file:

sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Monitorando todos os arquivos abertos no servidor:

sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Criando um arquivo de rastreamento que conterá apenas eventos de gravação em diretórios pessoais (com os quais podemos inspecionar posteriormente 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

Vendo tudo no nível do syscall, um processo chamado exe_file:

sudo sysdig proc.name=exe_file

O Sysdig tem muitos cinzéis, veja para coisas mais interessantes que ele pode fazer:

Você também percebeu dtraceque não é muito usado no Linux, mas ainda é muito usado nos sistemas operacionais * BSD:

# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'

Além disso sysdig, stracee dtracevocê também tem ltracequais registros / intercepta sinais / bibliotecas dinâmicas / chamadas de sistema que são chamadas / recebidas por um processo:

ltraceé um programa que simplesmente executa o comando especificado até que ele saia. Ele intercepta e registra as chamadas da biblioteca dinâmica chamadas pelo processo executado e os sinais recebidos por esse processo. Também pode interceptar e imprimir as chamadas do sistema executadas pelo 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) +++  

Se o programa for pequeno, considere também desmontá-lo objdump -d exe_fileou desmontá-lo / descompilá-lo Hopper, para ver todos os arquivos com os quais lida.

Para obter mais detalhes, consulte: Entendendo o que um binário Linux está fazendo

Como primeira abordagem, eu também faria:

strings exe_file

É uma abordagem de baixo custo e, com sorte, alguns nomes de arquivos podem estar presentes no modo ASCII no arquivo binário com sorte.

Veja também a resposta relacionada Por que o verdadeiro e o falso são tão grandes?

Se os binários / arquivos que acompanham a distribuição, você também pode buscar as fontes nos repositórios de fontes da distribuição ou nos repositórios oficiais do utilitário real.

Como último recurso, você sempre pode usar ferramentas como gdb ou rr para depurar o binário em tempo real.

Rui F Ribeiro
fonte
aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = aberto Não foi possível carregar o erro do driver dispositivo de abertura / dev / sysdig0. Verifique se você possui credenciais raiz e se o módulo sysdig-probe está carregado.
precisa saber é o seguinte
/ * <a> aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = open Unable carregar o erro de driver ao abrir o dispositivo / dev / sysdig0. Verifique se você possui credenciais raiz e se o módulo sysdig-probe está carregado. <code> * /
Boll19
@ Boll19 Ocorreu um erro lá, corrigiu-o. Essa mensagem parece sobre um sysdigbug (você está usando o ARM?), Poste uma nova pergunta para ele.
Rui F Ribeiro