當 /etc/{passwd,shadow,group} 是符號連結(debian 擠壓)時,不能 useradd/adduser
當我將 /etc/passwd /etc/shadow /etc/group 從 /etc 移動到 /home 並創建符號連結以使 /etc/{passwd,shadow,group} 分別指向 / 時,我遇到了 useradd 問題home/{passwd,shadow,group}
我無法創建任何使用者並讓 useradd 輸出:
root@client:/home# useradd testuser Adding user `testuser' ... Adding new group `testuser' (1000) ... groupadd: cannot open /etc/group
順便說一句 useradd 輸出是
root@client:/home# adduser testuser useradd: cannot open /etc/passwd
為什麼
useradd
拒絕打開符號連結/etc/passwd
?要回答這個問題,我們需要看一下原始碼
useradd
(我在 Ubuntu 12.04 上這樣做,在 Debian 上可能略有不同):
- 找出哪個包擁有
/usr/sbin/useradd
:$ dpkg-query -S /usr/sbin/useradd passwd: /usr/sbin/useradd
- 安裝源:
$ 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 (...)
cd
到源目錄:$ cd shadow-4.1.4.2+svn3283/
- 在目錄中搜尋
useradd
的源文件,理想情況下應該呼叫useradd.c
:$ find . -name useradd.c ./src/useradd.c
答對了! 5. 查找錯誤消息
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 ()); (...)
-B 1
表示在匹配行之前列印 1 行前導上下文。這是生成您看到的錯誤消息的地方。函式
pw_open
控制是否/etc/passwd
可以打開或拋出錯誤。
pw_open
不是 Linux系統呼叫(apropos pw_open
不返回任何結果),所以它可能在這個包中實現。讓我們搜尋一下。 6. 追踪pw_open
導致:$ grep -R pw_open * (...) lib/pwio.c:int pw_open (int mode) (...)
pw_open
實施是:$ grep -A 3 'int pw_open (int mode)' lib/pwio.c int pw_open (int mode) { return commonio_open (&passwd_db, mode); }
越來越近了,但我們還沒有到。
commonio_open
是我們的新目標。 7. 搜尋commonio_open
:$ grep -R commonio_open * (...) lib/commonio.c:int commonio_open (struct commonio_db *db, int mode)
- 打開
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);
你看到了
O_NOFOLLOW
嗎?這是罪魁禍首(來自man 2 open
):O_NOFOLLOW If pathname is a symbolic link, then the open fails.
總結,
useradd.c
使用pw_open
,然後使用,使用帶有選項的系統呼叫commonio_open
打開,它拒絕符號連結。/etc/passwd``open``O_NOFOLLOW
儘管在許多(我會說大多數)情況下,符號連結可以用作文件的替換,
useradd
但它非常挑剔並拒絕它,可能是因為符號連結/etc/passwd
強烈暗示/etc
已被篡改。我為什麼要
passwd
離開/etc
?啟動和登錄需要幾個文件
/etc
,例如(但不限於):fstab
、inittab
、passwd
和. 任何系統管理員都希望這些文件存在,而不是符號連結到或任何地方。shadow``init.d/``/home
因此,即使可以,您也應該離開
passwd
。/etc
此外,Linux 中的文件系統結構定義明確,請在此處查看:http: //www.pathname.com/fhs/pub/fhs-2.3.html。還有一章
/etc
。不建議四處移動。