Linux Slackware 3.2, 3.3, 3.4, 3.5


    Ted Hickman  discovered following.   He noticed  something  rather
    "insecure" about the slackware 3.4 /bin/login (and probably  other
    versions). If  the /etc/group  file does  not exist,  any user who
    logs into the system is given uid 0 gid 0!

        buglord login: meek
        initgroups: No such file or directory
        Linux 2.0.34.
        Last login: Fri Jul 10 20:56:17 on tty6.
        You have mail.
        buglord:~# id
        uid=0(root) gid=0

    The following is recorded in the syslog:

        Jul 10 22:28:42 buglord login[25795]: initgroups failed for user `meek`:
           No such file or directory

    Further analysis was  done by Richard  Thomas.  An  examination of
    shadow-971001 shows the following in libmisc/setugid.c:

     *      setup_uid_gid() performs the following steps -
     *      set the supplementary group IDs
     *      optionally call specified function which may add more groups
     *      set the group ID to the value from the password file entry
     *      set the user ID to the value from the password file entry
     *      Returns 0 on success, or -1 on failure.

    setup_uid_gid(info, is_console)
            const struct passwd *info;
            int is_console;
             * For systems which support multiple concurrent groups, go get
             * the group set from the /etc/group file.

            if (initgroups (info->pw_name, info->pw_gid) == -1) {
                    SYSLOG((LOG_ERR, "initgroups failed for user `%s': %m\n",
                    return -1;


    And src/login.c line 960:

                setup_uid_gid(&pwent, is_console);

    The call  to setup_uid_gid()  in login.c  does no  checking of the
    return  value.    If  initgroups  cannot   open  /etc/group,   the
    setup_uid_gid()  function  returns  before  it  gets around to the
    setgid() and setuid() calls (hence the uid and gid are both  still
    0).  No special claims to know what is happening in shadow, but it
    appears that they decided to do the calls in setup() individually,
    directly in login.c.  Seems  that if setup_uid_gid is nice  enough
    to return the success or failure status, the least we could do  is
    check it (ESPECIALLY since this  is also the status of  the setgid
    and setuid calls!). Why do they still include the setup() function
    if its not used?  How does  this become a security hole?  Well  if
    you can  find a  way to  delete the  /etc/group file  things could
    become rather  messy.   The file  has to  actually be non-existent
    (chmod 000 won't do it).


    So whats the fix? Well first of all, change src/login.c to:

            if (setup_uid_gid(&pwent, is_console))

    If  we  wanted  to  be  fancy  we  could continue to login even if
    initgroups()  fails  (most  likely  you  don't  "need" those extra
    groups to get into the system and fix it).  With _patch_ above you
    can't  crate  create  /etc/group  after  that  (you  can, but what
    then?).  This does not affect RedHat.