मैं AppArmor शिकायत मोड जैसे जटिल टूल के लिए नहीं जा रहा हूं, मुझे यह बताने के लिए आसान टूल की आवश्यकता है कि कौन सी फाइलें किसी विशिष्ट प्रोग्राम द्वारा एक्सेस की जाती हैं।
fstat()
या lstat()
जानकारी, आदि
मैं AppArmor शिकायत मोड जैसे जटिल टूल के लिए नहीं जा रहा हूं, मुझे यह बताने के लिए आसान टूल की आवश्यकता है कि कौन सी फाइलें किसी विशिष्ट प्रोग्राम द्वारा एक्सेस की जाती हैं।
fstat()
या lstat()
जानकारी, आदि
जवाबों:
क्रिस डाउन के अनुसार, आप पहले से ही चल रही प्रक्रिया की strace -p
जांच करने के लिए उपयोग कर सकते हैं , यह देखने के लिए कि यह अब तक क्या फाइलें खोलता है जब तक आप स्ट्रेस को समाप्त नहीं करते हैं या प्रक्रिया खुद ही समाप्त हो जाती है।
यदि आप किसी प्रक्रिया की संपूर्ण अवधि के लिए खोली गई फ़ाइलों को देखना चाहते हैं , तो प्रारंभ से ही, strace
निष्पादन योग्य नाम के साथ उपयोग करें। जोड़ना -f
यह सुनिश्चित करता है कि किसी भी उप-प्रक्रिया को भी सूचित किया जाए। उदाहरण
# 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 +++
#
का उपयोग करते हुए lsof
क्या एक प्रक्रिया फाइलों को देखने के लिए वर्तमान में खुला है
# 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
[...]
#
यदि आपके पास SystemTap है, तो आप खोली जा रही फ़ाइलों के लिए पूरे होस्ट की निगरानी कर सकते हैं।
[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
केवल प्रासंगिक सिस्टम कॉल नहीं है। उदाहरण के लिए एक यूनिक्स सॉकेट पर प्रक्रियाओं के बीच फ़ाइल डिस्क्रिप्टर पास करना संभव है, और openat
सिस्टम कॉल है जो एक फ़ाइल भी खोल सकता है।
strace
, उदाहरण में ENOENT लाइनें देखें।
आप opensnoop
BCC से उपयोग कर सकते हैं , जो कि हुड के नीचे eBPF का उपयोग करता है:
# ./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
[...]
यह काफी अच्छा प्रदर्शन है क्योंकि यह syscalls को फिर से शुरू करने के बजाय kprobes का उपयोग करता है, जैसे कि strace
करता है।
आप इसके साथ भी कर सकते हैं strace
(संभावित -f
रूप से ट्रेस प्रक्रिया 'बच्चों का पालन करने के लिए), लेकिन इसके संचालन का तरीका, जिसमें ptrace के भाग के रूप में syscalls को फिर से शामिल करना आपके आवेदन को कुछ हद तक धीमा कर देगा:
# 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
[...]
आप अपने आवेदन को इस तरह से शुरू कर सकते हैं, यदि वांछित है, का उपयोग कर strace [executable]
, या strace -f [executable]
।
निगरानी के लिए मेरा पसंदीदा उपकरण जो एक फाइल खोलता है वह शक्तिशाली निगरानी ढांचा है sysdig
।
नाम से एक प्रोग्राम द्वारा खोली गई सभी खुली फाइलों की निगरानी के लिए exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
सर्वर में खोली गई सभी फाइलों की निगरानी करना:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
एक ट्रेस फ़ाइल बनाना जिसमें केवल होम निर्देशिकाओं में लिखने की घटनाएं होंगी (जिनका हम बाद में निरीक्षण कर सकते हैं 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
Syscall स्तर पर सब कुछ देखकर एक प्रक्रिया जिसका नाम exe_file
है:
sudo sysdig proc.name=exe_file
Sysdig में कई छेनी हैं, अधिक दिलचस्प चीजों के लिए देखें यह कर सकते हैं:
आपको यह भी पता dtrace
चला है कि लिनक्स में बहुत अधिक उपयोग नहीं किया जाता है, लेकिन अभी भी * बीएसडी ऑपरेटिंग सिस्टम के साथ बहुत अधिक उपयोग किया जाता है:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
इसके अलावा sysdig
, strace
और dtrace
, आपको भी मिला है ltrace
, जो सिग्नल / डायनेमिक लाइब्रेरी / सिस्टम कॉल को रिकॉर्ड / इंटरसेप्ट करता है, जिसे एक प्रक्रिया द्वारा कॉल / प्राप्त किया जाता है:
ltrace
एक प्रोग्राम है जो केवल निर्दिष्ट कमांड चलाता है जब तक कि यह बाहर नहीं निकलता है। यह डायनेमिक लाइब्रेरी कॉल को इंटरसेप्ट और रिकॉर्ड करता है, जिन्हें निष्पादित प्रक्रिया और उस प्रक्रिया द्वारा प्राप्त सिग्नल कहा जाता है। यह प्रोग्राम द्वारा निष्पादित सिस्टम कॉल को इंटरसेप्ट और प्रिंट भी कर सकता है।
$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) +++
यदि यह कार्यक्रम छोटा है, तो आप इसे असंतुष्ट करने objdump -d exe_file
या इसके साथ विघटित / विघटित करने पर विचार कर सकते हैं, इसके साथ संबंधित Hopper
सभी फाइलों को देखने के लिए।
अधिक विवरण के लिए देखें: यह समझना कि लिनक्स बाइनरी क्या कर रहा है
पहले दृष्टिकोण के रूप में, मैं यह भी करूंगा:
strings exe_file
यह कम लागत वाला दृष्टिकोण है, और भाग्य के साथ कुछ फाइलें नाम केवल बाइनरी फ़ाइल में ASCII मोड में मौजूद हो सकती हैं।
संबंधित उत्तर भी देखें क्यों सच और झूठ इतने बड़े हैं?
यदि बायनेरिज़ / फाइलें जो वितरण के साथ आती हैं, तो आप वितरण के स्रोत भंडार से स्रोतों को प्राप्त कर सकते हैं, या वास्तविक उपयोगिता के आधिकारिक भंडार।
अंतिम संसाधन के रूप में, आप हमेशा वास्तविक समय में बाइनरी को डीबग करने के लिए जीडीबी या आरआर जैसे टूल का उपयोग कर सकते हैं ।
sysdig
बग के बारे में लगता है (क्या आप एआरएम का उपयोग कर रहे हैं?), कृपया इसके लिए एक नया प्रश्न पोस्ट करें।