Index | Thread | Search

From:
Sebastien Marie <semarie@kapouay.eu.org>
Subject:
patch: useradd bug with range and -g =uid
To:
tech@openbsd.org
Cc:
"Todd C. Miller" <millert@openbsd.org>
Date:
Wed, 11 Sep 2024 18:13:20 +0200

Download raw body.

Thread
  • Sebastien Marie:

    patch: useradd bug with range and -g =uid

Hi,

While playing with useradd(8) for ports infrastructure, I found that
useradd(8) could have buggy behaviour in some cases.

First, create a new group (without reusing an existing gid)

# groupadd -g 5000 test

Next, create a new user with the same name, using '-g =uid' and range.

# useradd -r 5000..5010 -g =uid test
useradd: Warning: home directory `/home/test' doesn't exist, and -m was not specified

It results in creating a user 'test' with user=5001 and gid=5001, and no
group 5001.

# getent passwd test
test:*:5001:5001::/home/test:/bin/ksh
# grep 5001 /etc/group
#

The problem is the check for searching free uid/gid isn't the same as
the own for creating the group if not existing (check by gid or check by
name).

src/usr.sbin/user/user.c :
    /* return the next valid unused uid */
    static int
    getnextuid(int sync_uid_gid, uid_t *uid, uid_t low_uid, uid_t high_uid)
    {
            for (*uid = low_uid ; *uid <= high_uid ; (*uid)++) {
                    if (!uid_exists((uid_t)*uid) && *uid != NOBODY_UID) {
                            if (sync_uid_gid) {
                                    if (!gid_exists((gid_t)*uid)) {
                                            return 1;
                                    }
                            } else {
                                    return 1;
                            }
                    }
            }
            return 0;
    }

src/usr.sbin/user/user.c :
            if (strcmp(up->u_primgrp, "=uid") == 0 && !group_exists(login) &&
                !creategid(login_name, gid, "")) {
                    close(ptmpfd);
                    pw_abort();
                    errx(EXIT_FAILURE, "can't create gid %u for login name %s",
                        gid, login_name);
            }


The following patch change the check to use gid_exists().

# ./obj/user add -r 5000..5010 -g =uid test
user: Warning: home directory `/home/test' doesn't exist, and -m was not specified
user: group `test' already exists
user: can't create gid 5001 for login name test

It only fixes the problem of creating invalid user entry (with gid=5001
whereas no group with this gid are existing).

Comments or OK ?
-- 
Sebastien Marie


# pid 94213: got diff .
diff /home/semarie/repos/openbsd/src
commit - 202e2461a0d9a8e3abe70503423141a09ea1c4f4
path + /home/semarie/repos/openbsd/src
blob - 01b6faf511d2be8bf89819505c184ee14d88b749
file + usr.sbin/user/user.c
--- usr.sbin/user/user.c
+++ usr.sbin/user/user.c
@@ -1285,7 +1285,7 @@ adduser(char *login_name, user_t *up)
 			(void) run(CHMOD, chmod_argv);
 		}
 	}
-	if (strcmp(up->u_primgrp, "=uid") == 0 && !group_exists(login_name) &&
+	if (strcmp(up->u_primgrp, "=uid") == 0 && !gid_exists(gid) &&
 	    !creategid(login_name, gid, "")) {
 		close(ptmpfd);
 		pw_abort();