From owner-svn-src-head@freebsd.org Sun Sep 18 16:25:42 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id C19CCBDF1F8; Sun, 18 Sep 2016 16:25:42 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9F7E8868; Sun, 18 Sep 2016 16:25:42 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8IGPfkU097288; Sun, 18 Sep 2016 16:25:41 GMT (envelope-from bapt@FreeBSD.org) Received: (from bapt@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8IGPfLd097287; Sun, 18 Sep 2016 16:25:41 GMT (envelope-from bapt@FreeBSD.org) Message-Id: <201609181625.u8IGPfLd097287@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bapt set sender to bapt@FreeBSD.org using -f From: Baptiste Daroussin Date: Sun, 18 Sep 2016 16:25:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r305936 - head/usr.bin/soelim X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2016 16:25:42 -0000 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 __FBSDID("$FreeBSD$"); +#include #include #include #include +#include +#include #include #include #include #include #include +#include #include #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); }