From nobody Wed Nov 02 12:35:46 2022 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 4N2RFG6ftwz4h4Tb; Wed, 2 Nov 2022 12:35:46 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4N2RFG661Fz43CP; Wed, 2 Nov 2022 12:35:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1667392546; 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=Ich4Ni9mBzb8rdI2r0pvKEUF2QJrMebwixhxtsuvtvY=; b=aQPRdwZSC4tkB4dgeOPkUKZL4qbvx3MdKPtPMMCmwV+fAv8RbO7vyP0IKffpK9CeJkyfNj M5nCpqBQ5rugGQuLSRVhAhnt+46xi5oHvitqx4hxKQHt9CrRboUqneAwdbeVxjlbZYYLqE Qn38S47x8QTtUeq69pcR9WEtJ6/RhLw2v5kqcBjhZ3sxjPlARGqzqzqMmhnU5HDcmBZHAN /hKk17k3k1H0+9k6TXT4netE9r4HOnnyxVjBFwoHPospOFwV4EaTjgJJ1TcEOzscvqTbeB 2xry+bWKVUmTff/4TJD+mAVBUUBthCIHqLQbNc2wHnk1uTkme1ZhqMO/5+O0IQ== 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 4N2RFG4ZrNzwG2; Wed, 2 Nov 2022 12:35:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2A2CZkug081091; Wed, 2 Nov 2022 12:35:46 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2A2CZk1t081090; Wed, 2 Nov 2022 12:35:46 GMT (envelope-from git) Date: Wed, 2 Nov 2022 12:35:46 GMT Message-Id: <202211021235.2A2CZk1t081090@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: =?utf-8?Q?Dag-Erling=20Sm=C3=B8rgrav?= Subject: git: 0ed86bcc0b2a - stable/13 - xinstall: fix dounpriv logic, add tests 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: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@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/stable/13 X-Git-Reftype: branch X-Git-Commit: 0ed86bcc0b2adca5aad1446720799f6fdddb8dd7 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1667392546; 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=Ich4Ni9mBzb8rdI2r0pvKEUF2QJrMebwixhxtsuvtvY=; b=FRDSDohHnKQD4bxh/rdDdSA21OpfulbEBXWbbXXWRHQm4NfkGhkbAJZ1r3zGcfe6cqRGKN h++Fcil35DQVDql7WvSiqM5rGj3SxIyK7Cdg03+aVAU+r7N+CGTcTyAO/xRU8emxoj/n93 AailQMu2SmsAJbSZYGJhMkUdx1yna5pJG+ctLmOk1TxjAiq45WHoBdffjc82NOS+Bhdetf jw7w6fTe83zKb3UrL+flS7/Rw7hO+H15yx6OyKVH3lRLK6SCH8G4jouUFsw73Da+053+RK wyr6cmZn+1oj4N3DbUTYqiBj1/lZ5v/BGyYgbXQv/bcekTvo8mgTlywJb1D3UA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1667392546; a=rsa-sha256; cv=none; b=QMrjQNzYMzMzThqPsXa/2lKMPvC8Ro8fKosdF1MotWK3HyGI7jW3qfCEsKYYx2xq8Zzy3n iL2Do5xJiKghYWjL0DnFwv5j66SL5mQfCziThs8eh6LUfWX9q6qG8HAdvanhr/JnxYgY1R OeTKxsI+2WMLDRuIBTuQ/xnAyzb7dW+nhviFMMntG0YHNod/x+yyn79WOTspzY2xbagUol nmq6Uoq9488KR8aNTMQ6Purqouf1302q3jXuYUmTj1qS+SpKaS4uxxe/w9mVzAmQG1CLgq zL8zk1ea7GDu8MJTjFEUnh6sQfgbyiRzu8iqVWakTppaakhc0mXVsZcGcWTgwA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=0ed86bcc0b2adca5aad1446720799f6fdddb8dd7 commit 0ed86bcc0b2adca5aad1446720799f6fdddb8dd7 Author: Dag-Erling Smørgrav AuthorDate: 2022-08-03 18:59:28 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2022-11-02 09:36:19 +0000 xinstall: fix dounpriv logic, add tests Sponsored by: Klara, Inc. MFC after: 1 week (cherry picked from commit 36d67475f5497664d33c41c2f6745dcb30b0ec42) xinstall: make md5 and ripemd160 conditional Sponsored by: Klara, Inc. (cherry picked from commit c7a8e8d372b212c97dde6ce2731db27aa0b2201c) xinstall: use dynamic bufsize as in cat(1) / cp(1). Sponsored by: Klara, Inc. (cherry picked from commit 54d8d0fe12a4996427923048ab4261819774fbd4) xinstall: alphabetize: upper case precedes lower. Sponsored by: Klara, Inc. (cherry picked from commit f44e2577120c60cd92f685037bbb63127e0091e4) --- usr.bin/xinstall/Makefile | 3 +- usr.bin/xinstall/install.1 | 14 ++--- usr.bin/xinstall/tests/install_test.sh | 80 +++++++++++++++++++++++++ usr.bin/xinstall/xinstall.c | 105 +++++++++++++++++++++++++++++---- 4 files changed, 181 insertions(+), 21 deletions(-) diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile index ce70cb882190..9969ef104e98 100644 --- a/usr.bin/xinstall/Makefile +++ b/usr.bin/xinstall/Makefile @@ -14,7 +14,8 @@ MAN= install.1 CFLAGS+= -I${SRCTOP}/contrib/mtree CFLAGS+= -I${SRCTOP}/lib/libnetbsd -LIBADD= md +LIBADD= md +CFLAGS+= -DWITH_MD5 -DWITH_RIPEMD160 HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1 index 4d4db9633d9b..2f1bb080d9c0 100644 --- a/usr.bin/xinstall/install.1 +++ b/usr.bin/xinstall/install.1 @@ -28,7 +28,7 @@ .\" From: @(#)install.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd August 12, 2019 +.Dd August 4, 2022 .Dt INSTALL 1 .Os .Sh NAME @@ -99,6 +99,12 @@ option's argument. .Pp The options are as follows: .Bl -tag -width indent +.It Fl B Ar suffix +Use +.Ar suffix +as the backup suffix if +.Fl b +is given. .It Fl b Back up any existing files before overwriting them by renaming them to @@ -106,12 +112,6 @@ them to See .Fl B for specifying a different backup suffix. -.It Fl B Ar suffix -Use -.Ar suffix -as the backup suffix if -.Fl b -is given. .It Fl C Copy the file. If the target file already exists and the files are the same, diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh index c723a6e0d280..e95f40fc19e7 100755 --- a/usr.bin/xinstall/tests/install_test.sh +++ b/usr.bin/xinstall/tests/install_test.sh @@ -404,6 +404,84 @@ symbolic_link_relative_absolute_common_body() { fi } +atf_test_case set_owner_group_mode +set_owner_group_mode_head() { + atf_set "require.user" "root" +} +set_owner_group_mode_body() { + local fu=65531 fg=65531 + local cu=65532 cg=65532 + local u="$(id -u)" + local g="$(id -g)" + local m=0755 cm=4444 + printf "test" >testf + atf_check chown "$fu:$fg" testf + atf_check chmod "$m" testf + + atf_check install testf testc + atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -o "$cu" testf testc + atf_check_equal "$cu:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -g "$cg" testf testc + atf_check_equal "$u:$cg:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -o "$cu" -g "$cg" testf testc + atf_check_equal "$cu:$cg:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -m "$cm" testf testc + atf_check_equal "$u:$g:10$cm" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -o "$cu" -m "$cm" testf testc + atf_check_equal "$cu:$g:10$cm" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -g "$cg" -m "$cm" testf testc + atf_check_equal "$u:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -o "$cu" -g "$cg" -m "$cm" testf testc + atf_check_equal "$cu:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)" +} + +atf_test_case set_owner_group_mode_unpriv +set_owner_group_mode_unpriv_head() { + atf_set "require.user" "root" +} +set_owner_group_mode_unpriv_body() { + local fu=65531 fg=65531 + local cu=65532 cg=65532 + local u="$(id -u)" + local g="$(id -g)" + local m=0755 cm=4444 cM=0444 + printf "test" >testf + atf_check chown "$fu:$fg" testf + atf_check chmod "$m" testf + + atf_check install -U testf testc + atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -o "$cu" testf testc + atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -g "$cg" testf testc + atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -o "$cu" -g "$cg" testf testc + atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -m "$cm" testf testc + atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -o "$cu" -m "$cm" testf testc + atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -g "$cg" -m "$cm" testf testc + atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" + + atf_check install -U -o "$cu" -g "$cg" -m "$cm" testf testc + atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" +} + atf_init_test_cases() { atf_add_test_case copy_to_nonexistent atf_add_test_case copy_to_nonexistent_safe @@ -444,4 +522,6 @@ atf_init_test_cases() { atf_add_test_case symbolic_link_relative_absolute_source_and_dest2 atf_add_test_case symbolic_link_relative_absolute_common atf_add_test_case mkdir_simple + atf_add_test_case set_owner_group_mode + atf_add_test_case set_owner_group_mode_unpriv } diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 114614abd16f..691a16191bba 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -57,10 +57,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef WITH_MD5 #include +#endif #include #include +#ifdef WITH_RIPEMD160 #include +#endif #include #include #include @@ -75,6 +79,21 @@ __FBSDID("$FreeBSD$"); #include "mtree.h" +/* + * Memory strategy threshold, in pages: if physmem is larger then this, use a + * large buffer. + */ +#define PHYSPAGES_THRESHOLD (32*1024) + +/* Maximum buffer size in bytes - do not allow it to grow larger than this. */ +#define BUFSIZE_MAX (2*1024*1024) + +/* + * Small (default) buffer size in bytes. It's inefficient for this to be + * smaller than MAXPHYS. + */ +#define BUFSIZE_SMALL (MAXPHYS) + /* * We need to build xinstall during the bootstrap stage when building on a * non-FreeBSD system. Linux does not have the st_flags and st_birthtime @@ -100,8 +119,12 @@ __FBSDID("$FreeBSD$"); #define BACKUP_SUFFIX ".old" typedef union { +#ifdef WITH_MD5 MD5_CTX MD5; +#endif +#ifdef WITH_RIPEMD160 RIPEMD160_CTX RIPEMD160; +#endif SHA1_CTX SHA1; SHA256_CTX SHA256; SHA512_CTX SHA512; @@ -109,8 +132,12 @@ typedef union { static enum { DIGEST_NONE = 0, +#ifdef WITH_MD5 DIGEST_MD5, +#endif +#ifdef WITH_RIPEMD160 DIGEST_RIPEMD160, +#endif DIGEST_SHA1, DIGEST_SHA256, DIGEST_SHA512, @@ -288,10 +315,14 @@ main(int argc, char *argv[]) if (digest != NULL) { if (strcmp(digest, "none") == 0) { digesttype = DIGEST_NONE; +#ifdef WITH_MD5 } else if (strcmp(digest, "md5") == 0) { digesttype = DIGEST_MD5; +#endif +#ifdef WITH_RIPEMD160 } else if (strcmp(digest, "rmd160") == 0) { digesttype = DIGEST_RIPEMD160; +#endif } else if (strcmp(digest, "sha1") == 0) { digesttype = DIGEST_SHA1; } else if (strcmp(digest, "sha256") == 0) { @@ -402,10 +433,14 @@ digest_file(const char *name) { switch (digesttype) { +#ifdef WITH_MD5 case DIGEST_MD5: return (MD5File(name, NULL)); +#endif +#ifdef WITH_RIPEMD160 case DIGEST_RIPEMD160: return (RIPEMD160_File(name, NULL)); +#endif case DIGEST_SHA1: return (SHA1_File(name, NULL)); case DIGEST_SHA256: @@ -424,12 +459,16 @@ digest_init(DIGEST_CTX *c) switch (digesttype) { case DIGEST_NONE: break; +#ifdef WITH_MD5 case DIGEST_MD5: MD5Init(&(c->MD5)); break; +#endif +#ifdef WITH_RIPEMD160 case DIGEST_RIPEMD160: RIPEMD160_Init(&(c->RIPEMD160)); break; +#endif case DIGEST_SHA1: SHA1_Init(&(c->SHA1)); break; @@ -449,12 +488,16 @@ digest_update(DIGEST_CTX *c, const char *data, size_t len) switch (digesttype) { case DIGEST_NONE: break; +#ifdef WITH_MD5 case DIGEST_MD5: MD5Update(&(c->MD5), data, len); break; +#endif +#ifdef WITH_RIPEMD160 case DIGEST_RIPEMD160: RIPEMD160_Update(&(c->RIPEMD160), data, len); break; +#endif case DIGEST_SHA1: SHA1_Update(&(c->SHA1), data, len); break; @@ -472,10 +515,14 @@ digest_end(DIGEST_CTX *c, char *buf) { switch (digesttype) { +#ifdef WITH_MD5 case DIGEST_MD5: return (MD5End(&(c->MD5), buf)); +#endif +#ifdef WITH_RIPEMD160 case DIGEST_RIPEMD160: return (RIPEMD160_End(&(c->RIPEMD160), buf)); +#endif case DIGEST_SHA1: return (SHA1_End(&(c->SHA1), buf)); case DIGEST_SHA256: @@ -1009,19 +1056,18 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) #endif } - if (!dounpriv & - (gid != (gid_t)-1 && gid != to_sb.st_gid) || - (uid != (uid_t)-1 && uid != to_sb.st_uid)) + if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) || + (uid != (uid_t)-1 && uid != to_sb.st_uid))) { if (fchown(to_fd, uid, gid) == -1) { serrno = errno; (void)unlink(to_name); errno = serrno; err(EX_OSERR,"%s: chown/chgrp", to_name); } - + } if (mode != (to_sb.st_mode & ALLPERMS)) { if (fchmod(to_fd, - dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) { + dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) { serrno = errno; (void)unlink(to_name); errno = serrno; @@ -1036,7 +1082,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) * trying to turn off UF_NODUMP. If we're trying to set real flags, * then warn if the fs doesn't support it, otherwise fail. */ - if (!dounpriv & !devnull && (flags & SETFLAGS || + if (!dounpriv && !devnull && (flags & SETFLAGS || (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && fchflags(to_fd, flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { @@ -1082,7 +1128,7 @@ compare(int from_fd, const char *from_name __unused, size_t from_len, return 1; do_digest = (digesttype != DIGEST_NONE && dresp != NULL && - *dresp == NULL); + *dresp == NULL); if (from_len <= MAX_CMP_SIZE) { if (do_digest) digest_init(&ctx); @@ -1108,15 +1154,32 @@ compare(int from_fd, const char *from_name __unused, size_t from_len, } out: if (!done_compare) { - char buf1[MAXBSIZE]; - char buf2[MAXBSIZE]; + static char *buf, *buf1, *buf2; + static size_t bufsize; int n1, n2; + if (buf == NULL) { + /* + * Note that buf and bufsize are static. If + * malloc() fails, it will fail at the start + * and not copy only some files. + */ + if (sysconf(_SC_PHYS_PAGES) > + PHYSPAGES_THRESHOLD) + bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); + else + bufsize = BUFSIZE_SMALL; + buf = malloc(bufsize * 2); + if (buf == NULL) + err(1, "Not enough memory"); + buf1 = buf; + buf2 = buf + bufsize; + } rv = 0; lseek(from_fd, 0, SEEK_SET); lseek(to_fd, 0, SEEK_SET); while (rv == 0) { - n1 = read(from_fd, buf1, sizeof(buf1)); + n1 = read(from_fd, buf1, bufsize); if (n1 == 0) break; /* EOF */ else if (n1 > 0) { @@ -1233,10 +1296,11 @@ static char * copy(int from_fd, const char *from_name, int to_fd, const char *to_name, off_t size) { + static char *buf = NULL; + static size_t bufsize; int nr, nw; int serrno; char *p; - char buf[MAXBSIZE]; int done_copy; DIGEST_CTX ctx; @@ -1270,7 +1334,22 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name, done_copy = 1; } if (!done_copy) { - while ((nr = read(from_fd, buf, sizeof(buf))) > 0) { + if (buf == NULL) { + /* + * Note that buf and bufsize are static. If + * malloc() fails, it will fail at the start + * and not copy only some files. + */ + if (sysconf(_SC_PHYS_PAGES) > + PHYSPAGES_THRESHOLD) + bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); + else + bufsize = BUFSIZE_SMALL; + buf = malloc(bufsize); + if (buf == NULL) + err(1, "Not enough memory"); + } + while ((nr = read(from_fd, buf, bufsize)) > 0) { if ((nw = write(to_fd, buf, nr)) != nr) { serrno = errno; (void)unlink(to_name); @@ -1380,7 +1459,7 @@ install_dir(char *path) ch = *p; *p = '\0'; again: - if (stat(path, &sb) < 0) { + if (stat(path, &sb) != 0) { if (errno != ENOENT || tried_mkdir) err(EX_OSERR, "stat %s", path); if (mkdir(path, 0755) < 0) {