Debian

當 /etc/{passwd,shadow,group} 是符號連結(debian 擠壓)時,不能 useradd/adduser

  • April 23, 2022

當我將 /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 上可能略有不同):

  1. 找出哪個包擁有/usr/sbin/useradd
$ dpkg-query -S /usr/sbin/useradd
passwd: /usr/sbin/useradd
  1. 安裝源:
$ 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
(...)
  1. cd到源目錄:
$ cd shadow-4.1.4.2+svn3283/
  1. 在目錄中搜尋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)
  1. 打開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,例如(但不限於):fstabinittabpasswd和. 任何系統管理員都希望這些文件存在,而不是符號連結到或任何地方。shadow``init.d/``/home

因此,即使可以,您也應該離開passwd/etc

此外,Linux 中的文件系統結構定義明確,請在此處查看:http: //www.pathname.com/fhs/pub/fhs-2.3.html。還有一章/etc。不建議四處移動。

引用自:https://serverfault.com/questions/491033