Tôi sẽ không sử dụng các công cụ phức tạp như chế độ khiếu nại của AppArmor, tôi cần các công cụ dễ dàng để cho tôi biết các tệp nào được truy cập bởi một chương trình cụ thể.
fstat()
hoặc lstat()
thông tin, v.v.
Tôi sẽ không sử dụng các công cụ phức tạp như chế độ khiếu nại của AppArmor, tôi cần các công cụ dễ dàng để cho tôi biết các tệp nào được truy cập bởi một chương trình cụ thể.
fstat()
hoặc lstat()
thông tin, v.v.
Câu trả lời:
Theo Chris Down, bạn có thể sử dụng strace -p
để kiểm tra một quy trình đã chạy , để xem các tệp nào sẽ mở từ bây giờ cho đến khi bạn chấm dứt bước hoặc quá trình tự kết thúc.
Nếu bạn muốn xem các tệp được mở trong toàn bộ thời gian của một quy trình, ngay từ đầu, hãy sử dụng strace
với tên thực thi. Thêm -f
đảm bảo rằng bất kỳ quy trình phụ rẽ nhánh cũng được báo cáo. Thí dụ
# 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 +++
#
Sử dụng lsof
để xem những gì một quy trình hiện đang mở
# 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
[...]
#
Nếu bạn có SystemTap, bạn có thể giám sát toàn bộ máy chủ để xem các tệp đang được mở.
[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
không phải là cuộc gọi hệ thống duy nhất có liên quan. Ví dụ, có thể truyền mô tả tệp giữa các quy trình qua ổ cắm unix và có openat
lệnh gọi hệ thống cũng có thể mở tệp.
strace
, xem các dòng ENOENT trong ví dụ.
Bạn có thể sử dụng opensnoop
từ BCC, sử dụng eBPF trong phần mềm:
# ./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
[...]
Điều này khá hiệu quả vì nó sử dụng kprobes thay vì phải khởi động lại các tòa nhà cao tầng, giống như strace
vậy.
Bạn cũng có thể làm điều này với strace
(có khả năng -f
theo dõi quá trình truy tìm dấu vết của con cái), nhưng cách vận hành của nó, liên quan đến việc khởi động lại các tòa nhà cao tầng vì một phần của ptrace sẽ làm chậm ứng dụng của bạ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
[...]
Bạn cũng có thể bắt đầu ứng dụng của mình theo cách này nếu muốn, sử dụng strace [executable]
hoặc strace -f [executable]
.
Công cụ yêu thích của tôi để theo dõi tập tin nào ứng dụng mở ra là khung giám sát mạnh mẽ sysdig
.
Để theo dõi tất cả các tệp đang mở được mở bởi một chương trình có tên exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Giám sát tất cả các tệp được mở trong máy chủ:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Tạo một tệp theo dõi sẽ chỉ chứa các sự kiện bằng văn bản trong các thư mục nhà (mà chúng ta có thể kiểm tra sau này 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
Nhìn thấy mọi thứ ở cấp độ tòa nhà, một quá trình có tên là exe_file
:
sudo sysdig proc.name=exe_file
Sysdig có nhiều cái đục, hãy xem những điều thú vị hơn nó có thể làm:
Bạn cũng đã nhận được dtrace
rằng nó không được sử dụng nhiều trong Linux, nhưng vẫn được sử dụng rất nhiều với các hệ điều hành * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
Ngoài ra sysdig
, strace
và dtrace
, bạn cũng đã nhận được ltrace
, ghi / chặn tín hiệu / thư viện động / lệnh gọi hệ thống được gọi / nhận bởi một quy trình:
ltrace
là một chương trình chỉ đơn giản là chạy lệnh được chỉ định cho đến khi nó thoát. Nó chặn và ghi lại các cuộc gọi thư viện động được gọi bởi quá trình thực thi và các tín hiệu được nhận bởi quá trình đó. Nó cũng có thể chặn và in các cuộc gọi hệ thống được thực hiện bởi chương trình.
$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) +++
Nếu chương trình nhỏ, bạn cũng có thể xem xét tháo rời chương trình objdump -d exe_file
hoặc phân tách / dịch ngược chương trình Hopper
, để xem tất cả các tệp mà nó xử lý.
Để biết thêm chi tiết, hãy xem: Hiểu những gì một nhị phân Linux đang làm
Cách tiếp cận đầu tiên, tôi cũng sẽ làm:
strings exe_file
Đây là một cách tiếp cận chi phí thấp và may mắn, một số tên tệp có thể xuất hiện trong chế độ ASCII trong tệp nhị phân một cách may mắn.
Xem thêm câu trả lời liên quan Tại sao đúng và sai quá lớn?
Nếu tệp nhị phân / tệp đi kèm với bản phân phối, bạn cũng có thể tìm nạp các nguồn từ kho lưu trữ nguồn của bản phân phối hoặc kho chính thức của tiện ích thực tế.
Là tài nguyên cuối cùng, bạn luôn có thể sử dụng các công cụ như gdb hoặc rr để gỡ lỗi nhị phân trong thời gian thực.
sysdig
lỗi (bạn đang sử dụng ARM?), Vui lòng gửi câu hỏi mới cho nó.