当我将 /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脚本。任何系统管理员都希望这些文件在那里,而不是符号链接到任何地方。inittabpasswdshadowinit.d//home
所以,即使你能,你应该离开passwd在/etc。
此外,Linux 中的文件系统结构定义良好,请在此处查看:http : //www.pathname.com/fhs/pub/fhs-2.3.html。也有一章/etc。不建议移动东西。
| 归档时间: |
|
| 查看次数: |
11139 次 |
| 最近记录: |