diff options
-rw-r--r-- | ChangeLog.txt | 4 | ||||
-rw-r--r-- | ports/linux/newclone/guts/clone.c | 27 | ||||
-rw-r--r-- | ports/linux/newclone/pseudo_wrappers.c | 33 | ||||
-rw-r--r-- | ports/linux/oldclone/guts/clone.c | 27 | ||||
-rw-r--r-- | ports/linux/oldclone/pseudo_wrappers.c | 36 | ||||
-rw-r--r-- | pseudo.1 | 7 |
6 files changed, 93 insertions, 41 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 2c70277..0421a95 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +2011-10-26: + * (mhatle) update clone wrapper to add an intermediate function + to avoid setting environment variables in the parent. + 2011-10-20: * (mhatle) change from internal PSEUDO_RELOADED to external PSEUDO_UNLOAD environment variable. Enable external programs diff --git a/ports/linux/newclone/guts/clone.c b/ports/linux/newclone/guts/clone.c index 4b65036..ee6fc09 100644 --- a/ports/linux/newclone/guts/clone.c +++ b/ports/linux/newclone/guts/clone.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Wind River Systems; see + * Copyright (c) 2008-2011 Wind River Systems; see * guts/COPYRIGHT for information. * * static int @@ -8,18 +8,23 @@ */ /* because clone() doesn't actually continue in this function, we * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! + * child. Instead, we have to create an intermediate function, + * wrap_clone_child, which does this fix up. */ - pseudo_debug(1, "client resetting for clone(2) call\n"); - pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { - pseudo_reinit_libpseudo(); - } else { - pseudo_dropenv(); - } + + struct clone_args * myargs = malloc(sizeof(struct clone_args)); + + myargs->fn = fn; + myargs->flags = flags; + myargs->arg = arg; + /* call the real syscall */ - rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid); + rc = (*real_clone)(wrap_clone_child, child_stack, flags, myargs, pid, tls, ctid); + + /* If we're not sharing memory, we need to free myargs in the parent */ + if (!(flags & CLONE_VM)) + free(myargs); + /* ... * return rc; * } diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c index dd44408..9dbac42 100644 --- a/ports/linux/newclone/pseudo_wrappers.c +++ b/ports/linux/newclone/pseudo_wrappers.c @@ -10,6 +10,34 @@ ap) { return 0; } +struct clone_args { + int (*fn)(void *); + int flags; + void *arg; +}; + +int wrap_clone_child(void *args) { + struct clone_args *clargs = args; + + int (*fn)(void *) = clargs->fn; + int flags = clargs->flags; + void *arg = clargs->arg; + + /* We always free in the client */ + free(clargs); + + if (!(flags & CLONE_VM)) { + pseudo_setupenv(); + if (!pseudo_get_value("PSEUDO_UNLOAD")) { + pseudo_reinit_libpseudo(); + } else { + pseudo_dropenv(); + } + } + + return fn(arg); +} + int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { sigset_t saved; @@ -42,11 +70,6 @@ clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { int save_errno; int save_disabled = pseudo_disabled; - /* because clone() doesn't actually continue in this function, we - * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! - */ #include "guts/clone.c" diff --git a/ports/linux/oldclone/guts/clone.c b/ports/linux/oldclone/guts/clone.c index e8b87e8..5240bb3 100644 --- a/ports/linux/oldclone/guts/clone.c +++ b/ports/linux/oldclone/guts/clone.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Wind River Systems; see + * Copyright (c) 2008-2011 Wind River Systems; see * guts/COPYRIGHT for information. * * static int @@ -8,18 +8,23 @@ */ /* because clone() doesn't actually continue in this function, we * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! + * child. Instead, we have to create an intermediate function, + * wrap_clone_child, which does this fix up. */ - pseudo_debug(1, "client resetting for clone(2) call\n"); - pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { - pseudo_reinit_libpseudo(); - } else { - pseudo_dropenv(); - } + + struct clone_args * myargs = malloc(sizeof(struct clone_args)); + + myargs->fn = fn; + myargs->flags = flags; + myargs->arg = arg; + /* call the real syscall */ - rc = (*real_clone)(fn, child_stack, flags, arg); + rc = (*real_clone)(wrap_clone_child, child_stack, flags, myargs, pid); + + /* If we're not sharing memory, we need to free myargs in the parent */ + if (!(flags & CLONE_VM)) + free(myargs); + /* ... * return rc; * } diff --git a/ports/linux/oldclone/pseudo_wrappers.c b/ports/linux/oldclone/pseudo_wrappers.c index f0bf112..c0ce5dd 100644 --- a/ports/linux/oldclone/pseudo_wrappers.c +++ b/ports/linux/oldclone/pseudo_wrappers.c @@ -1,13 +1,40 @@ -int +static int wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) { /* unused */ return 0; } +struct clone_args { + int (*fn)(void *); + int flags; + void *arg; +}; + +int wrap_clone_child(void *args) { + struct clone_args *clargs = args; + + int (*fn)(void *) = clargs->fn; + int flags = clargs->flags; + void *arg = clargs->arg; + + /* We always free in the client */ + free(clargs); + + if (!(flags & CLONE_VM)) { + pseudo_setupenv(); + if (!pseudo_get_value("PSEUDO_UNLOAD")) { + pseudo_reinit_libpseudo(); + } else { + pseudo_dropenv(); + } + } + + return fn(arg); +} + int clone(int (*fn)(void *), void *child_stack, int flags, void *arg) { sigset_t saved; - va_list ap; pid_t *pid; struct user_desc *tls; pid_t *ctid; @@ -30,11 +57,6 @@ clone(int (*fn)(void *), void *child_stack, int flags, void *arg) { int save_errno; int save_disabled = pseudo_disabled; - /* because clone() doesn't actually continue in this function, we - * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! - */ #include "guts/clone.c" @@ -576,13 +576,6 @@ than it is otherwise. This is probably because nearly every operation communication with the server, and probably some kind of database activity. -The -.IR clone(2) -wrapper unconditionallity restores the system environment. It also invokes -the checks to see if the user has requested pseudo to be disabled or unloaded. -Due to the semantics of clone, this causes both the parent and child processes -to be disabled or unloaded. - .SH SEE ALSO fakeroot(1), ld.so(8), pseudolog(1), sqlite3(1) .SH FURTHER READING |