From owner-p4-projects@FreeBSD.ORG Mon Jun 8 08:58:54 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8D2AE1065674; Mon, 8 Jun 2009 08:58:54 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4D7841065672 for ; Mon, 8 Jun 2009 08:58:54 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 399138FC13 for ; Mon, 8 Jun 2009 08:58:54 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n588wsJB002571 for ; Mon, 8 Jun 2009 08:58:54 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n588wst2002569 for perforce@freebsd.org; Mon, 8 Jun 2009 08:58:54 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Mon, 8 Jun 2009 08:58:54 GMT Message-Id: <200906080858.n588wst2002569@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Cc: Subject: PERFORCE change 163769 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Jun 2009 08:58:55 -0000 http://perforce.freebsd.org/chv.cgi?CH=163769 Change 163769 by rwatson@rwatson_freebsd_capabilities on 2009/06/08 08:58:00 Clean up cap_exec by adding various utility functions, etc. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/tools/cap/cap_exec/cap_exec.c#5 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/tools/cap/cap_exec/cap_exec.c#5 (text+ko) ==== @@ -65,16 +65,39 @@ #define BIN_CAPS (CAP_SEEK | CAP_FSTAT | CAP_FSTATFS | CAP_READ | \ CAP_FEXECVE | CAP_MMAP | CAP_MAPEXEC) +static void +cap_limitfd(int fd, cap_rights_t rights) +{ + int fd_new; + + fd_new = cap_new(fd, rights); + if (fd_new < 0) + err(-1, "cap_new"); + if (fd_new != fd) { + if (dup2(fd_new, fd) < 0) + err(-1, "dup2"); + close(fd_new); + } +} + +static int +cap_open_limit(const char *path, int flags, cap_rights_t rights) +{ + int fd; + + fd = open(path, flags); + if (fd < 0) + err(-1, "open: %s", path); + cap_limitfd(fd, rights); + return (fd); +} + int main(int argc, char *argv[]) { - int fd_exec, fd_libc, fd_new; - int fd_stdin, fd_stdout, fd_stderr, fd_procdesc; + int fd_exec, fd_ldso, fd_libc, fd_procdesc; char *env_caplibindex; struct pollfd pollfd; -#ifdef LDSO_MODE - int fd_ldso; -#endif pid_t pid; if (argc < 2) @@ -85,104 +108,44 @@ err(-1, "pdfork"); if (pid == 0) { /* - * Open files by name before entering capability mode. Flag - * for close when fexecve(2) runs. - */ - fd_exec = open(argv[1], O_RDONLY); - if (fd_exec < 0) - err(-1, "open: %s", argv[1]); -#ifdef LDSO_MODE - if (fd_exec != 3) - errx(-1, "fd_exec not fd 3"); - fd_ldso = open(LD_ELF_CAP_SO, O_RDONLY); - if (fd_ldso < 0) - err(-1, "open: %s", LD_ELF_CAP_SO); - fd_new = cap_new(fd_ldso, BIN_CAPS); - if (fd_new < 0) - err(-1, "cap_new"); - if (dup2(fd_new, fd_ldso) < 0) - err(-1, "dup2"); - close(fd_new); - if (fcntl(fd_ldso, F_SETFD, FD_CLOEXEC) < 0) - err(-1, "fcntl FD_CLOEXEC"); - - fd_libc = open(LIBPATH LIBC_SO, O_RDONLY); - if (fd_libc < 0) - err(-1, "open: %s", LIBPATH LIBC_SO); - fd_new = cap_new(fd_libc, BIN_CAPS); - if (fd_new < 0) - err(-1, "cap_new"); - if (dup2(fd_new, fd_libc) < 0) - err(-1, "dup2"); - close(fd_new); -#else - if (fcntl(fd_exec, F_SETFD, FD_CLOEXEC) < 0) - err(-1, "fcntl FD_CLOEXEC"); -#endif - - /* - * Global namespaces no longer required, enter capability - * mode. - */ - if (cap_enter() < 0) - err(-1, "cap_enter"); - - /* * Set up stdin, stdout, and stderr by wrapping the existing * file descriptors in constrained capabilities. */ - fd_stdin = cap_new(STDIN_FILENO, STDIN_CAPS); - if (fd_stdin < 0) - err(-1, "cap_new"); - if (dup2(fd_stdin, STDIN_FILENO) < 0) - err(-1, "dup2"); - close(fd_stdin); - - fd_stdout = cap_new(STDOUT_FILENO, STDOUT_CAPS); - if (fd_stdout < 0) - err(-1, "cap_new"); - if (dup2(fd_stdout, STDOUT_FILENO) < 0) - err(-1, "dup2"); - close(fd_stdout); - - fd_stderr = cap_new(STDERR_FILENO, STDERR_CAPS); - if (fd_stderr < 0) - err(-1, "cap_new"); - if (dup2(fd_stderr, STDERR_FILENO) < 0) - err(-1, "dup2"); - close(fd_stderr); + cap_limitfd(STDIN_FILENO, STDIN_CAPS); + cap_limitfd(STDOUT_FILENO, STDOUT_CAPS); + cap_limitfd(STDERR_FILENO, STDERR_CAPS); /* - * Set up environmental variable so that the runtime linker - * can access libc in a sandbox. + * Open and configure the binary, ELF interpreter, and libc. + * The rtld-elf-cap runtime requires the binary to be passed + * as fd 3, so verify that's what we got. */ -#ifdef LDSO_MODE + fd_exec = cap_open_limit(argv[1], O_RDONLY, BIN_CAPS); + if (fd_exec != 3) + err(-1, "cap_open_limit(%s) returned fd %d", argv[1], + fd_exec); + fd_ldso = cap_open_limit(LD_ELF_CAP_SO, O_RDONLY, BIN_CAPS); + if (fcntl(fd_ldso, F_SETFD, FD_CLOEXEC) < 0) + err(-1, "fcntl FD_CLOEXEC"); + fd_libc = cap_open_limit(LIBPATH LIBC_SO, O_RDONLY, BIN_CAPS); if (asprintf(&env_caplibindex, "%d:%s", fd_libc, LIBC_SO) == -1) err(-1, "asprintf"); - printf("caplibindex: %s\n", env_caplibindex); setenv("LD_CAPLIBINDEX", env_caplibindex, 1); -#endif /* - * Perhaps a closeall() or something to clear any remaining - * file descriptors here? + * Global namespaces no longer required, enter capability + * mode. */ + if (cap_enter() < 0) + err(-1, "cap_enter"); /* * Scrub the remainder of process state by calling fexecve(2) * the desired binary. */ -#ifdef LDSO_MODE if (fexecve(fd_ldso, argv + 1, environ) < 0) -#if 0 - if (fexecve(fd_ldso, ldso_argv, environ) < 0) -#endif err(-1, "%s", LD_ELF_CAP_SO); -#else - if (fexecve(fd_exec, argv + 1, environ) < 0) - err(-1, "%s", argv[1]); -#endif /* NOTREACHED */ }