git: efec2f0d4e17 - stable/14 - md5: Enter capability mode earlier

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 15 Feb 2024 14:23:41 UTC
The branch stable/14 has been updated by markj:

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

commit efec2f0d4e1739c94cb2581e6ff25a41fc9e38c2
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-01-03 18:00:47 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-02-15 14:16:07 +0000

    md5: Enter capability mode earlier
    
    Reviewed by:    markj
    MFC after:      1 month
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/988
    
    (cherry picked from commit 9b20849bc5f1b500f2de7aeca77f0e6556069bbb)
---
 sbin/md5/Makefile |  9 ++++++---
 sbin/md5/md5.c    | 57 +++++++++++++++++++++++++++++++------------------------
 2 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile
index 359c4b96f9fd..e4e6335ae875 100644
--- a/sbin/md5/Makefile
+++ b/sbin/md5/Makefile
@@ -59,16 +59,19 @@ MLINKS=	md5.1 md5sum.1 \
 
 LIBADD=	md
 
-.ifndef(BOOTSTRAPPING)
+.include <src.opts.mk>
+
+.if ${MK_CASPER} != "no" && !defined(RESCUE) && !defined(BOOTSTRAPPING)
 # Avoid depending on capsicum during bootstrap. caph_limit_stdout() is not
 # available when building for Linux/MacOS or older FreeBSD hosts.
 # We need to bootstrap md5 when building on Linux since the md5sum command there
 # produces different output.
 CFLAGS+=-DHAVE_CAPSICUM
+CFLAGS+=-DWITH_CASPER
+LIBADD+=	casper
+LIBADD+=	cap_fileargs
 .endif
 
-.include <src.opts.mk>
-
 HAS_TESTS=
 SUBDIR.${MK_TESTS}+= tests
 
diff --git a/sbin/md5/md5.c b/sbin/md5/md5.c
index 15fd7ebec5d4..eb9a2ffae1cc 100644
--- a/sbin/md5/md5.c
+++ b/sbin/md5/md5.c
@@ -47,6 +47,8 @@
 #ifdef HAVE_CAPSICUM
 #include <sys/capsicum.h>
 #include <capsicum_helpers.h>
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
 #endif
 
 /*
@@ -311,6 +313,7 @@ gnu_check(const char *checksumsfile)
 	const char	*digestname;
 	size_t	digestnamelen;
 	size_t	hashstrlen;
+	struct stat st;
 
 	if (strcmp(checksumsfile, "-") == 0)
 		inp = stdin;
@@ -358,6 +361,15 @@ gnu_check(const char *checksumsfile)
 		rec = malloc(sizeof(*rec));
 		if (rec == NULL)
 			errx(1, "malloc failed");
+
+		if (*filename == '*' ||
+		    *filename == ' ' ||
+		    *filename == 'U' ||
+		    *filename == '^') {
+			if (lstat(filename, &st) != 0)
+				filename++;
+		}
+
 		rec->chksum = strdup(hashstr);
 		rec->filename = strdup(filename);
 		if (rec->chksum == NULL || rec->filename == NULL)
@@ -385,6 +397,7 @@ main(int argc, char *argv[])
 {
 #ifdef HAVE_CAPSICUM
 	cap_rights_t	rights;
+	fileargs_t	*fa = NULL;
 #endif
 	const struct option *longopts;
 	const char *shortopts;
@@ -585,24 +598,25 @@ main(int argc, char *argv[])
 		rec = head;
 	}
 
+#ifdef HAVE_CAPSICUM
+	fa = fileargs_init(argc, argv, O_RDONLY, 0,
+	    cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN | FA_LSTAT);
+	if (fa == NULL)
+		err(1, "Unable to initialize casper");
+	if (caph_enter_casper() < 0)
+		err(1, "Unable to enter capability mode");
+#endif
+
 	if (*argv) {
 		do {
-			struct stat st;
 			const char *filename = *argv;
 			const char *filemode = "rb";
 
-			if (*filename == '*' ||
-			    *filename == ' ' ||
-			    *filename == 'U' ||
-			    *filename == '^') {
-				if (lstat(filename, &st) != 0) {
-					input_mode = (int)*filename;
-					filename++;
-				}
-			}
-			if (input_mode == input_text)
-				filemode = "r";
+#ifdef HAVE_CAPSICUM
+			if ((f = fileargs_fopen(fa, filename, filemode)) == NULL) {
+#else
 			if ((f = fopen(filename, filemode)) == NULL) {
+#endif
 				if (errno != ENOENT || !(cflag && ignoreMissing)) {
 					warn("%s", filename);
 					failed = true;
@@ -611,20 +625,10 @@ main(int argc, char *argv[])
 					rec = rec->next;
 				continue;
 			}
-			/*
-			 * XXX Enter capability mode on the last argv file.
-			 * When a casper file service or other approach is
-			 * available, switch to that and enter capability mode
-			 * earlier.
-			 */
-			if (*(argv + 1) == NULL) {
 #ifdef HAVE_CAPSICUM
-				cap_rights_init(&rights, CAP_READ, CAP_FSTAT);
-				if (caph_rights_limit(fileno(f), &rights) < 0 ||
-				    caph_enter() < 0)
-					err(1, "capsicum");
+			if (caph_rights_limit(fileno(f), &rights) < 0)
+				err(1, "capsicum");
 #endif
-			}
 			if (cflag && mode != mode_bsd) {
 				checkAgainst = rec->chksum;
 				rec = rec->next;
@@ -635,7 +639,7 @@ main(int argc, char *argv[])
 		} while (*++argv);
 	} else if (!cflag && string == NULL && !skip) {
 #ifdef HAVE_CAPSICUM
-		if (caph_limit_stdin() < 0 || caph_enter() < 0)
+		if (caph_limit_stdin() < 0)
 			err(1, "capsicum");
 #endif
 		if (mode == mode_bsd)
@@ -659,6 +663,9 @@ main(int argc, char *argv[])
 		if (checksFailed != 0 || (strict && malformed > 0))
 			return (1);
 	}
+#ifdef HAVE_CAPSICUM
+	fileargs_free(fa);
+#endif
 	if (failed)
 		return (1);
 	if (checksFailed > 0)