当我将 /etc/passwd /etc/shadow /etc/group 从 /etc 移动到 /home 并创建符号链接以使 /etc/{passwd,shadow,group} 分别指向 / 时,我遇到了 useradd 问题家/{passwd,shadow,group}
我无法创建任何用户并让 useradd 输出:
root@client:/home# useradd testuser
Adding user `testuser' ...
Adding new group `testuser' (1000) ...
groupadd: cannot open /etc/group
Run Code Online (Sandbox Code Playgroud)
顺便说一句 useradd 输出是
root@client:/home# adduser testuser
useradd: cannot open /etc/passwd
Run Code Online (Sandbox Code Playgroud)
jau*_*ume 28
useradd
拒绝打开一个符号链接/etc/passwd
?要回答这个问题,我们需要查看源代码useradd
(我在 Ubuntu 12.04 上这样做,在 Debian 上它可能略有不同):
找出哪个包拥有/usr/sbin/useradd
:
$ dpkg-query -S /usr/sbin/useradd
passwd: /usr/sbin/useradd
Run Code Online (Sandbox Code Playgroud)安装源码:
$ apt-get source passwd
Reading package lists... Done
Building dependency tree
Reading state information... Done
Picking 'shadow' as source package instead of 'passwd'
(...)
dpkg-source: info: extracting shadow in shadow-4.1.4.2+svn3283
dpkg-source: info: unpacking shadow_4.1.4.2+svn3283.orig.tar.gz
dpkg-source: info: applying shadow_4.1.4.2+svn3283-3ubuntu5.1.diff.gz
(...)
Run Code Online (Sandbox Code Playgroud)cd
到源目录:
$ cd shadow-4.1.4.2+svn3283/
Run Code Online (Sandbox Code Playgroud)在目录中搜索useradd
的源文件,理想情况下应称为useradd.c
:
$ find . -name useradd.c
./src/useradd.c
Run Code Online (Sandbox Code Playgroud)
答对了!
查找错误消息cannot open /etc/passwd
(实际上我只搜索cannot open
,因为整个字符串不返回任何结果):
$ grep -B 1 'cannot open' src/useradd.c
(...)
if (pw_open (O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
(...)
Run Code Online (Sandbox Code Playgroud)
-B 1
表示在匹配行之前打印 1 行前导上下文。
这是生成您看到的错误消息的地方。函数pw_open
控制是否/etc/passwd
可以打开或应该抛出错误。
pw_open
不是 Linux系统调用(apropos pw_open
不返回任何结果),所以它可能在这个包中实现。让我们搜索一下。
追踪pw_open
导致:
$ grep -R pw_open *
(...)
lib/pwio.c:int pw_open (int mode)
(...)
Run Code Online (Sandbox Code Playgroud)
pw_open
实施是:
$ grep -A 3 'int pw_open (int mode)' lib/pwio.c
int pw_open (int mode)
{
return commonio_open (&passwd_db, mode);
}
Run Code Online (Sandbox Code Playgroud)
越来越近了,但我们还没有到那里。commonio_open
是我们的新目标。
搜索commonio_open
:
$ grep -R commonio_open *
(...)
lib/commonio.c:int commonio_open (struct commonio_db *db, int mode)
Run Code Online (Sandbox Code Playgroud)打开lib/commonio.c
并滚动到功能commonio_open
:
int commonio_open (struct commonio_db *db, int mode)
{
(...)
fd = open (db->filename,
(db->readonly ? O_RDONLY : O_RDWR)
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
Run Code Online (Sandbox Code Playgroud)
你看到了O_NOFOLLOW
吗?这是罪魁祸首(来自man 2 open
):
O_NOFOLLOW
If pathname is a symbolic link, then the open fails.
Run Code Online (Sandbox Code Playgroud)总而言之,useradd.c
使用pw_open
,然后使用commonio_open
,/etc/passwd
使用open
带有选项的系统调用打开O_NOFOLLOW
,拒绝符号链接。
虽然符号链接可以在许多(我会说大多数)情况下用作文件的替换,useradd
但它非常挑剔并拒绝它,可能是因为符号链接/etc/passwd
强烈表明/etc
已被篡改。
passwd
的/etc
?有几个文件/etc
需要启动和登录,例如(但不限于): ,fstab
,,和在init脚本。任何系统管理员都希望这些文件在那里,而不是符号链接到任何地方。inittab
passwd
shadow
init.d/
/home
所以,即使你能,你应该离开passwd
在/etc
。
此外,Linux 中的文件系统结构定义良好,请在此处查看:http : //www.pathname.com/fhs/pub/fhs-2.3.html。也有一章/etc
。不建议移动东西。
归档时间: |
|
查看次数: |
11139 次 |
最近记录: |