From e4f6bfd6fec87e8eb77f1a9fe34b8b7884ef9748 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Jul 2017 03:04:20 +0200 Subject: [PATCH] zcip: fix slow environment leak Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 +++ networking/ifplugd.c | 6 ++---- networking/zcip.c | 9 +++++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 0317c7d6a..6abf88218 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1485,6 +1485,9 @@ extern void selinux_or_die(void) FAST_FUNC; * HOME=pw->pw_dir * SHELL=shell * else does nothing + * + * NB: CHANGEENV and CLEARENV use setenv() - this leaks memory! + * If setup_environment() is used is vforked child, this leaks memory _in parent too_! */ #define SETUP_ENV_CHANGEENV (1 << 0) #define SETUP_ENV_CLEARENV (1 << 1) diff --git a/networking/ifplugd.c b/networking/ifplugd.c index c36bc9524..9bc1a075f 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -342,10 +342,8 @@ static int run_script(const char *action) /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ r = spawn_and_wait(argv); - unsetenv(IFPLUGD_ENV_PREVIOUS); - unsetenv(IFPLUGD_ENV_CURRENT); - free(env_PREVIOUS); - free(env_CURRENT); + bb_unsetenv_and_free(env_PREVIOUS); + bb_unsetenv_and_free(env_CURRENT); bb_error_msg("exit code: %d", r & 0xff); return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; diff --git a/networking/zcip.c b/networking/zcip.c index 232165efa..94174a165 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -183,6 +183,7 @@ static int run(char *argv[3], const char *param, uint32_t nip) int status; const char *addr = addr; /* for gcc */ const char *fmt = "%s %s %s" + 3; + char *env_ip = env_ip; argv[2] = (char*)param; @@ -190,12 +191,16 @@ static int run(char *argv[3], const char *param, uint32_t nip) if (nip != 0) { addr = nip_to_a(nip); - xsetenv("ip", addr); + /* Must not use setenv() repeatedly, it leaks memory. Use putenv() */ + env_ip = xasprintf("ip=%s", addr); + putenv(env_ip); fmt -= 3; } bb_error_msg(fmt, argv[2], argv[0], addr); - status = spawn_and_wait(argv + 1); + if (nip != 0) + bb_unsetenv_and_free(env_ip); + if (status < 0) { bb_perror_msg("%s %s %s" + 3, argv[2], argv[0]); return -errno;