Nie zamierzam korzystać ze skomplikowanych narzędzi, takich jak tryb skarg AppArmor, potrzebuję łatwych narzędzi, aby powiedzieć mi, do których plików dostęp ma dany program.
fstat()
lub lstat()
informacje itp.
Nie zamierzam korzystać ze skomplikowanych narzędzi, takich jak tryb skarg AppArmor, potrzebuję łatwych narzędzi, aby powiedzieć mi, do których plików dostęp ma dany program.
fstat()
lub lstat()
informacje itp.
Odpowiedzi:
Według Chrisa Down możesz użyć strace -p
do zbadania już uruchomionego procesu, aby zobaczyć, jakie pliki otwiera od teraz, aż do momentu zakończenia śledzenia lub samego procesu.
Jeśli chcesz, aby pliki były otwarte przez cały czas trwania procesu, od samego początku użyj strace
nazwy pliku wykonywalnego. Dodanie -f
gwarantuje, że raportowane będą również wszelkie rozwidlone podprocesy. Przykład
# 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 +++
#
Używanie lsof
do sprawdzania, jakie pliki aktualnie otwiera proces
# 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
[...]
#
Jeśli masz SystemTap, możesz monitorować cały host pod kątem otwierania plików.
[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
to nie jedyne odpowiednie wywołanie systemowe. Na przykład możliwe jest przekazywanie deskryptorów plików między procesami przez gniazdo unix, i istnieje openat
wywołanie systemowe, które może również otworzyć plik.
strace
, patrz wiersze ENOENT w przykładzie.
Możesz skorzystać opensnoop
z BCC, który korzysta z eBPF pod maską:
# ./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
[...]
Jest to dość wydajne, ponieważ używa kprobes zamiast restartować syscalls, podobnie jak strace
robi.
Możesz to również zrobić za pomocą strace
(potencjalnie z -f
podążaniem za potomkami śledzonego procesu), ale jego sposób działania, polegający na ponownym uruchomieniu wywołań systemowych w ramach ptrace , nieco spowolni twoją aplikację:
# 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
[...]
Możesz również uruchomić aplikację w ten sposób, jeśli chcesz, używając strace [executable]
lub strace -f [executable]
.
Moim ulubionym narzędziem do monitorowania, które pliki otwiera aplikacja, jest potężne środowisko monitorowania sysdig
.
Do monitorowania wszystkich otwartych plików otwartych przez program o nazwie exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Monitorowanie wszystkich plików otwartych na serwerze:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Tworzenie pliku śledzenia, który będzie zawierał tylko zdarzenia zapisu w katalogach domowych (które możemy później sprawdzić 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
Widząc wszystko na poziomie syscall, proces o nazwie exe_file
wykonuje:
sudo sysdig proc.name=exe_file
Sysdig ma wiele dłut, sprawdź ciekawsze rzeczy, które może zrobić:
Masz również to, dtrace
że nie jest zbyt często używane w Linuksie, ale nadal jest dużo używane w systemach operacyjnych * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
Poza tym sysdig
, strace
i dtrace
, również mam ltrace
, które rekordy / przechwytuje sygnały / biblioteki dynamiczne / wywołania systemowe, które są nazywane / otrzymane w procesie:
ltrace
to program, który po prostu uruchamia określone polecenie, dopóki nie zakończy działania. Przechwytuje i rejestruje dynamiczne wywołania biblioteki, które są wywoływane przez wykonywany proces oraz sygnały odbierane przez ten proces. Może także przechwytywać i drukować wywołania systemowe wykonywane przez program.
$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) +++
Jeśli program jest mały, możesz również rozważyć jego dezasemblację objdump -d exe_file
lub deasemblację / dekompilację Hopper
, aby zobaczyć wszystkie pliki , z którymi ma do czynienia.
Aby uzyskać więcej informacji, zobacz: Zrozumienie, co robi plik binarny systemu Linux
Jako pierwsze podejście zrobiłbym również:
strings exe_file
Jest to podejście tanie, a przy odrobinie szczęścia niektóre nazwy plików mogą po prostu być obecne w trybie ASCII w pliku binarnym przy odrobinie szczęścia.
Zobacz także pokrewną odpowiedź Dlaczego prawda i fałsz są tak duże?
Jeśli pliki binarne / pliki dostarczane z dystrybucją można również pobrać źródła ze źródłowych repozytoriów dystrybucji lub oficjalnych repozytoriów rzeczywistego narzędzia.
Jako ostatni zasób możesz zawsze używać narzędzi takich jak gdb lub rr do debugowania pliku binarnego w czasie rzeczywistym.
sysdig
błędu (czy używasz ARM?), Proszę o nowe pytanie.