获取 运行 服务在 Ubuntu 中使用的所有共享库的列表
Get a list of all shared libraries that a running service is using in Ubuntu
我为上述问题找到的一些解决方案是:(让我们以运行服务为例,说/usr/sbin/acpid
并说进程的pid是1234)
ldd /usr/sbin/acpid
输出:
linux-vdso.so.1 => (0x00007ffe5eb7a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa0b1a48000)
/lib64/ld-linux-x86-64.so.2 (0x000055a297a76000)
sudo objdump -p /usr/sbin/acpid |需要 grep
输出:
NEEDED libc.so.6
- sudo pmap 1234
输出:
1234: /usr/sbin/acpid
0000000000400000 44K r-x-- acpid
000000000060a000 4K r---- acpid
000000000060b000 4K rw--- acpid
000000000060c000 4K rw--- [ anon ]
00000000020ce000 132K rw--- [ anon ]
00007f0ac06c7000 1788K r-x-- libc-2.23.so
00007f0ac0886000 2048K ----- libc-2.23.so
00007f0ac0a86000 16K r---- libc-2.23.so
00007f0ac0a8a000 8K rw--- libc-2.23.so
00007f0ac0a8c000 16K rw--- [ anon ]
00007f0ac0a90000 152K r-x-- ld-2.23.so
00007f0ac0caa000 12K rw--- [ anon ]
00007f0ac0cb3000 8K rw--- [ anon ]
00007f0ac0cb5000 4K r---- ld-2.23.so
00007f0ac0cb6000 4K rw--- ld-2.23.so
00007f0ac0cb7000 4K rw--- [ anon ]
00007ffcacbda000 132K rw--- [ stack ]
00007ffcacbfb000 8K r---- [ anon ]
00007ffcacbfd000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 4400K
- readelf -d /usr/sbin/acpid |需要 grep
输出:
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
同样在这个过程中,我了解了共享库到底是什么,以及如何在 Linux 中广泛地处理它们。
下面是我需要帮助的事情:
- 如果我们查看上述每个解决方案的输出,libc.so.6 存在于解决方案 1、2 和 4 的输出中,但不存在于3. 上述解决方案 1 的输出报告 inux-vdso.so.1 和 /lib64/ld-linux-x86-64.so.2 为好吧,没有其他解决方案报告。那么这些解决方案中的哪一个应该被视为准确的解决方案。
- 据我了解,共享库是在运行时由加载程序加载到内存中的。此外,按需 进程可以在需要时加载更多共享库。我在这里是对还是错?以防万一,任何给定进程使用的共享库都可以始终是动态的。所以,如果我真的需要知道进程正在使用的共享库,我是否需要一直轮询进程才能弄清楚? (我确定对此有更好/优雅的解决方案)
- 解决方案 1,ldd 方法,是我想避免的方法,因为它具有启动的固有安全风险(取决于所使用的 ldd 的版本)一个可执行文件本身来找出它的共享库。
那么找出进程正在使用的共享库的最佳方法是什么?
我会考虑 lsof -p <pid>
:
https://linux.die.net/man/8/lsof
例如:
lsof -p 552|grep '.so'
cron 552 root mem REG 8,17 153905860 /lib/x86_64-linux-gnu/libnss_files-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905748 /lib/x86_64-linux-gnu/libnss_nis-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905744 /lib/x86_64-linux-gnu/libnsl-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905743 /lib/x86_64-linux-gnu/libnss_compat-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897718 /lib/x86_64-linux-gnu/libpcre.so.3.13.1 (path dev=248,120)
cron 552 root mem REG 8,17 153905740 /lib/x86_64-linux-gnu/libdl-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897705 /lib/x86_64-linux-gnu/libaudit.so.1.0.0 (path dev=248,120)
cron 552 root mem REG 8,17 153905753 /lib/x86_64-linux-gnu/libc-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897811 /lib/x86_64-linux-gnu/libselinux.so.1 (path dev=248,120)
cron 552 root mem REG 8,17 153897716 /lib/x86_64-linux-gnu/libpam.so.0.83.1 (path dev=248,120)
cron 552 root mem REG 8,17 153905746 /lib/x86_64-linux-gnu/ld-2.19.so (path dev=248,120)
...
PS:
是的,“2. 根据我的理解,共享库已加载到内存中...”是正确的。
libc.so.6 is present in the output of solutions 1, 2 and 4 but not in 3.
libc.so.6
是 libc-2.23.so
的符号链接,因此它存在,尽管形式不同。
and /lib64/ld-linux-x86-64.so.2 as well which no other solution reports.
同上,是 ld-2.23.so
。
Also the output of solution 1 above reports inux-vdso.so.1
这是一个虚拟共享库,它不存在但被内核模拟以提高某些库函数的性能。我猜 3 在
ffffffffff600000 4K r-x-- [ anon ]
但没有注释。
which of these solutions should be taken as the accurate one.
2和4是等价的。它们不如 1 和 3,因为它们仅报告您的应用程序的 直接 依赖项(而不是其依赖项的传递依赖项)。此外,1 不如 3,因为它不会报告动态加载的库(通过 dlopen
)。
Also, on demand a process can load any more shared libraries
when ever needed. Am I right or wrong here ?
是的,它用于实现例如插件。
So, if I really need to know the shared libraries
being used by a process, will I need to poll the process
all the time to figure this out ?
(Am sure there is much better /elegant solution to this)
不,没有更简单的解决方案。您可以检查应用程序是否调用 dlopen
(通过扫描 readelf --dyn-syms -W
的输出)- 如果不是,您是 most probably 很好(一些非常聪明的应用程序可能会通过 mmap
等方式自行加载库,但这种情况很少见,可以忽略)。
如果应用程序 确实 调用 dlopen
而你能做的最好的事情就是使用解决方案 3。这显然是不完整的,因为应用程序可能随时加载新的库,取决于它的算法(而且通常没有办法静态地计算出来,因为这等同于解决停机问题)。
寻找潜在 dlopen
-ed 库的一个近似解决方案是扫描应用程序中的所有字符串(通过 运行ning strings
在它上面)并提取所有看起来像库名称的东西。当然,这不会捕获动态生成库名称的情况(例如,从某些配置文件中读取)。
Solution 1, the ldd approach, is something I would want
to avoid because of the inherent security risk it has
(depending on the version of the ldd being used) of
starting an executable itself to figure out it's shared libraries.
我不认为可执行文件已启动,即 没有 应用程序或库代码获取 运行.
So what is the best approach to figure out the shared libraries being
used by a process?
我没有。 3(它有许多等效的变体,例如扫描 /proc/PID/maps
或 lsof
,如其他 post 中所建议的)。根据您对 dlopen
的偏好程度,您还可以扫描字符串以查找可能加载的库,但恕我直言,这在大多数情况下都有些矫枉过正。
我为上述问题找到的一些解决方案是:(让我们以运行服务为例,说/usr/sbin/acpid
并说进程的pid是1234)
ldd /usr/sbin/acpid
输出:linux-vdso.so.1 => (0x00007ffe5eb7a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa0b1a48000)
/lib64/ld-linux-x86-64.so.2 (0x000055a297a76000)sudo objdump -p /usr/sbin/acpid |需要 grep
输出:NEEDED libc.so.6
- sudo pmap 1234
输出:1234: /usr/sbin/acpid
0000000000400000 44K r-x-- acpid
000000000060a000 4K r---- acpid
000000000060b000 4K rw--- acpid
000000000060c000 4K rw--- [ anon ]
00000000020ce000 132K rw--- [ anon ]
00007f0ac06c7000 1788K r-x-- libc-2.23.so
00007f0ac0886000 2048K ----- libc-2.23.so
00007f0ac0a86000 16K r---- libc-2.23.so
00007f0ac0a8a000 8K rw--- libc-2.23.so
00007f0ac0a8c000 16K rw--- [ anon ]
00007f0ac0a90000 152K r-x-- ld-2.23.so
00007f0ac0caa000 12K rw--- [ anon ]
00007f0ac0cb3000 8K rw--- [ anon ]
00007f0ac0cb5000 4K r---- ld-2.23.so
00007f0ac0cb6000 4K rw--- ld-2.23.so
00007f0ac0cb7000 4K rw--- [ anon ]
00007ffcacbda000 132K rw--- [ stack ]
00007ffcacbfb000 8K r---- [ anon ]
00007ffcacbfd000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 4400K - readelf -d /usr/sbin/acpid |需要 grep
输出:0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
同样在这个过程中,我了解了共享库到底是什么,以及如何在 Linux 中广泛地处理它们。
下面是我需要帮助的事情:
- 如果我们查看上述每个解决方案的输出,libc.so.6 存在于解决方案 1、2 和 4 的输出中,但不存在于3. 上述解决方案 1 的输出报告 inux-vdso.so.1 和 /lib64/ld-linux-x86-64.so.2 为好吧,没有其他解决方案报告。那么这些解决方案中的哪一个应该被视为准确的解决方案。
- 据我了解,共享库是在运行时由加载程序加载到内存中的。此外,按需 进程可以在需要时加载更多共享库。我在这里是对还是错?以防万一,任何给定进程使用的共享库都可以始终是动态的。所以,如果我真的需要知道进程正在使用的共享库,我是否需要一直轮询进程才能弄清楚? (我确定对此有更好/优雅的解决方案)
- 解决方案 1,ldd 方法,是我想避免的方法,因为它具有启动的固有安全风险(取决于所使用的 ldd 的版本)一个可执行文件本身来找出它的共享库。
那么找出进程正在使用的共享库的最佳方法是什么?
我会考虑 lsof -p <pid>
:
https://linux.die.net/man/8/lsof
例如:
lsof -p 552|grep '.so'
cron 552 root mem REG 8,17 153905860 /lib/x86_64-linux-gnu/libnss_files-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905748 /lib/x86_64-linux-gnu/libnss_nis-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905744 /lib/x86_64-linux-gnu/libnsl-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153905743 /lib/x86_64-linux-gnu/libnss_compat-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897718 /lib/x86_64-linux-gnu/libpcre.so.3.13.1 (path dev=248,120)
cron 552 root mem REG 8,17 153905740 /lib/x86_64-linux-gnu/libdl-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897705 /lib/x86_64-linux-gnu/libaudit.so.1.0.0 (path dev=248,120)
cron 552 root mem REG 8,17 153905753 /lib/x86_64-linux-gnu/libc-2.19.so (path dev=248,120)
cron 552 root mem REG 8,17 153897811 /lib/x86_64-linux-gnu/libselinux.so.1 (path dev=248,120)
cron 552 root mem REG 8,17 153897716 /lib/x86_64-linux-gnu/libpam.so.0.83.1 (path dev=248,120)
cron 552 root mem REG 8,17 153905746 /lib/x86_64-linux-gnu/ld-2.19.so (path dev=248,120)
...
PS: 是的,“2. 根据我的理解,共享库已加载到内存中...”是正确的。
libc.so.6 is present in the output of solutions 1, 2 and 4 but not in 3.
libc.so.6
是 libc-2.23.so
的符号链接,因此它存在,尽管形式不同。
and /lib64/ld-linux-x86-64.so.2 as well which no other solution reports.
同上,是 ld-2.23.so
。
Also the output of solution 1 above reports inux-vdso.so.1
这是一个虚拟共享库,它不存在但被内核模拟以提高某些库函数的性能。我猜 3 在
ffffffffff600000 4K r-x-- [ anon ]
但没有注释。
which of these solutions should be taken as the accurate one.
2和4是等价的。它们不如 1 和 3,因为它们仅报告您的应用程序的 直接 依赖项(而不是其依赖项的传递依赖项)。此外,1 不如 3,因为它不会报告动态加载的库(通过 dlopen
)。
Also, on demand a process can load any more shared libraries when ever needed. Am I right or wrong here ?
是的,它用于实现例如插件。
So, if I really need to know the shared libraries being used by a process, will I need to poll the process all the time to figure this out ? (Am sure there is much better /elegant solution to this)
不,没有更简单的解决方案。您可以检查应用程序是否调用 dlopen
(通过扫描 readelf --dyn-syms -W
的输出)- 如果不是,您是 most probably 很好(一些非常聪明的应用程序可能会通过 mmap
等方式自行加载库,但这种情况很少见,可以忽略)。
如果应用程序 确实 调用 dlopen
而你能做的最好的事情就是使用解决方案 3。这显然是不完整的,因为应用程序可能随时加载新的库,取决于它的算法(而且通常没有办法静态地计算出来,因为这等同于解决停机问题)。
寻找潜在 dlopen
-ed 库的一个近似解决方案是扫描应用程序中的所有字符串(通过 运行ning strings
在它上面)并提取所有看起来像库名称的东西。当然,这不会捕获动态生成库名称的情况(例如,从某些配置文件中读取)。
Solution 1, the ldd approach, is something I would want to avoid because of the inherent security risk it has (depending on the version of the ldd being used) of starting an executable itself to figure out it's shared libraries.
我不认为可执行文件已启动,即 没有 应用程序或库代码获取 运行.
So what is the best approach to figure out the shared libraries being used by a process?
我没有。 3(它有许多等效的变体,例如扫描 /proc/PID/maps
或 lsof
,如其他 post 中所建议的)。根据您对 dlopen
的偏好程度,您还可以扫描字符串以查找可能加载的库,但恕我直言,这在大多数情况下都有些矫枉过正。