Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Sep 2016 16:25:41 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r305936 - head/usr.bin/soelim
Message-ID:  <201609181625.u8IGPfLd097287@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bapt
Date: Sun Sep 18 16:25:41 2016
New Revision: 305936
URL: https://svnweb.freebsd.org/changeset/base/305936

Log:
  Capsicum-ize soelim(1).
  
  As a trick to be able to access all files passed in arguments (readonly) within
  the sandbox we first open the root directory, then consider all files as
  relative to this file descriptor.
  
  This might be improved once casper add supports for filesystem.
  
  MFC after:	1 month
  Reviewed by:	allanjude
  Differential Revision:	https://reviews.freebsd.org/D7936

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

Modified: head/usr.bin/soelim/soelim.c
==============================================================================
--- head/usr.bin/soelim/soelim.c	Sun Sep 18 15:55:57 2016	(r305935)
+++ head/usr.bin/soelim/soelim.c	Sun Sep 18 16:25:41 2016	(r305936)
@@ -27,15 +27,19 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/capsicum.h>
 #include <sys/types.h>
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stringlist.h>
+#include <termios.h>
 #include <unistd.h>
 
 #define C_OPTION 0x1
@@ -51,18 +55,27 @@ usage(void)
 	exit(EXIT_FAILURE);
 }
 
+static const char *
+relpath(const char *path)
+{
+	while (*path == '/' && *path != '\0')
+		path++;
+
+	return (path);
+}
+
 static FILE *
-soelim_fopen(const char *name)
+soelim_fopen(int rootfd, const char *name)
 {
-	FILE *f;
 	char path[PATH_MAX];
 	size_t i;
+	int fd;
 
 	if (strcmp(name, "-") == 0)
 		return (stdin);
 
-	if ((f = fopen(name, "r")) != NULL)
-		return (f);
+	if ((fd = openat(rootfd, relpath(name), O_RDONLY)) != -1)
+		return (fdopen(fd, "r"));
 
 	if (*name == '/') {
 		warn("can't open '%s'", name);
@@ -72,17 +85,17 @@ soelim_fopen(const char *name)
 	for (i = 0; i < includes->sl_cur; i++) {
 		snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
 		    name);
-		if ((f = fopen(path, "r")) != NULL)
-			return (f);
+		if ((fd = openat(rootfd, relpath(path), O_RDONLY)) != -1)
+			return (fdopen(fd, "r"));
 	}
 
 	warn("can't open '%s'", name);
 
-	return (f);
+	return (NULL);
 }
 
 static int
-soelim_file(FILE *f, int flag)
+soelim_file(int rootfd, FILE *f, int flag)
 {
 	char *line = NULL;
 	char *walk, *cp;
@@ -118,7 +131,7 @@ soelim_file(FILE *f, int flag)
 			printf("%s", line);
 			continue;
 		}
-		if (soelim_file(soelim_fopen(walk), flag) == 1) {
+		if (soelim_file(rootfd, soelim_fopen(rootfd, walk), flag) == 1) {
 			free(line);
 			return (1);
 		}
@@ -135,11 +148,15 @@ soelim_file(FILE *f, int flag)
 int
 main(int argc, char **argv)
 {
-	int ch, i;
+	int ch, i, rootfd;
 	int ret = 0;
 	int flags = 0;
+	unsigned long cmd;
+	char cwd[MAXPATHLEN];
+	cap_rights_t rights;
 
 	includes = sl_init();
+	sl_add(includes, getcwd(cwd, sizeof(cwd)));
 	if (includes == NULL)
 		err(EXIT_FAILURE, "sl_init()");
 
@@ -165,13 +182,42 @@ main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
+	cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_IOCTL);
+	/*
+	 * EBADF in case stdin is closed by the caller
+	 */
+	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS
+	    && errno != EBADF)
+		err(EXIT_FAILURE, "unable to limit rights for stdin");
+	cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL);
+	if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit rights for stdout");
+	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit rights for stderr");
+	rootfd = open("/", O_DIRECTORY | O_RDONLY);
+	cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_FSTAT, CAP_FCNTL);
+	if (cap_rights_limit(rootfd, &rights) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit rights");
+
+	cmd = TIOCGETA;
+	if (cap_ioctls_limit(STDOUT_FILENO, &cmd, 1) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit ioctls for stdout");
+	if (cap_ioctls_limit(STDERR_FILENO, &cmd, 1) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit ioctls for stderr");
+	if (cap_ioctls_limit(STDIN_FILENO, &cmd, 1) < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to limit ioctls for stdin");
+
+	if (cap_enter() < 0 && errno != ENOSYS)
+		err(EXIT_FAILURE, "unable to enter capability mode");
+
 	if (argc == 0)
-		ret = soelim_file(stdin, flags);
+		ret = soelim_file(rootfd, stdin, flags);
 
 	for (i = 0; i < argc; i++)
-		ret = soelim_file(soelim_fopen(argv[i]), flags);
+		ret = soelim_file(rootfd, soelim_fopen(rootfd, argv[i]), flags);
 
 	sl_free(includes, 0);
+	close(rootfd);
 
 	return (ret);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609181625.u8IGPfLd097287>