diff options
Diffstat (limited to 'ports/common')
-rw-r--r-- | ports/common/guts/execl.c | 13 | ||||
-rw-r--r-- | ports/common/guts/execle.c | 13 | ||||
-rw-r--r-- | ports/common/guts/execlp.c | 13 | ||||
-rw-r--r-- | ports/common/guts/execv.c | 36 | ||||
-rw-r--r-- | ports/common/guts/execve.c | 37 | ||||
-rw-r--r-- | ports/common/guts/execvp.c | 37 | ||||
-rw-r--r-- | ports/common/guts/fork.c | 24 | ||||
-rw-r--r-- | ports/common/pseudo_wrappers.c | 376 | ||||
-rw-r--r-- | ports/common/subports | 8 | ||||
-rw-r--r-- | ports/common/wrapfuncs.in | 7 |
10 files changed, 564 insertions, 0 deletions
diff --git a/ports/common/guts/execl.c b/ports/common/guts/execl.c new file mode 100644 index 0000000..ce908ed --- /dev/null +++ b/ports/common/guts/execl.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * int execl(const char *file, const char *arg, va_list ap) + * int rc = -1; + */ + + rc = real_execl(file, arg, ap); + +/* return rc; + * } + */ diff --git a/ports/common/guts/execle.c b/ports/common/guts/execle.c new file mode 100644 index 0000000..68d8bba --- /dev/null +++ b/ports/common/guts/execle.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * int execle(const char *file, const char *arg, va_list ap) + * int rc = -1; + */ + + rc = real_execle(file, arg, ap); + +/* return rc; + * } + */ diff --git a/ports/common/guts/execlp.c b/ports/common/guts/execlp.c new file mode 100644 index 0000000..d357986 --- /dev/null +++ b/ports/common/guts/execlp.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * int execlp(const char *file, const char *arg, va_list ap) + * int rc = -1; + */ + + rc = real_execlp(file, arg, ap); + +/* return rc; + * } + */ diff --git a/ports/common/guts/execv.c b/ports/common/guts/execv.c new file mode 100644 index 0000000..15ad51e --- /dev/null +++ b/ports/common/guts/execv.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execv(const char *file, char *const *argv) { + * int rc = -1; + */ + /* note: we don't canonicalize this, because we are intentionally + * NOT redirecting execs into the chroot environment. If you try + * to execute /bin/sh, you get the actual /bin/sh, not + * <CHROOT>/bin/sh. This allows use of basic utilities. This + * design will likely be revisited. + */ + if (antimagic == 0) { + char *path_guess = pseudo_exec_path(file, 0); + pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0); + free(path_guess); + } + + if (!pseudo_get_value("PSEUDO_RELOADED")) + pseudo_setupenv(); + else { + pseudo_setupenv(); + pseudo_dropenv(); + } + + /* if exec() fails, we may end up taking signals unexpectedly... + * not much we can do about that. + */ + sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL); + rc = real_execv(file, argv); + +/* return rc; + * } + */ diff --git a/ports/common/guts/execve.c b/ports/common/guts/execve.c new file mode 100644 index 0000000..a47b9a7 --- /dev/null +++ b/ports/common/guts/execve.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execve(const char *file, char *const *argv, char *const *envp) { + * int rc = -1; + */ + char * const *new_environ; + /* note: we don't canonicalize this, because we are intentionally + * NOT redirecting execs into the chroot environment. If you try + * to execute /bin/sh, you get the actual /bin/sh, not + * <CHROOT>/bin/sh. This allows use of basic utilities. This + * design will likely be revisited. + */ + if (antimagic == 0) { + char *path_guess = pseudo_exec_path(file, 0); + pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0); + free(path_guess); + } + + if (!pseudo_get_value("PSEUDO_RELOADED")) + new_environ = pseudo_setupenvp(envp); + else { + new_environ = pseudo_setupenvp(envp); + new_environ = pseudo_dropenvp(new_environ); + } + + /* if exec() fails, we may end up taking signals unexpectedly... + * not much we can do about that. + */ + sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL); + rc = real_execve(file, argv, new_environ); + +/* return rc; + * } + */ diff --git a/ports/common/guts/execvp.c b/ports/common/guts/execvp.c new file mode 100644 index 0000000..419f41b --- /dev/null +++ b/ports/common/guts/execvp.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execvp(const char *file, char *const *argv) { + * int rc = -1; + */ + + /* note: we don't canonicalize this, because we are intentionally + * NOT redirecting execs into the chroot environment. If you try + * to execute /bin/sh, you get the actual /bin/sh, not + * <CHROOT>/bin/sh. This allows use of basic utilities. This + * design will likely be revisited. + */ + if (antimagic == 0) { + char *path_guess = pseudo_exec_path(file, 1); + pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0); + free(path_guess); + } + + if (!pseudo_get_value("PSEUDO_RELOADED")) + pseudo_setupenv(); + else { + pseudo_setupenv(); + pseudo_dropenv(); + } + + /* if exec() fails, we may end up taking signals unexpectedly... + * not much we can do about that. + */ + sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL); + rc = real_execvp(file, argv); + +/* return rc; + * } + */ diff --git a/ports/common/guts/fork.c b/ports/common/guts/fork.c new file mode 100644 index 0000000..76cac6f --- /dev/null +++ b/ports/common/guts/fork.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_fork(void) { + * int rc = -1; + */ + rc = real_fork(); + /* special case: we may want to enable or disable + * pseudo in the child process + */ + if (rc == 0) { + if (!pseudo_get_value("PSEUDO_RELOADED")) { + pseudo_setupenv(); + pseudo_reinit_libpseudo(); + } else { + pseudo_setupenv(); + pseudo_dropenv(); + } + } +/* return rc; + * } + */ diff --git a/ports/common/pseudo_wrappers.c b/ports/common/pseudo_wrappers.c new file mode 100644 index 0000000..2cfc400 --- /dev/null +++ b/ports/common/pseudo_wrappers.c @@ -0,0 +1,376 @@ +/* these aren't used, but the wrapper table isn't happy unless they + * exist + */ +static int +wrap_execl(const char *file, const char *arg, va_list ap) { + (void) file; + (void) arg; + (void) ap; + return 0; +} + +static int +wrap_execle(const char *file, const char *arg, va_list ap) { + (void) file; + (void) arg; + (void) ap; + return 0; +} + +static int +wrap_execlp(const char *file, const char *arg, va_list ap) { + (void) file; + (void) arg; + (void) ap; + return 0; +} + +static char ** +execl_to_v(va_list ap, const char *argv0, char *const **envp) { + size_t i = 0; + size_t alloc_size = 256; + + char **argv = malloc((sizeof *argv) * alloc_size); + + if (!argv) { + pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n", + (unsigned long) alloc_size); + return NULL; + } + argv[i++] = (char *) argv0; + + while (argv[i-1]) { + argv[i++] = va_arg(ap, char *const); + if (i > alloc_size - 1) { + alloc_size = alloc_size + 256; + argv = realloc(argv, (sizeof *argv) * alloc_size); + if (!argv) { + pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n", + (unsigned long) alloc_size); + return NULL; + } + } + } + if (envp) { + *envp = va_arg(ap, char **); + } + return argv; +} + +/* The following wrappers require Special Handling */ + +int +execl(const char *file, const char *arg, ...) { + sigset_t saved; + va_list ap; + char **argv; + + int rc = -1; + + if (!pseudo_check_wrappers()) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execl"); + return rc; + } + + va_start(ap, arg); + argv = execl_to_v(ap, arg, 0); + va_end(ap); + if (!argv) { + errno = ENOMEM; + return -1; + } + + pseudo_debug(4, "called: execl\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execv(file, argv); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execl\n"); + errno = save_errno; + free(argv); + return rc; +} + +int +execlp(const char *file, const char *arg, ...) { + sigset_t saved; + va_list ap; + char **argv; + + int rc = -1; + + if (!pseudo_check_wrappers()) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execlp"); + return rc; + } + + va_start(ap, arg); + argv = execl_to_v(ap, arg, 0); + va_end(ap); + if (!argv) { + errno = ENOMEM; + return -1; + } + + pseudo_debug(4, "called: execlp\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execvp(file, argv); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execlp\n"); + errno = save_errno; + free(argv); + return rc; +} + +int +execle(const char *file, const char *arg, ...) { + sigset_t saved; + va_list ap; + char **argv; + char **envp; + + int rc = -1; + + if (!pseudo_check_wrappers()) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execle"); + return rc; + } + + va_start(ap, arg); + argv = execl_to_v(ap, arg, (char *const **)&envp); + va_end(ap); + if (!argv) { + errno = ENOMEM; + return -1; + } + + pseudo_debug(4, "called: execle\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execve(file, argv, envp); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execle\n"); + errno = save_errno; + free(argv); + return rc; +} + +int +execv(const char *file, char *const *argv) { + sigset_t saved; + + int rc = -1; + + if (!pseudo_check_wrappers() || !real_execv) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execv"); + return rc; + } + + pseudo_debug(4, "called: execv\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execv(file, argv); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execv\n"); + errno = save_errno; + return rc; +} + +int +execve(const char *file, char *const *argv, char *const *envp) { + sigset_t saved; + + int rc = -1; + + if (!pseudo_check_wrappers() || !real_execve) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execve"); + return rc; + } + + pseudo_debug(4, "called: execve\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execve(file, argv, envp); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execve\n"); + errno = save_errno; + return rc; +} + +int +execvp(const char *file, char *const *argv) { + sigset_t saved; + + int rc = -1; + + if (!pseudo_check_wrappers() || !real_execvp) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("execvp"); + return rc; + } + + pseudo_debug(4, "called: execvp\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + /* exec*() use this to restore the sig mask */ + pseudo_saved_sigmask = saved; + rc = wrap_execvp(file, argv); + + save_errno = errno; + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: execvp\n"); + errno = save_errno; + return rc; +} + +int +fork(void) { + sigset_t saved; + + int rc = -1; + + if (!pseudo_check_wrappers() || !real_fork) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("fork"); + return rc; + } + + pseudo_debug(4, "called: fork\n"); + pseudo_sigblock(&saved); + if (pseudo_getlock()) { + errno = EBUSY; + sigprocmask(SIG_SETMASK, &saved, NULL); + return -1; + } + + int save_errno; + + rc = wrap_fork(); + + save_errno = errno; + + pseudo_droplock(); + sigprocmask(SIG_SETMASK, &saved, NULL); + pseudo_debug(4, "completed: fork\n"); + errno = save_errno; + return rc; +} + +int +vfork(void) { + /* we don't provide support for the distinct semantics + * of vfork() + */ + return fork(); +} + +static int +wrap_execv(const char *file, char *const *argv) { + int rc = -1; + +#include "guts/execv.c" + + return rc; +} + +static int +wrap_execve(const char *file, char *const *argv, char *const *envp) { + int rc = -1; + +#include "guts/execve.c" + + return rc; +} + +static int +wrap_execvp(const char *file, char *const *argv) { + int rc = -1; + +#include "guts/execvp.c" + + return rc; +} + +static int +wrap_fork(void) { + int rc = -1; + +#include "guts/fork.c" + + return rc; +} + diff --git a/ports/common/subports b/ports/common/subports new file mode 100644 index 0000000..e2aac56 --- /dev/null +++ b/ports/common/subports @@ -0,0 +1,8 @@ +#!/bin/sh +case $(uname -s) in +Linux) echo "linux";; +Darwin) echo "darwin";; +*) echo >&2 "Unknown result from uname -s: %(uname -s). Aborting." + exit 1 + ;; +esac diff --git a/ports/common/wrapfuncs.in b/ports/common/wrapfuncs.in new file mode 100644 index 0000000..17440f9 --- /dev/null +++ b/ports/common/wrapfuncs.in @@ -0,0 +1,7 @@ +int execlp(const char *file, const char *arg, ...); /* hand_wrapped=1 */ +int execl(const char *file, const char *arg, ...); /* hand_wrapped=1 */ +int execle(const char *file, const char *arg, ...); /* hand_wrapped=1 */ +int execv(const char *file, char *const *argv); /* hand_wrapped=1 */ +int execve(const char *file, char *const *argv, char *const *envp); /* hand_wrapped=1 */ +int execvp(const char *file, char *const *argv); /* hand_wrapped=1 */ +int fork(void); /* hand_wrapped=1 */ |