用于显示程序访问哪些文件的工具?


12

我不打算使用AppArmor投诉模式之类的复杂工具,我需要简单的工具来告诉我特定程序可以访问哪些文件。


7
在什么操作系统下?
Jeff Schaller

可能对解释您期望程序以何种方式访问​​文件(读取,写入,附加,仅获取信息fstat()lstat()信息等
很有用。– Sergiy Kolodyazhnyy,

Suse和Ubuntu
Boll19

没什么我要知道的,是fstat()还是lstat()正在编程?
Boll19

换句话说,Sergiy Kolodyazhnyy的评论:如果程序检查文件的长度,修改日期,权限或其他属性,但不访问文件的数据,您是否将其视为“正在访问文件”?
telcoM

Answers:


12

根据Chris Down的说法,您可以strace -p用来检查一个已经在运行的进程,以查看从现在开始直到终止strace或进程本身完成之前打开的文件。

如果要查看在整个过程中打开的文件,请从一开始就使用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"
[...]
#

2
open不是唯一相关的系统调用。例如,可以通过UNIX套接字在进程之间传递文件描述符,并且存在openat可以打开文件的系统调用。
卡巴斯德(Kasperd)'18年

---- SIGUSR1 {si_signo = SIGUSR1,si_code = SI_TKILL,si_pid = 6026,si_uid = 1002} ----
怎么

kaspers,是否只需要在strace输出命令中搜索“ openat”?
Boll19 '18

尝试打开文件(但该文件可能不存在)也显示在“ strace”输出中吗?
Boll19

Boll19,由于文件不存在而无法打开的文件被愉快地报告在内strace,请参见示例中的ENOENT行。
史蒂夫

5

您可以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
[...]

因为它使用kprobes而不是像strace那样必须重新启动syscall,所以它的性能很高。

您也可以使用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]


5

我最喜欢的用于监视应用程序打开哪些文件的工具是强大的监视框架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在Linux中使用不多的信息,但是在* BSD操作系统上仍然使用很多:

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

此外sysdigstracedtrace,你也有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,以查看其处理的所有文件。

有关更多详细信息,请参阅:了解Linux二进制文件的功能

作为第一种方法,我还将这样做:

strings exe_file

这是一种低成本的方法,如果运气好的话,有些文件名可能只是在运气好的二进制文件中以ASCII模式出现。

另请参阅相关答案为什么对与错这么大?

如果发行版随附了二进制文件/文件,您还可以从发行版的源存储库或实际实用程序的正式存储库中获取源。

作为最后的资源,您始终可以使用gdbrr之类的工具实时调试二进制文件。


aaa43bb66:〜#sudo proc.name = exe_file sysdig -p“%12user.name%6proc.pid%12proc.name%3fd.num%fd.typechar%fd.name”“ evt.type = open无法加载驱动程序错误打开设备/ dev / sysdig0。确保您具有root用户凭据,并且已加载sysdig-probe模块。
Boll19 '18

/ * <pre> aaa43bb66:〜#sudo proc.name = exe_file sysdig -p“%12user.name%6proc.pid%12proc.name%3fd.num%fd.typechar%fd.name” evt.type = open无法启用加载驱动程序错误打开设备/ dev / sysdig0。确保您具有root用户凭据,并且已加载sysdig-probe模块。<code> * /
Boll19'1

@ Boll19那里有一个错误,已更正。该消息似乎是一个sysdig错误(您正在使用ARM吗?),请为此发布一个新问题。
Rui F Ribeiro
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.