diff options
| author | Karel Zak <kzak@redhat.com> | 2020-08-25 10:43:07 +0200 |
|---|---|---|
| committer | Karel Zak <kzak@redhat.com> | 2020-08-25 10:43:07 +0200 |
| commit | e113093ce94ac1145f9986e072746e8b6e8d0da9 (patch) | |
| tree | c2264850ae9aa49b04dbfe8dd048f0dcfb601495 /lib/env.c | |
| parent | 80a54e2b3e4ddfb89e4cdfbedc659c6fc5c9e598 (diff) | |
| download | util-linux-e113093ce94ac1145f9986e072746e8b6e8d0da9.tar.gz | |
lib/env: add function to save and restore unwanted variables
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/env.c')
| -rw-r--r-- | lib/env.c | 103 |
1 files changed, 100 insertions, 3 deletions
@@ -50,8 +50,73 @@ static char * const noslash[] = { (char *) 0 }; -void -sanitize_env(void) + +struct ul_env_list { + char *env; + struct ul_env_list *next; +}; + +/* + * Saves @name env.varable to @ls, returns pointer to the new head of the list. + */ +static struct ul_env_list *env_list_add(struct ul_env_list *ls0, const char *str) +{ + struct ul_env_list *ls; + char *p; + size_t sz = 0; + + if (!str || !*str) + return ls0; + + sz = strlen(str) + 1; + p = malloc(sizeof(struct ul_env_list) + sz); + + ls = (struct ul_env_list *) p; + p += sizeof(struct ul_env_list); + memcpy(p, str, sz); + ls->env = p; + + ls->next = ls0; + return ls; +} + +/* + * Use setenv() for all stuff in @ls. + * + * It would be possible to use putenv(), but we want to keep @ls free()-able. + */ +int env_list_setenv(struct ul_env_list *ls) +{ + int rc = 0; + + while (ls && rc == 0) { + if (ls->env) { + char *val = strchr(ls->env, '='); + if (!val) + continue; + *val = '\0'; + rc = setenv(ls->env, val + 1, 0); + *val = '='; + } + ls = ls->next; + } + return rc; +} + +void env_list_free(struct ul_env_list *ls) +{ + while (ls) { + struct ul_env_list *x = ls; + ls = ls->next; + free(x); + } +} + +/* + * Removes unwanted variables from environ[]. If @ls is not NULL than stores + * unwnated variables to the list. + */ +void __sanitize_env(struct ul_env_list **org) { char **envp = environ; char * const *bad; @@ -64,6 +129,8 @@ sanitize_env(void) for (cur = envp; *cur; cur++) { for (bad = forbid; *bad; bad++) { if (strncmp(*cur, *bad, strlen(*bad)) == 0) { + if (org) + *org = env_list_add(*org, *cur); last = remote_entry(envp, cur - envp, last); cur--; break; @@ -77,6 +144,8 @@ sanitize_env(void) continue; if (!strchr(*cur, '/')) continue; /* OK */ + if (org) + *org = env_list_add(*org, *cur); last = remote_entry(envp, cur - envp, last); cur--; break; @@ -84,6 +153,10 @@ sanitize_env(void) } } +void sanitize_env(void) +{ + __sanitize_env(NULL); +} char *safe_getenv(const char *arg) { @@ -116,6 +189,7 @@ int main(void) char copy[32]; char *p; int retval = EXIT_SUCCESS; + struct ul_env_list *removed = NULL; for (bad = forbid; *bad; bad++) { strcpy(copy, *bad); @@ -124,7 +198,11 @@ int main(void) *p = '\0'; setenv(copy, copy, 1); } - sanitize_env(); + + /* removed */ + __sanitize_env(&removed); + + /* check removal */ for (bad = forbid; *bad; bad++) { strcpy(copy, *bad); p = strchr(copy, '='); @@ -136,6 +214,25 @@ int main(void) retval = EXIT_FAILURE; } } + + /* restore removed */ + env_list_setenv(removed); + + /* check restore */ + for (bad = forbid; *bad; bad++) { + strcpy(copy, *bad); + p = strchr(copy, '='); + if (p) + *p = '\0'; + p = getenv(copy); + if (!p) { + warnx("%s was not restored", copy); + retval = EXIT_FAILURE; + } + } + + env_list_free(removed); + return retval; } #endif |
