8

i'm having trouble with useradd when im moving /etc/passwd /etc/shadow /etc/group from /etc to /home and create a symlink in order to have /etc/{passwd,shadow,group} respecively pointing to /home/{passwd,shadow,group}

i cannot create any user and have useradd outputing:

root@client:/home# useradd testuser
Adding user `testuser' ...
Adding new group `testuser' (1000) ...
groupadd: cannot open /etc/group

btw useradd output is

root@client:/home# adduser testuser
useradd: cannot open /etc/passwd

3 Answers3

31

Why does useradd refuse to open a symlinked /etc/passwd?

To answer the question we need to take a look at the source code of useradd (I did this on Ubuntu 12.04, on Debian it may differ slightly):

  1. Find out which package owns /usr/sbin/useradd:

    $ dpkg-query -S /usr/sbin/useradd
    passwd: /usr/sbin/useradd
    
  2. Install the source:

    $ 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
    (...)
    
  3. cd to the source directory:

    $ cd shadow-4.1.4.2+svn3283/
    
  4. Search the directory for useradd's source file, which ideally should be called useradd.c:

    $ find . -name useradd.c
    ./src/useradd.c
    

    Bingo!

  5. Look for error message cannot open /etc/passwd (in fact I only search for cannot open, since the whole string doesn't return any results):

    $ 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 means print 1 line of leading context before the matching line.

    This is where the error message you see is being generated. Function pw_open controls whether /etc/passwd can be opened or an error should be thrown.

    pw_open is not a Linux syscall (apropos pw_open doesn't return any results), so it is probably implemented within this package. Let's search for it.

  6. Tracing pw_open leads to:

    $ grep -R pw_open * 
    (...)
    lib/pwio.c:int pw_open (int mode)
    (...)
    

    pw_open implementation is:

    $ grep -A 3 'int pw_open (int mode)' lib/pwio.c 
    int pw_open (int mode)
    {
        return commonio_open (&passwd_db, mode);
    }
    

    Getting closer, but we're not there yet. commonio_open is our new objective.

  7. Search for commonio_open:

    $ grep -R commonio_open *
    (...)
    lib/commonio.c:int commonio_open (struct commonio_db *db, int mode)
    
  8. Open lib/commonio.c and scroll to function 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);
    

    Do you see O_NOFOLLOW? This is the culprit (from man 2 open):

    O_NOFOLLOW 
          If pathname is a symbolic link, then the open fails.
    

Summarizing, useradd.c uses pw_open, which in turn uses commonio_open, which opens /etc/passwd using syscall open with option O_NOFOLLOW, that rejects symbolic links.

Although a symlink can be used as a replacement of a file in many (I'd say most) situations, useradd is quite picky and rejects it, probably because a symlinked /etc/passwd strongly suggests that /etc has been tampered with.

Why should I leave passwd in /etc?

There are several files in /etc needed to boot and log in, for example (but not limited to): fstab, inittab, passwd, shadow and the init scripts in init.d/. Any sysadmin expects those files to be there, not symlinked to /home or wherever.

So even if you could, you should leave passwd in /etc.

Furthermore, the filesystem structure in Linux is well defined, take a look at it here: http://www.pathname.com/fhs/pub/fhs-2.3.html. There is also a chapter for /etc. Moving things around is not recommended.

jaume
  • 767
2

Doctor, it hurts when I do this.

Well, don't do it then!

Seriously, don't stick files as critical as that in an unexpected location. Whatever you're trying to test: find a better way. If you're trying to do central authentication: use ldap. Or nis if you must.

0

System unable to make any changes on the files /etc/passwd, /etc/shadow

Regenerate issue:

[root@ubuntu]# useradd salten
cannot open /etc/passwd
useradd: cannot open /etc/group
useradd: cannot open /etc/gshadow

Below shows that files are immutable, If you set the -i argument, a file will be marked as "immutable", meaning its data (and some vital metadata) cannot be changed, even by root, until the attribute is unset.

List the attributes:

[root@salten]#lsattr /etc/passwd
----i-------- /etc/shadow

Change the file attribute :

[root@salten]# chattr -i /etc/passwd
[root@salten]# lsattr /etc/passwd
[root@salten]# chattr -i /etc/group
[root@salten]# chattr -i /etc/gshadow

Try to add user:

[root@salten]# useradd apache

It works !!!

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Community Apr 24 '22 at 18:54