From nobody Sat May 10 08:57:15 2025 X-Original-To: dev-commits-src-main@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 4ZvfrW4qPpz5w6P8; Sat, 10 May 2025 08:57:15 +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 "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZvfrW2cD6z3bST; Sat, 10 May 2025 08:57:15 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746867435; 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=GuUenWuRvxQDjexYXTOg/8v+EZoGBijmVJu6L8HtTvk=; b=nmnHWKh3A+vkg0mm6VzOvvSY/onRx0Wh6qQSZj5hYUVjP9lZgT6MBFLSDJrSkM6kp/RItR BWhXwM5ILws9J2/e3uUszcVit6naAkcqQjlR02FTyTLXAUriQXn5Ut81uuUuuWPt+Hyie8 QV9/ZZaeWUG7wp3iM4aou2A5H7nkhHsxX7WF5iDzq8K3FIEL50KiAqOYMDijShRLtUQAr5 Iz5npw1K1vCfSzyT5qvGehaehc3B2OULireHbwNP3BvJk/ncbMv9gIWtfKR++b1vs05tBt uKgFzJ4vQM8wugWrz0QA1WRhpUvSQaqG7Y7l0XZi/IaGCCQxpWwczonCggzQoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746867435; 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=GuUenWuRvxQDjexYXTOg/8v+EZoGBijmVJu6L8HtTvk=; b=R907h2/8RJcZSsOCbl8rqz2DzLyNnf+bMVfJg1TYPFnLDxkqs61ygkqPGMHa9s84aOwjLj rtpb0SzknGmoxEAeg9ANwKQuXtpWigbEG0RLWwhMzEHAjm1S39Xn5clIg1LEJ2PvV2O9u7 DVjhTqCCY/z8DI6UfuHNRRfSL7niRoFVu3wI1dzQmE7t5mogIYVlyi8mjBKf+iUFoaY665 Px/0iCddmUqk3N9pMoOSV2puaqQlgHsx53AFDOmU8XXE10RRis1zZqYjYM4z9/+9Xv0qdR PQmRmzKBcsDas8PfiE9RZ+ApuDZnogW1dt/zqEZpgT12r1MjlLLvVYYfIzPO/A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1746867435; a=rsa-sha256; cv=none; b=vtd+WbSGm9g3IHYNk9Mt5+HWVRuGWgC7GMArLoGhuwMtRwDgl6dd1qLJm0lEqckb3kxuXB bqHYutsjKOku2y0GHCmRXtNONeD/RfZaCWvlscvAtV5VRihQStf6UeXYatfokxAYX/4mkS YxljndFXCDY8u1ORxTKbVzdP+2N6pwGer5BZ7TdGt0X8UpPxuwywNF0IaD06VUKMFo5eTS CfyRaKxXU4waI7seT0NT8uoGZ/7p2KCeo6pbD4biPzPJHD7KU/ls7DDHgupVQ3nhl9WEhY FBCcOxBXAErF1ujByVf5Y0QaL+rmdgwA0tD6Au8x2o/JR9NHUTxnqoUVVRhn0g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZvfrW1vw3zgPK; Sat, 10 May 2025 08:57:15 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54A8vFMm059764; Sat, 10 May 2025 08:57:15 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54A8vFOZ059761; Sat, 10 May 2025 08:57:15 GMT (envelope-from git) Date: Sat, 10 May 2025 08:57:15 GMT Message-Id: <202505100857.54A8vFOZ059761@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 48578dcb6b7e - main - cp: Fix issues with destination directory mode. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 48578dcb6b7ea14e095bf783152b5bc66c045a10 Auto-Submitted: auto-generated The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=48578dcb6b7ea14e095bf783152b5bc66c045a10 commit 48578dcb6b7ea14e095bf783152b5bc66c045a10 Author: Dag-Erling Smørgrav AuthorDate: 2025-05-10 08:55:41 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-05-10 08:55:41 +0000 cp: Fix issues with destination directory mode. Ensure that we are able to enter the destination directory after we create it, even if the current umask would normally prevent it, and that it has the expected permissions once we are done, even if we had to tweak them to be able to enter it. Fixes: 82fc0d09e862 Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D50266 --- bin/cp/cp.c | 33 +++++++++++++++++++++++++++++---- bin/cp/tests/cp_test.sh | 23 +++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/bin/cp/cp.c b/bin/cp/cp.c index a3c8d910639c..c6b34198f20a 100644 --- a/bin/cp/cp.c +++ b/bin/cp/cp.c @@ -331,10 +331,18 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) assert(to.dir < 0); assert(root_stat == NULL); mode = curr_stat->st_mode | S_IRWXU; + /* + * Will our umask prevent us from entering + * the directory after we create it? + */ + if (~mask & S_IRWXU) + umask(~mask & ~S_IRWXU); if (mkdir(to.base, mode) != 0) { warn("%s", to.base); fts_set(ftsp, curr, FTS_SKIP); badcp = rval = 1; + if (~mask & S_IRWXU) + umask(~mask); continue; } to.dir = open(to.base, O_DIRECTORY | O_SEARCH); @@ -343,6 +351,8 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) (void)rmdir(to.base); fts_set(ftsp, curr, FTS_SKIP); badcp = rval = 1; + if (~mask & S_IRWXU) + umask(~mask); continue; } if (fstat(to.dir, &created_root_stat) != 0) { @@ -352,9 +362,14 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) fts_set(ftsp, curr, FTS_SKIP); to.dir = -1; badcp = rval = 1; + if (~mask & S_IRWXU) + umask(~mask); continue; } + if (~mask & S_IRWXU) + umask(~mask); root_stat = &created_root_stat; + curr->fts_number = 1; } else { /* entering a directory; append its name to to.path */ len = snprintf(to.end, END(to.path) - to.end, "%s%s", @@ -432,9 +447,7 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) } else if (curr->fts_number) { const char *path = *to.path ? to.path : dot; mode = curr_stat->st_mode; - if (((mode & (S_ISUID | S_ISGID | S_ISTXT)) || - ((mode | S_IRWXU) & mask) != (mode & mask)) && - fchmodat(to.dir, path, mode & mask, 0) != 0) { + if (fchmodat(to.dir, path, mode & mask, 0) != 0) { warn("chmod: %s/%s", to.base, to.path); rval = 1; } @@ -538,12 +551,22 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) */ if (dne) { mode = curr_stat->st_mode | S_IRWXU; + /* + * Will our umask prevent us from entering + * the directory after we create it? + */ + if (~mask & S_IRWXU) + umask(~mask & ~S_IRWXU); if (mkdirat(to.dir, to.path, mode) != 0) { warn("%s/%s", to.base, to.path); fts_set(ftsp, curr, FTS_SKIP); badcp = rval = 1; + if (~mask & S_IRWXU) + umask(~mask); break; } + if (~mask & S_IRWXU) + umask(~mask); } else if (!S_ISDIR(to_stat.st_mode)) { warnc(ENOTDIR, "%s/%s", to.base, to.path); fts_set(ftsp, curr, FTS_SKIP); @@ -554,8 +577,10 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) * Arrange to correct directory attributes later * (in the post-order phase) if this is a new * directory, or if the -p flag is in effect. + * Note that fts_number may already be set if this + * is the newly created destination directory. */ - curr->fts_number = pflag || dne; + curr->fts_number |= pflag || dne; break; case S_IFBLK: case S_IFCHR: diff --git a/bin/cp/tests/cp_test.sh b/bin/cp/tests/cp_test.sh index bfc4009580cb..29dce783ffe2 100755 --- a/bin/cp/tests/cp_test.sh +++ b/bin/cp/tests/cp_test.sh @@ -557,6 +557,28 @@ to_link_outside_body() cp -r dir dst } +atf_test_case dstmode +dstmode_body() +{ + mkdir -m 0755 dir + echo "foo" >dir/file + umask 0177 + #atf_check cp -R dir dst +#begin + # atf-check stupidly refuses to work if the current umask is + # weird, instead of just dealing with the situation + cp -R dir dst >stdout 2>stderr + rc=$? + umask 022 + atf_check_equal 0 $rc + atf_check cat stdout + atf_check cat stderr +#end + atf_check -o inline:"40600\n" stat -f%p dst + atf_check chmod 0750 dst + atf_check cmp dir/file dst/file +} + atf_init_test_cases() { atf_add_test_case basic @@ -593,4 +615,5 @@ atf_init_test_cases() atf_add_test_case to_dirlink atf_add_test_case to_deaddirlink atf_add_test_case to_link_outside + atf_add_test_case dstmode }