diff options
author | Mark Hatle <mark.hatle@windriver.com> | 2010-08-09 15:19:41 -0500 |
---|---|---|
committer | Peter Seebach <seebs@laptop-seebs-net.local> | 2010-08-11 14:37:59 -0500 |
commit | a3075407e06a000a931874af57c33341b6a13da9 (patch) | |
tree | 14c7e28fde0dafa022396b90645f44a1f37bb306 | |
parent | 34dce532d23326be07dd9824159f341223814ba2 (diff) | |
download | pseudo-a3075407e06a000a931874af57c33341b6a13da9.tar.gz pseudo-a3075407e06a000a931874af57c33341b6a13da9.tar.bz2 pseudo-a3075407e06a000a931874af57c33341b6a13da9.zip |
Enable execl, execle, execlp, execv, and execvp wrappers
We wrap all of the execs so that we can ensure the environment is
properly configured prior to the exec running.
handle ... for the new execl* wrappers
Add a test for the new execl* ... handling.
-rw-r--r-- | ChangeLog.txt | 4 | ||||
-rw-r--r-- | guts/execl.c | 30 | ||||
-rw-r--r-- | guts/execle.c | 32 | ||||
-rw-r--r-- | guts/execlp.c | 30 | ||||
-rw-r--r-- | guts/execv.c | 15 | ||||
-rw-r--r-- | guts/execvp.c | 15 | ||||
-rwxr-xr-x | makewrappers | 47 | ||||
-rwxr-xr-x | run_tests.sh | 2 | ||||
-rwxr-xr-x | test/test-execl.sh | 21 | ||||
-rw-r--r-- | wrapfuncs.in | 5 |
10 files changed, 194 insertions, 7 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 1acac41..044afcb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +2010-08-10: + * (mhatle) add execl, execle, execlp, execv, and execvp wrappers + * (seebs) handle ... for execl, etc. + 2010-08-06: * (mhatle) Fix an exec program with an empty environment diff --git a/guts/execl.c b/guts/execl.c new file mode 100644 index 0000000..92a4cdc --- /dev/null +++ b/guts/execl.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execl(const char *path, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + + rc = wrap_execv (path, (char *const *) argv); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execle.c b/guts/execle.c new file mode 100644 index 0000000..f4c2ea7 --- /dev/null +++ b/guts/execle.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execle(const char *path, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + char *const *envp; + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + envp = va_arg (ap, char *const *); + + rc = wrap_execve (path, (char *const *) argv, envp); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execlp.c b/guts/execlp.c new file mode 100644 index 0000000..8fd2cdf --- /dev/null +++ b/guts/execlp.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execlp(const char *file, const char *arg, va_list ap) { + * int rc = -1; + */ + + size_t i = 0; + size_t alloc_size = 256; + const char **argv = malloc(sizeof (const char *) * alloc_size); + + argv[i++] = arg; + + while (argv[i-1]) { + argv[i++] = va_arg (ap, const char *); + if ( i > alloc_size - 1 ) { + alloc_size = alloc_size + 256; + argv = realloc(argv, sizeof (const char *) * alloc_size); + } + } + + rc = wrap_execvp (file, (char *const *) argv); + + free (argv); + +/* return rc; + * } + */ diff --git a/guts/execv.c b/guts/execv.c new file mode 100644 index 0000000..3fec52a --- /dev/null +++ b/guts/execv.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * static int + * wrap_execv(const char *path, char *const *argv) { + * int rc = -1; + */ + environ = pseudo_setupenv(environ, getenv("PSEUDO_OPTS")); + + rc = real_execv(path, argv); + +/* return rc; + * } + */ diff --git a/guts/execvp.c b/guts/execvp.c new file mode 100644 index 0000000..64e4b4b --- /dev/null +++ b/guts/execvp.c @@ -0,0 +1,15 @@ +/* + * 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; + */ + environ = pseudo_setupenv(environ, getenv("PSEUDO_OPTS")); + + rc = real_execvp(file, argv); + +/* return rc; + * } + */ diff --git a/makewrappers b/makewrappers index c094a55..60e8938 100755 --- a/makewrappers +++ b/makewrappers @@ -97,7 +97,11 @@ do IFS=$save_IFS args='' dummy_args='' + wrap_args='' + va_list_abort_on_real='' optional_arg=false + make_va_list=false + maybe_va_end='' prepend='' depth=0 for arg @@ -138,9 +142,24 @@ do arg=${arg% } prepend='' case $arg in + ...) + make_va_list=true + maybe_va_end='va_end(ap);' + va_list_abort_on_real='assert(!"cannot chain to real versions of variadic functions");' + args="$args${args+, }..." + dummy_args="$dummy_args${dummy_args:+, }..." + wrap_args="$wrap_args${wrap_args:+, }va_list ap" + arg="..." + argname="ap" + argnames="$argnames${argnames:+, }ap" + wrapargnames="$wrapargnames${wrapargnames:+, }ap" + # used for creating a va_list + optional_prev=$prev_argname + ;; ...*) optional_arg=true args="$args${args:+, }..." + wrap_args="$wrap_args${wrap_args:+, }..." dummy_args="$dummy_args${dummy_args:+, }..." arg=`expr "$arg" : '\.\.\.{\(.*\)}'` argname=`expr "$arg" : '.*[^a-zA-Z0-9_]\([a-zA-Z0-9_]*\)$'` @@ -156,6 +175,7 @@ do *\(*) # function pointer argname=`expr "$arg" : '[^(]*(\*\([a-zA-Z0-9_]*\).*'` args="$args${args:+, }$arg" + wrap_args="$wrap_args${wrap_args:+, }$arg" dummy_args="$dummy_args${dummy_args:+, }$arg __attribute__((unused))" wrapargnames="$wrapargnames${wrapargnames:+, }$argname" argnames="$argnames${argnames:+, }$argname" @@ -164,6 +184,7 @@ do *) argname=`expr "$arg" : '.*[^a-zA-Z0-9_](*\([a-zA-Z0-9_]*\))*(*)*$'` args="$args${args:+, }$arg" + wrap_args="$wrap_args${wrap_args:+, }$arg" dummy_args="$dummy_args${dummy_args:+, }$arg __attribute__((unused))" # special handling for canonicalization # set this before changing path -> rpath, for guts files @@ -268,9 +289,16 @@ $type $name($args) { EOF fi + if $make_va_list; then + cat >&5 <<EOF + va_list ap; + va_start(ap, $optional_prev); +EOF + fi # and now the body of the wrapper: cat >&5 <<EOF sigset_t blocked, saved; + $(write_decl "$type" "rc" "$default_value") pseudo_debug(4, "called: $name\n"); /* these are signals for which the handlers often @@ -292,10 +320,14 @@ EOF } $decl_paths if (pseudo_populate_wrappers()) { - $(write_decl "$type" "rc" "$default_value") int save_errno; if (antimagic > 0) { if (real_$name) { + /* if this function takes ..., there is + * no way to pass the real argument list + * to it... + */ + $va_list_abort_on_real $(write_assign rc) (*real_$name)($argnames); } else { $(write_assign rc) dummy_$name($argnames); @@ -305,6 +337,7 @@ $alloc_paths $(write_assign rc) wrap_$name($argnames); $free_paths } + $maybe_va_end save_errno = errno; pseudo_droplock(); sigprocmask(SIG_SETMASK, &saved, NULL); @@ -315,7 +348,9 @@ $free_paths pseudo_droplock(); sigprocmask(SIG_SETMASK, &saved, NULL); pseudo_debug(4, "completed: $name\n"); - $(write_return "dummy_$name($argnames)"); + $(write_assign rc) dummy_$name($argnames); + $maybe_va_end + $(write_return rc); } } @@ -332,7 +367,7 @@ EOF if $optional_arg; then cat >&5 << EOF static $type -wrap_$name($args) { +wrap_$name($wrap_args) { $(write_decl "$type" "rc" "$default_value") $optional_decl; @@ -349,7 +384,7 @@ EOF else cat >&5 << EOF static $type -wrap_$name($args) { +wrap_$name($wrap_args) { $(write_decl "$type" "rc" "$default_value") #include "$guts" @@ -385,7 +420,7 @@ EOF * guts/COPYRIGHT for information. * * static $type - * wrap_$name($args) { + * wrap_$name($wrap_args) { * $(write_decl "$type" "rc" "$default_value") */ @@ -401,7 +436,7 @@ EOF cat >&6 <<EOF /* $type $name($args); */ static $type dummy_$name($args); -static $type wrap_$name($args); +static $type wrap_$name($wrap_args); static $type (*real_$name)($args); EOF diff --git a/run_tests.sh b/run_tests.sh index 9228668..0eced9f 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -42,7 +42,7 @@ do else echo "${filename/%.sh}: Failed." fi - rm -rf var + rm -rf var/pseudo/* done echo "${num_passed_tests}/${num_tests} test(s) passed." diff --git a/test/test-execl.sh b/test/test-execl.sh new file mode 100755 index 0000000..1a1c580 --- /dev/null +++ b/test/test-execl.sh @@ -0,0 +1,21 @@ +#!/bin/bash +cat > execl_test.c << EOF +#include <unistd.h> +int main() { + return execl("/usr/bin/env", "/usr/bin/env", "A=A", "B=B", "C=C", NULL); +} +EOF + +gcc -o execl_test execl_test.c + +./execl_test | grep -q "C=C" + +if [ "$?" = "0" ] +then + #echo "Passed." + rm -f execl_test execl_test.c + exit 0 +fi +#echo "Failed" +rm -f execl_test execl_test.c +exit 1 diff --git a/wrapfuncs.in b/wrapfuncs.in index 95bb8b9..40c86eb 100644 --- a/wrapfuncs.in +++ b/wrapfuncs.in @@ -88,7 +88,12 @@ char *tmpnam(char *s); int truncate(const char *path, off_t length); int utime(const char *path, const struct utimbuf *buf); int utimes(const char *path, const struct timeval *times); +int execl(const char *path, const char *arg, ...); +int execlp(const char *file, const char *arg, ...); +int execle(const char *path, const char *arg, ...); +int execv(const char *path, char *const *argv); int execve(const char *filename, char *const *argv, char *const *envp); +int execvp(const char *file, char *const *argv); # for emulation of passwd utilities struct passwd *getpwnam(const char *name); struct passwd *getpwuid(uid_t uid); |