PERFORCE change 163769 for review
Robert Watson
rwatson at FreeBSD.org
Mon Jun 8 08:58:55 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163769
Change 163769 by rwatson at 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 */
}
More information about the p4-projects
mailing list