Date: Mon, 8 Jun 2009 08:58:54 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 163769 for review Message-ID: <200906080858.n588wst2002569@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */ }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906080858.n588wst2002569>