git: 6a7238fd7c60 - main - pw: set the user's home directory mode if it existed

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sun, 01 Dec 2024 19:10:50 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=6a7238fd7c60f35191eadaa026d3d395c6140c47

commit 6a7238fd7c60f35191eadaa026d3d395c6140c47
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-12-01 19:05:57 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-12-01 19:08:31 +0000

    pw: set the user's home directory mode if it existed
    
    The adduser(8) prompt allows one to set the mode of a new home
    directory, but pw(8) doesn't honor the -M mode if the home directory
    already exists at creation time.  It doesn't seem to make sense to
    ignore the mode (which may lead to a security issue on the system being
    configured) when we'll happily chown an existing directory, so fix the
    inconsistency.
    
    PR:             280099
    Reviewed by:    des, jlduran (previous version)
    Differential Revision:  https://reviews.freebsd.org/D46443
---
 usr.sbin/adduser/adduser.8 |  6 ++++--
 usr.sbin/pw/cpdir.c        | 27 +++++++++++++++++++++------
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/usr.sbin/adduser/adduser.8 b/usr.sbin/adduser/adduser.8
index 8ba623fedd9d..e21a7653f250 100644
--- a/usr.sbin/adduser/adduser.8
+++ b/usr.sbin/adduser/adduser.8
@@ -27,7 +27,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 11, 2024
+.Dd December 1, 2024
 .Dt ADDUSER 8
 .Os
 .Sh NAME
@@ -246,7 +246,9 @@ file can reference the internal variables of the
 script.
 .It Fl M Ar mode
 Create the home directory with permissions set to
-.Ar mode .
+.Ar mode ,
+modified by the current
+.Xr umask 2 .
 .It Fl N
 Do not read the default configuration file.
 .It Fl q
diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c
index 504933ab88af..3dee8f7c43ac 100644
--- a/usr.sbin/pw/cpdir.c
+++ b/usr.sbin/pw/cpdir.c
@@ -49,13 +49,28 @@ copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid,
 	if (*dir == '/')
 		dir++;
 
-	if (mkdirat(rootfd, dir, mode) != 0 && errno != EEXIST) {
-		warn("mkdir(%s)", dir);
-		return;
+	if (mkdirat(rootfd, dir, mode) != 0) {
+		mode_t pumask;
+
+		if (errno != EEXIST) {
+			warn("mkdir(%s)", dir);
+			return;
+		}
+
+		pumask = umask(0);
+		umask(pumask);
+
+		if (fchmodat(rootfd, dir, mode & ~pumask,
+		    AT_SYMLINK_NOFOLLOW) == -1)
+			warn("chmod(%s)", dir);
 	}
-	fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW);
-	if (flags > 0)
-		chflagsat(rootfd, dir, flags, AT_SYMLINK_NOFOLLOW);
+
+	if (fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW) == -1)
+		warn("chown(%s)", dir);
+
+	if (flags > 0 && chflagsat(rootfd, dir, flags,
+	    AT_SYMLINK_NOFOLLOW) == -1)
+		warn("chflags(%s)", dir);
 
 	if (skelfd == -1)
 		return;