aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-03 15:01:06 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-03 15:01:06 +0200
commita769390da604b4815535e296d8a46fdf9094c2c7 (patch)
tree9317c96f494de0a2a8f026272fd541ed245c2ec3
parent04465dad66478aea28100ff5b9094d1c02336f07 (diff)
downloadbusybox-w32-a769390da604b4815535e296d8a46fdf9094c2c7.tar.gz
busybox-w32-a769390da604b4815535e296d8a46fdf9094c2c7.tar.bz2
busybox-w32-a769390da604b4815535e296d8a46fdf9094c2c7.zip
hush: fix a memory corruption when exported variable is modified
The construct such as this: t=1 export t t=new_value1 had a small probability of momentarily using free()d value. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/shell/hush.c b/shell/hush.c
index d0d983018..668b1f2b7 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1891,6 +1891,7 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
1891{ 1891{
1892 struct variable **var_pp; 1892 struct variable **var_pp;
1893 struct variable *cur; 1893 struct variable *cur;
1894 char *free_me = NULL;
1894 char *eq_sign; 1895 char *eq_sign;
1895 int name_len; 1896 int name_len;
1896 1897
@@ -1907,6 +1908,7 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
1907 var_pp = &cur->next; 1908 var_pp = &cur->next;
1908 continue; 1909 continue;
1909 } 1910 }
1911
1910 /* We found an existing var with this name */ 1912 /* We found an existing var with this name */
1911 if (cur->flg_read_only) { 1913 if (cur->flg_read_only) {
1912#if !BB_MMU 1914#if !BB_MMU
@@ -1955,12 +1957,17 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
1955 strcpy(cur->varstr, str); 1957 strcpy(cur->varstr, str);
1956 goto free_and_exp; 1958 goto free_and_exp;
1957 } 1959 }
1958 } else { 1960 /* Can't reuse */
1959 /* max_len == 0 signifies "malloced" var, which we can 1961 cur->max_len = 0;
1960 * (and has to) free */ 1962 goto set_str_and_exp;
1961 free(cur->varstr); 1963 }
1962 } 1964 /* max_len == 0 signifies "malloced" var, which we can
1963 cur->max_len = 0; 1965 * (and have to) free. But we can't free(cur->varstr) here:
1966 * if cur->flg_export is 1, it is in the environment.
1967 * We should either unsetenv+free, or wait until putenv,
1968 * then putenv(new)+free(old).
1969 */
1970 free_me = cur->varstr;
1964 goto set_str_and_exp; 1971 goto set_str_and_exp;
1965 } 1972 }
1966 1973
@@ -1987,10 +1994,15 @@ static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_
1987 cur->flg_export = 0; 1994 cur->flg_export = 0;
1988 /* unsetenv was already done */ 1995 /* unsetenv was already done */
1989 } else { 1996 } else {
1997 int i;
1990 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr); 1998 debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
1991 return putenv(cur->varstr); 1999 i = putenv(cur->varstr);
2000 /* only now we can free old exported malloced string */
2001 free(free_me);
2002 return i;
1992 } 2003 }
1993 } 2004 }
2005 free(free_me);
1994 return 0; 2006 return 0;
1995} 2007}
1996 2008