From: Sebastien Marie Subject: patch: useradd bug with range and -g =uid To: tech@openbsd.org Cc: "Todd C. Miller" Date: Wed, 11 Sep 2024 18:13:20 +0200 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();