From nobody Fri Sep 04 10:43:38 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hbtNq1hv7z6qTb5 for ; Fri, 04 Sep 2026 10:43:39 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hbtNq0TYsz4CdM for ; Fri, 04 Sep 2026 10:43:39 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788518619; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=sWlQ8Ki+RP0nIcrAyMAq6QTMz1W+DOx4HEoAuNirHWE=; b=JrZi+eHfjcw/BERJFLCncC07Xb3U6fCvkj105kX1W0Ddx5tUklWk+IZwXO2WhAfP7oHd9c 5XleQMIfDQe5CHGIR9jSfFRrVH7g8O7QTJp1OvIFdMqw+/VjEvSYE8GKJzzqZmfS0x6b2c TC/8Co2JjjSJjcWcFfjqTzcFoGFVaemxrk6zRvP2OiPHIGXlPCYdqG5/NhXVE9NhnV6CQJ EZ3W9jyC8DzJx7rKXRxmLam5wvcwv/hKsKD4GJ1oQzK46DHMCr3c1R1yKrLt0YhTmzUx8f 5pBfWcjEBIlU5nyp39qm17J1uTvg/CfgjzFl7s0Qfi4Rf8OpJqn5USyyJDpcjg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788518619; a=rsa-sha256; cv=none; b=oXV9D1J30fJ6OURuxQLUEtY7N61Nb4b0U0AyzHX01TORKoHo/DgMLX3Ikrl0VrnWhNbV5l PxO2P3mRuQD+eMb3XuZGZpY2ym+hjYDNmKyvwV7gCYsML0WmzBpD8Kpsucnqw2gl/o/BUg Tbek1tfIUopPZno+Nkh40Uh2SDIt7fXBVfL1HdKUoNqf/uydPK5gBLBFd4gEs5Yha9Fl9D aNGpHN68Hx8CWoNia6G3w1RGKHsnzVwlbp91JKImlZzHX46BrD0B+FO9jObSonjNUv+8da Fam5Ze1OtNXFcGALCHf3VgiewhL7xj8qXVUgVlAZcl/AS+4elMCFF55bzLdwMQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788518619; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=sWlQ8Ki+RP0nIcrAyMAq6QTMz1W+DOx4HEoAuNirHWE=; b=xyg55jE0S88JqQt71WS+O44tMlijxY01pinAZeRcXKYU2iBGKHzeFP5weZEIeVFMeSzQTy UtOjREgQy5zQidwJ3PUFlkEgN29/nGDYk6YE30wc67ocdWAzFOKfwLhzcOQwy1czoqT1b0 gXAeEM03GFSdJ8D2eE7Fl9VCW5Jsn3XYgjnqzyrRpwTDHbkKHuiYvgl5PCOAbu+Uc44KOU TNgEZWlIcDgnlIJ2xfj/Wu5UH/T20FFjK9fze8hhC7elfBoNJwnzTDgnKMlJMOtapQZ+8v jg2r80lYcySYov9dsDI/THv6EHlLOFYotswtGzn+2NBTmyWzmqjIzBkq3Ts6qw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hbtNp6QVszwF3 for ; Fri, 04 Sep 2026 10:43:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 466fe by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 04 Sep 2026 10:43:38 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Baptiste Daroussin Subject: git: 92e8a76b8786 - main - pw: use _PWDASH pseudo-fd for "-" in pw_checkfd List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 92e8a76b87862aa2ee7e6c3f637034e60ffbc2e6 Auto-Submitted: auto-generated Date: Fri, 04 Sep 2026 10:43:38 +0000 Message-Id: <6a9aa0da.466fe.87e792d@gitrepo.freebsd.org> The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=92e8a76b87862aa2ee7e6c3f637034e60ffbc2e6 commit 92e8a76b87862aa2ee7e6c3f637034e60ffbc2e6 Author: Baptiste Daroussin AuthorDate: 2026-09-04 10:17:02 +0000 Commit: Baptiste Daroussin CommitDate: 2026-09-04 10:42:29 +0000 pw: use _PWDASH pseudo-fd for "-" in pw_checkfd pw_checkfd() returned the character "-" (45) for the "-" argument, which was ambiguous with a real file descriptor. MFC After: 1 week --- usr.sbin/pw/pw.h | 1 + usr.sbin/pw/pw_group.c | 6 +- usr.sbin/pw/pw_user.c | 6 +- usr.sbin/pw/pw_utils.c | 2 +- usr.sbin/pw/tests/Makefile | 10 +++- usr.sbin/pw/tests/pw_unit_test.c | 107 +++++++++++++++++++++++++++++++++++ usr.sbin/pw/tests/pw_useradd_test.sh | 35 ++++++++++++ 7 files changed, 159 insertions(+), 8 deletions(-) diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h index 6be667f166fb..fcb5214a10e5 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -63,6 +63,7 @@ enum _which #define _DEF_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO) #define _PW_CONF "pw.conf" +#define _PWDASH (-2) /* pseudo-fd returned by pw_checkfd for '-' */ #define _UC_MAXLINE 1024 #define _UC_MAXSHELLS 32 diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c index 2840e972af59..2df22e014b67 100644 --- a/usr.sbin/pw/pw_group.c +++ b/usr.sbin/pw/pw_group.c @@ -56,7 +56,7 @@ grp_set_passwd(struct group *grp, bool update, int fd, bool precrypted) if (fd == -1) return; - if (fd == '-') { + if (fd == _PWDASH) { grp->gr_passwd = "*"; /* No access */ return; } @@ -538,7 +538,7 @@ pw_group_add(int argc, char **argv, char *arg1) "exclusive options"); fd = pw_checkfd(optarg); precrypted = true; - if (fd == '-') + if (fd == _PWDASH) errx(EX_USAGE, "-H expects a file descriptor"); break; case 'h': @@ -636,7 +636,7 @@ pw_group_mod(int argc, char **argv, char *arg1) "exclusive options"); fd = pw_checkfd(optarg); precrypted = true; - if (fd == '-') + if (fd == _PWDASH) errx(EX_USAGE, "-H expects a file descriptor"); break; case 'h': diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index abb8a09ce468..e2b84b2a83d3 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -171,7 +171,7 @@ pw_set_passwd(struct passwd *pwd, int fd, bool precrypted, bool update) char line[_PASSWORD_LEN+1]; char *p; - if (fd == '-') { + if (fd == _PWDASH) { if (!pwd->pw_passwd || *pwd->pw_passwd != '*') { pwd->pw_passwd = "*"; /* No access */ return (1); @@ -1306,7 +1306,7 @@ pw_user_add(int argc, char **argv, char *arg1) "exclusive options"); fd = pw_checkfd(optarg); precrypted = true; - if (fd == '-') + if (fd == _PWDASH) errx(EX_USAGE, "-H expects a file descriptor"); break; case 'h': @@ -1629,7 +1629,7 @@ pw_user_mod(int argc, char **argv, char *arg1) "exclusive options"); fd = pw_checkfd(optarg); precrypted = true; - if (fd == '-') + if (fd == _PWDASH) errx(EX_USAGE, "-H expects a file descriptor"); break; case 'h': diff --git a/usr.sbin/pw/pw_utils.c b/usr.sbin/pw/pw_utils.c index 87dd421ca8a3..363cceafec39 100644 --- a/usr.sbin/pw/pw_utils.c +++ b/usr.sbin/pw/pw_utils.c @@ -42,7 +42,7 @@ pw_checkfd(char *nptr) int fd = -1; if (strcmp(nptr, "-") == 0) - return '-'; + return (_PWDASH); fd = strtonum(nptr, 0, INT_MAX, &errstr); if (errstr != NULL) errx(EX_USAGE, "Bad file descriptor '%s': %s", diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile index 910a563d680d..b92897ab9208 100644 --- a/usr.sbin/pw/tests/Makefile +++ b/usr.sbin/pw/tests/Makefile @@ -2,8 +2,16 @@ PACKAGE= tests BINDIR= ${TESTSDIR} +.PATH: ${SRCTOP}/usr.sbin/pw + PROGS+= crypt -LIBADD+= crypt +LIBADD.crypt+= crypt + +ATF_TESTS_C= pw_unit_test +SRCS.pw_unit_test= pw_unit_test.c \ + pw_utils.c strtounum.c +LIBADD.pw_unit_test= util +CFLAGS.pw_unit_test= -I${SRCTOP}/usr.sbin/pw ATF_TESTS_SH= pw_etcdir_test \ pw_lock_test \ diff --git a/usr.sbin/pw/tests/pw_unit_test.c b/usr.sbin/pw/tests/pw_unit_test.c new file mode 100644 index 000000000000..f335f8e100a5 --- /dev/null +++ b/usr.sbin/pw/tests/pw_unit_test.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2026 Baptiste Daroussin + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "pw.h" +#include "pwupd.h" + +struct pwconf conf; + +/* stub */ +struct userconf * +read_userconfig(char const *file __unused) +{ + + return (NULL); +} + +ATF_TC_WITHOUT_HEAD(checkfd_dash); +ATF_TC_BODY(checkfd_dash, tc) +{ + char dash[] = "-"; + + ATF_CHECK_EQ(pw_checkfd(dash), _PWDASH); +} + +ATF_TC_WITHOUT_HEAD(checkfd_zero); +ATF_TC_BODY(checkfd_zero, tc) +{ + char zero[] = "0"; + + ATF_CHECK_EQ(pw_checkfd(zero), 0); +} + +ATF_TC_WITHOUT_HEAD(checkfd_valid); +ATF_TC_BODY(checkfd_valid, tc) +{ + char five[] = "5"; + + ATF_CHECK_EQ(pw_checkfd(five), 5); +} + +ATF_TC_WITHOUT_HEAD(checkfd_max); +ATF_TC_BODY(checkfd_max, tc) +{ + char max[] = "2147483647"; + + ATF_CHECK_EQ(pw_checkfd(max), INT_MAX); +} + +static void +checkfd_invalid(const char *value, const char *errstr) +{ + pid_t pid; + char buf[32]; + char experr[128]; + + strlcpy(buf, value, sizeof(buf)); + snprintf(experr, sizeof(experr), + "pw_unit_test: Bad file descriptor '%s': %s\n", value, errstr); + pid = atf_utils_fork(); + if (pid == 0) { + pw_checkfd(buf); + exit(1); + } + atf_utils_wait(pid, EX_USAGE, "", experr); +} + +ATF_TC_WITHOUT_HEAD(checkfd_invalid); +ATF_TC_BODY(checkfd_invalid, tc) +{ + checkfd_invalid("abc", "invalid"); +} + +ATF_TC_WITHOUT_HEAD(checkfd_negative); +ATF_TC_BODY(checkfd_negative, tc) +{ + checkfd_invalid("-1", "too small"); +} + +ATF_TC_WITHOUT_HEAD(checkfd_overflow); +ATF_TC_BODY(checkfd_overflow, tc) +{ + checkfd_invalid("999999999999", "too large"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, checkfd_dash); + ATF_TP_ADD_TC(tp, checkfd_zero); + ATF_TP_ADD_TC(tp, checkfd_valid); + ATF_TP_ADD_TC(tp, checkfd_max); + ATF_TP_ADD_TC(tp, checkfd_invalid); + ATF_TP_ADD_TC(tp, checkfd_negative); + ATF_TP_ADD_TC(tp, checkfd_overflow); + + return (atf_no_error()); +} diff --git a/usr.sbin/pw/tests/pw_useradd_test.sh b/usr.sbin/pw/tests/pw_useradd_test.sh index 4b0778759203..82c8d8b8524f 100755 --- a/usr.sbin/pw/tests/pw_useradd_test.sh +++ b/usr.sbin/pw/tests/pw_useradd_test.sh @@ -528,6 +528,38 @@ user_add_already_in_group_body() grep testuser ${HOME}/group } +atf_test_case user_add_fd_dash +user_add_fd_dash_body() +{ + populate_etc_skel + + atf_check -s exit:0 ${PW} useradd fdtest -h - + atf_check -s exit:0 -o match:"^fdtest:\*:" \ + grep "^fdtest:" ${HOME}/master.passwd +} + +atf_test_case user_add_fd_numeric +user_add_fd_numeric_body() +{ + populate_etc_skel + + echo "testpass123" > ${HOME}/pwfile + fd=$(echo ${HOME}/pwfile) + echo "stdinpass" | atf_check -s exit:0 \ + ${PW} useradd fdstdin -h 0 + atf_check -s exit:0 -o not-match:"^fdstdin:\*:" \ + grep "^fdstdin:" ${HOME}/master.passwd +} + +atf_test_case user_add_H_dash_rejected +user_add_H_dash_rejected_body() +{ + populate_etc_skel + + atf_check -s exit:64 -e inline:"pw: -H expects a file descriptor\n" \ + ${PW} useradd htest -H - +} + atf_init_test_cases() { atf_add_test_case user_add atf_add_test_case user_add_noupdate @@ -572,4 +604,7 @@ atf_init_test_cases() { atf_add_test_case user_add_conf_defaultpasswd atf_add_test_case user_add_existing_login_group atf_add_test_case user_add_already_in_group + atf_add_test_case user_add_fd_dash + atf_add_test_case user_add_fd_numeric + atf_add_test_case user_add_H_dash_rejected }