@@ -8,6 +8,8 @@
* wrap_execv(const char *file, char *const *argv) {
* int rc = -1;
*/
+ char **new_environ, **orig_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
@@ -19,17 +21,24 @@
pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
}
- pseudo_setupenv();
- if (pseudo_has_unload(NULL)) {
- /* and here we attach */
- pseudo_dropenv();
- }
+ /* Due to bash intercepting setenv/getenv/unsetenv and changing environ
+ internally itself at will, we create our own environ copy at process
+ creation based on it to ensure it is correct */
+ orig_environ = environ;
+ new_environ = pseudo_setupenvp(environ);
+ if (pseudo_has_unload(new_environ))
+ new_environ = pseudo_dropenvp(new_environ);
+ environ = 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_execv(file, argv);
+ environ = orig_environ;
+ free(new_environ);
+
/* return rc;
* }
*/
@@ -8,6 +8,7 @@
* wrap_execvp(const char *file, char *const *argv) {
* int rc = -1;
*/
+ char **new_environ, **orig_environ;
/* note: we don't canonicalize this, because we are intentionally
* NOT redirecting execs into the chroot environment. If you try
@@ -20,9 +21,14 @@
pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
}
- pseudo_setupenv();
- if (pseudo_has_unload(NULL))
- pseudo_dropenv();
+ /* Due to bash intercepting setenv/getenv/unsetenv and changing environ
+ internally itself at will, we create our own environ copy at process
+ creation based on it to ensure it is correct */
+ orig_environ = environ;
+ new_environ = pseudo_setupenvp(environ);
+ if (pseudo_has_unload(new_environ))
+ new_environ = pseudo_dropenvp(new_environ);
+ environ = new_environ;
/* if exec() fails, we may end up taking signals unexpectedly...
* not much we can do about that.
@@ -30,6 +36,9 @@
sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL);
rc = real_execvp(file, argv);
+ environ = orig_environ;
+ free(new_environ);
+
/* return rc;
* }
*/
@@ -7,15 +7,25 @@
* FILE *popen(const char *command, const char *mode)
* FILE *rc = NULL;
*/
+ char **new_environ, **orig_environ;
+
/* on at least some systems, popen() calls fork and exec
* in ways that avoid our usual enforcement of the environment.
*/
- pseudo_setupenv();
- if (pseudo_has_unload(NULL))
- pseudo_dropenv();
+ /* Due to bash intercepting setenv/getenv/unsetenv and changing environ
+ internally itself at will, we create our own environ copy at process
+ creation based on it to ensure it is correct */
+ orig_environ = environ;
+ new_environ = pseudo_setupenvp(environ);
+ if (pseudo_has_unload(new_environ))
+ new_environ = pseudo_dropenvp(new_environ);
+ environ = new_environ;
rc = real_popen(command, mode);
+ environ = orig_environ;
+ free(new_environ);
+
/* return rc;
* }
*/
@@ -7,15 +7,25 @@
* int system(const char *command)
* int rc = -1;
*/
+ char **new_environ, **orig_environ;
+
if (!command)
return 1;
- pseudo_setupenv();
- if (pseudo_has_unload(NULL))
- pseudo_dropenv();
+ /* Due to bash intercepting setenv/getenv/unsetenv and changing environ
+ internally itself at will, we create our own environ copy at process
+ creation based on it to ensure it is correct */
+ orig_environ = environ;
+ new_environ = pseudo_setupenvp(environ);
+ if (pseudo_has_unload(new_environ))
+ new_environ = pseudo_dropenvp(new_environ);
+ environ = new_environ;
rc = real_system(command);
+ environ = orig_environ;
+ free(new_environ);
+
/* return rc;
* }
*/
@@ -52,9 +52,6 @@ extern FILE *pseudo_grp;
/* pseudo_wrappers will try to initialize these */
extern int (*pseudo_real_lstat)(const char *path, PSEUDO_STATBUF *buf);
-extern int (*pseudo_real_unsetenv)(const char *);
-extern char * (*pseudo_real_getenv)(const char *);
-extern int (*pseudo_real_setenv)(const char *, const char *, int);
extern int (*pseudo_real_fork)(void);
extern int (*pseudo_real_execv)(const char *, char * const *);
@@ -73,15 +73,9 @@ typedef struct {
char *data;
} pseudo_evlog_entry;
-/* so bash overrides getenv/unsetenv/etcetera, preventing them from
- * actually modifying environ, so we have pseudo_wrappers try to dlsym
- * the right values. This could fail, in which case we'd get null
- * pointers, and we'll just call whatever the linker gives us and
- * hope for the best.
- */
-#define SETENV(x, y, z) (pseudo_real_setenv ? pseudo_real_setenv : setenv)(x, y, z)
-#define GETENV(x) (pseudo_real_getenv ? pseudo_real_getenv : getenv)(x)
-#define UNSETENV(x) (pseudo_real_unsetenv ? pseudo_real_unsetenv : unsetenv)(x)
+#define SETENV(x, y, z) setenv(x, y, z)
+#define GETENV(x) getenv(x)
+#define UNSETENV(x) unsetenv(x)
#define PSEUDO_EVLOG_ENTRIES 250
#define PSEUDO_EVLOG_LENGTH 256
@@ -173,12 +173,6 @@ pseudo_init_wrappers(void) {
pseudo_real_fsetxattr = real_fsetxattr;
#endif
pseudo_real_lstat = base_lstat;
- /* bash has its own local copies of these which it uses
- * instead of ours...
- */
- pseudo_real_unsetenv = dlsym(RTLD_NEXT, "unsetenv");
- pseudo_real_getenv = dlsym(RTLD_NEXT, "getenv");
- pseudo_real_setenv = dlsym(RTLD_NEXT, "setenv");
/* and these are used so the client's server spawn can bypass
* wrappers.
*/