svn commit: r310144 - head/usr.bin/iconv

Conrad E. Meyer cem at FreeBSD.org
Fri Dec 16 02:06:36 UTC 2016


Author: cem
Date: Fri Dec 16 02:06:34 2016
New Revision: 310144
URL: https://svnweb.freebsd.org/changeset/base/310144

Log:
  iconv(1): Capsicumify
  
  This takes the usual shortcut of only sandboxing the last input file.
  It's a first cut and this program will be easy to adapt to sandbox all
  files in the future.
  
  iconv(1) has been changed to only open the conversion descriptor once,
  since the input and output encodings are fixed over all inputs.
  Instead, the descriptor is simply reset after each use (documented in
  iconv(3) API).
  
  Reviewed by:	no one, unfortunately
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D7917

Modified:
  head/usr.bin/iconv/iconv.c

Modified: head/usr.bin/iconv/iconv.c
==============================================================================
--- head/usr.bin/iconv/iconv.c	Fri Dec 16 02:03:40 2016	(r310143)
+++ head/usr.bin/iconv/iconv.c	Fri Dec 16 02:06:34 2016	(r310144)
@@ -28,7 +28,9 @@
  */
 
 #include <sys/cdefs.h>
+#include <sys/capsicum.h>
 
+#include <capsicum_helpers.h>
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
@@ -41,7 +43,7 @@
 #include <string.h>
 #include <unistd.h>
 
-static int		do_conv(FILE *, const char *, const char *, bool, bool);
+static int		do_conv(FILE *, iconv_t, bool, bool);
 static int		do_list(unsigned int, const char * const *, void *);
 static void		usage(void) __dead2;
 
@@ -67,23 +69,16 @@ usage(void)
 #define INBUFSIZE 1024
 #define OUTBUFSIZE (INBUFSIZE * 2)
 static int
-do_conv(FILE *fp, const char *from, const char *to, bool silent,
-    bool hide_invalid)
+do_conv(FILE *fp, iconv_t cd, bool silent, bool hide_invalid)
 {
-	iconv_t cd;
 	char inbuf[INBUFSIZE], outbuf[OUTBUFSIZE], *in, *out;
 	unsigned long long invalids;
 	size_t inbytes, outbytes, ret;
 
-	if ((cd = iconv_open(to, from)) == (iconv_t)-1)
-		err(EXIT_FAILURE, "iconv_open(%s, %s)", to, from);
-
-	if (hide_invalid) {
-		int arg = 1;
+	int arg = (int)hide_invalid;
+	if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&arg) == -1)
+		err(EXIT_FAILURE, "iconvctl(DISCARD_ILSEQ, %d)", arg);
 
-		if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&arg) == -1)
-			err(EXIT_FAILURE, NULL);
-	}
 	invalids = 0;
 	while ((inbytes = fread(inbuf, 1, INBUFSIZE, fp)) > 0) {
 		in = inbuf;
@@ -133,7 +128,6 @@ do_conv(FILE *fp, const char *from, cons
 	if (invalids > 0 && !silent)
 		warnx("warning: invalid characters: %llu", invalids);
 
-	iconv_close(cd);
 	return (invalids > 0);
 }
 
@@ -155,6 +149,7 @@ do_list(unsigned int n, const char * con
 int
 main(int argc, char **argv)
 {
+	iconv_t cd;
 	FILE *fp;
 	const char *opt_f, *opt_t;
 	int ch, i, res;
@@ -201,9 +196,28 @@ main(int argc, char **argv)
 	argv += optind;
 	if ((strcmp(opt_f, "") == 0) && (strcmp(opt_t, "") == 0))
 		usage();
-	if (argc == 0)
-		res = do_conv(stdin, opt_f, opt_t, opt_s, opt_c);
-	else {
+
+	if (caph_limit_stdio() < 0)
+		err(EXIT_FAILURE, "capsicum");
+
+	/*
+	 * Cache NLS data, for strerror, for err(3), before entering capability
+	 * mode.
+	 */
+	caph_cache_catpages();
+
+	/*
+	 * Cache iconv conversion handle before entering sandbox.
+	 */
+	cd = iconv_open(opt_t, opt_f);
+	if (cd == (iconv_t)-1)
+		err(EXIT_FAILURE, "iconv_open(%s, %s)", opt_t, opt_f);
+
+	if (argc == 0) {
+		if (cap_enter() < 0 && errno != ENOSYS)
+			err(EXIT_FAILURE, "unable to enter capability mode");
+		res = do_conv(stdin, cd, opt_s, opt_c);
+	} else {
 		res = 0;
 		for (i = 0; i < argc; i++) {
 			fp = (strcmp(argv[i], "-") != 0) ?
@@ -211,9 +225,17 @@ main(int argc, char **argv)
 			if (fp == NULL)
 				err(EXIT_FAILURE, "Cannot open `%s'",
 				    argv[i]);
-			res |= do_conv(fp, opt_f, opt_t, opt_s, opt_c);
+			/* Enter Capsicum sandbox for final input file. */
+			if (i + 1 == argc && cap_enter() < 0 && errno != ENOSYS)
+				err(EXIT_FAILURE,
+				    "unable to enter capability mode");
+			res |= do_conv(fp, cd, opt_s, opt_c);
 			(void)fclose(fp);
+
+			/* Reset iconv descriptor state. */
+			(void)iconv(cd, NULL, NULL, NULL, NULL);
 		}
 	}
+	iconv_close(cd);
 	return (res == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }


More information about the svn-src-head mailing list