为什么 ping 可以从用户运行,但不能作为 root 运行?为什么 root 不能加载现有的库,而用户可以?

Why ping does work from user, but does not work as root? Why root cannot load existing libraries, while user can?

我发现,当 运行 作为用户时 ping 可以工作,但当成为 root 时则不起作用。问题是,当 beeing root 时,LD 不加载 /lib64/libnss_dns.so.2 库,它得到 EACCESS 错误。

当我 运行 从 root ping:

root# ping -c1 localhost
ping: unknown host localhost

这是因为:

root# strace ping -c1 localhost 
....
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
open("/lib64/tls/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
stat("/lib64/tls/x86_64", 0x7fffa619da70) = -1 EACCES (Permission denied)
open("/lib64/tls/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
stat("/lib64/tls", 0x7fffa619da70)      = -1 EACCES (Permission denied)
open("/lib64/x86_64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
stat("/lib64/x86_64", 0x7fffa619da70)   = -1 EACCES (Permission denied)
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
stat("/lib64", {st_mode=S_IFDIR|0655, st_size=4096, ...}) = 0

不用担心。 /lib64/libnss_files.so.2 存在于我的系统中:

# ls -la /lib64/libnss_files.so.2
lrwxrwxrwx 1 root root 20 2015-08-19  /lib64/libnss_files.so.2 -> libnss_files-2.15.so
$ ls -la /lib64/libnss_files-2.15.so 
-rwxr-xr-x 1 root root 62418 2012-07-16  /lib64/libnss_files-2.15.so

当 运行 作为用户时,ping 工作正常:

user# ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.038 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.038/0.038/0.038/0.000 ms
user# strace ping -c1 localhost
...
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
...

如果我执行 LD_PRELOAD libnss_files.so.2,那么 ping 从 root 运行(为什么?):

root# LD_PRELOAD=/lib64/libnss_files.so.2 ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.043 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.043/0.043/0.043/0.000 ms

此系统 ping 具有 setuid:

# ls -la /usr/bin/ping
-rwsr-sr-x 1 root root 40000 2012-07-16  /usr/bin/ping

这怎么可能?为什么 root 在加载库时会出现 EACCES 错误,而用户加载它们却没有问题?为什么 LD_PRELOAD 对带有 setuid 的二进制文件有影响? LD_PRELOAD 如果它是来自 root 的 运行,是否对带有 setuid 的二进制文件有影响?

我已经用脚本记录了 LD_DEBUG=all ping -c1 localhoststrace -f ping -c1 localhost 运行 从用户和 root 获得的输出:

script.user.txt

script.root.txt

系统比较旧:

# uname -a
Linux gucio 3.4.6-2.10-desktop #1 SMP PREEMPT Thu Jul 26 09:36:26 UTC 2012 (641c197) x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/SuSE-release
openSUSE 12.2 (x86_64)
VERSION = 12.2
CODENAME = Mantis
$ ping -V
ping utility, iputils-sss20101006

本系统没有SELinux。本系统有AppArmor

https://serverfault.com/questions/747784/ping-as-root-doesnt-work-with-hostname-but-with-ip-normal-user-works 接受的答案表明 /(或 /lib64)的权限可能存在问题。 在那种情况下,/ 上的所有者缺少 x 权限,chmod +x / 解决了问题。

也许您的系统也遇到同样的权限问题?