我通常会发现所有与 Unix 相关的问题的答案都已作为问题和答案发布。然而,这个特殊的问题让我在过去的一个小时里陷入困境,所以我想我应该在这个网站上问我的第一个问题。
问题
我有一个运行 CentOS 5.11 的开发/登台服务器。locate
以普通用户身份运行不会产生任何输出(甚至没有错误消息):
locate readdir
但是,以超级用户身份运行该命令会打印有效结果列表:
$ sudo locate readdir
/home/anthony/repos/php-src/TSRM/readdir.h
/home/anthony/repos/php-src/ext/standard/tests/dir/readdir_basic.phpt
... etc.
strace
通常帮助我调试任何此类问题并运行strace locate readdir
节目:
stat64("/var/lib/mlocate/mlocate.db", 0xbff65398) = -1 EACCES (Permission denied)
access("/", R_OK|X_OK) = -1 EACCES (Permission denied)
exit_group(1) = ?
检查权限
locate
我检查了二进制文件及其默认数据库的所有权和权限。正如预期的那样,该命令setgid
作为slocate
组所有者,而数据库具有适当的所有权和权限。
$ ls -l /usr/bin/locate
-rwx--s--x 1 root slocate 22280 Sep 3 2009 /usr/bin/locate
$ sudo ls -l /var/lib/mlocate/mlocate.db
-rw-r----- 1 root slocate 78395703 May 8 04:02 /var/lib/mlocate/mlocate.db
$ sudo ls -ld /var/lib/mlocate/
drwxr-x--- 2 root slocate 4096 Sep 3 2009 /var/lib/mlocate/
也没有不寻常的文件属性:
$ sudo lsattr /usr/bin/locate /var/lib/mlocate/mlocate.db
------------- /usr/bin/locate
------------- /var/lib/mlocate/mlocate.db
与工作系统比较
同时,生产服务器上的一切都按预期运行。以常规(非 root)用户身份运行locate readdir
会返回应有的结果列表:
$ locate readdir
/usr/include/php/TSRM/readdir.h
/usr/lib/perl5/5.8.8/i386-linux-thread-multi/auto/POSIX/readdir.al
/usr/share/man/man2/readdir.2.gz
为了进行比较,我也运行了此命令,strace
但随后出现了与临时服务器上相同的权限被拒绝错误。我想知道这是怎么回事,直到我阅读了sudo
.列于虫子部分:
使用 setuid 位的程序在被跟踪时不具有有效的用户 ID 权限。
所以,不幸的是,我不能用于strace
调试。
我比较了登台服务器和生产服务器之间所有上述命令的结果,它们之间没有区别。两个系统都具有mlocate-0.15-1.el5.2
未对其文件进行任何修改的 RPM,如 所示rpm -V mlocate
。
其他考虑因素
我认为这可能与以下事实有关:在有问题的临时服务器上,我的登录是使用 Winbind 进行身份验证的,但我在同一个盒子上创建了一个常规本地用户,但仍然遇到相同的问题。显然我还缺少其他东西,但我根本不知道它是什么。
我怀疑这与setgid文件权限有关,可能是PAM,也可能是SELinux。我对 PAM 或 SELinux 都不太了解:我只在配置 Winbind 身份验证时看过 PAM,而 SELinux 是随操作系统一起安装的,但我从未使用过它。
注意:生产服务器所进行的修改远少于经过一些实验的开发服务器。
答案1
问题是/
(根目录)的权限以及从输出中找到这一行的线索strace
:
access("/", R_OK|X_OK) = -1 EACCES (Permission denied)
您缺少 的组读取权限设置/
。但是,由于您仍然拥有x
(执行)权限,允许您遍历目录,因此您仍然可以访问文件系统上的所有文件,这就是为什么在这些权限有效时,大多数内容都可以继续工作。唯一不允许您做的就是列出 的内容/
。大多数命令不需要 list /
,它们要么使用相对于当前目录的路径名,要么使用访问根目录之外的特定众所周知目录的绝对路径名(如/etc
和/var
)。
出于安全原因,locate
尽管它可以访问特权用户生成的完整文件名清单,但仍坚持仅报告调用用户通过从根扫描整个文件系统能够找到的结果。由于您无法列出/
,这使得直接从根开始扫描任何内容都是不可能的,locate
因此根本不会报告任何内容。
答案2
感谢Celada的敏锐眼光和对细节的关注,我检查了根目录的权限。
$ sudo ls -ld /
drwx--xr-x 25 root domain users 4096 Apr 22 17:57 /
当我使用 Active Directory 凭据进行身份验证时,domain users
这是 Winbind 分配给我的主要组。不久前,我通过更改组所有权并删除组的读取权限来拒绝其他用户对一组目录的读取权限。我一定是不小心对根目录做了同样的事情。哎哟!有趣的是,那是几周前的事了,我没有注意到任何问题 - 尽管这恰逢我有意识地决定开始以普通用户身份登录并使用 sudo 而不是以 root 身份登录。
无论如何,我将权限改回了应有的状态:
$ sudo chgrp root /
$ sudo chmod -v g+r /
mode of `/' changed to 0755 (rwxr-xr-x)
$ ls -ld /
drwxr-xr-x 25 root root 4096 Apr 22 17:57 /
现在locate
可以正常工作。