]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
env: save parsed variables into ul_env_list
authorKarel Zak <kzak@redhat.com>
Tue, 27 Aug 2024 11:07:56 +0000 (13:07 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 4 Sep 2024 11:39:03 +0000 (13:39 +0200)
The struct ul_env_list is currently only used to store the value of
env when sanitizing environ[]. It would be beneficial to also use the
functions related to ul_env_list for other purposes. In order to do
this, it is important to keep the NAME and VALUE components separate.

* Accept non-terminated name and value for env_list_add().

* Add env_list_add_from_string() to add item to the list from a
  "name=value" string.

* Add env_list_add_variable() to add item to the list using separate
  "name" and "value" strings.

* Update __sanitize_env() to use env_list_add_from_string().

* Modify the test to use "abc" as the value instead of copying the
  variable name (with '=') to the value.

Signed-off-by: Karel Zak <kzak@redhat.com>
include/env.h
lib/env.c

index 9b29919507fef094c1a752229c1ca5e72a890092..5e9198c884f1ae468c3e985e322709aaf16e021b 100644 (file)
@@ -13,6 +13,10 @@ struct ul_env_list;
 extern void sanitize_env(void);
 extern void __sanitize_env(struct ul_env_list **org);
 
+extern struct ul_env_list *env_list_add_variable(struct ul_env_list *ls,
+                               const char *name, const char *value);
+
+
 extern int env_list_setenv(struct ul_env_list *ls);
 extern void env_list_free(struct ul_env_list *ls);
 extern struct ul_env_list *env_from_fd(int pid);
index 2bdfe5697e900fdf0273ee83125ff60e2cb39918..bab8822b0ec4b8d0efb51b68027f8da0dd75eb27 100644 (file)
--- a/lib/env.c
+++ b/lib/env.c
@@ -52,36 +52,74 @@ static char * const noslash[] = {
 
 
 struct ul_env_list {
-       char *env;
+       char    *name;
+       char    *value;
+
        struct ul_env_list *next;
 };
 
 /*
- * Saves @name env.variable to @ls, returns pointer to the new head of the list.
+ * Saves to the list and returns a pointer to the new head of the list.
  */
-static struct ul_env_list *env_list_add(struct ul_env_list *ls0, const char *str)
+static struct ul_env_list *env_list_add( struct ul_env_list *ls0,
+                                        const char *name, size_t namesz,
+                                        const char *value, size_t valsz)
 {
        struct ul_env_list *ls;
-       char *p;
-       size_t sz = 0;
 
-       if (!str || !*str)
+       ls = calloc(1, sizeof(struct ul_env_list) + namesz + valsz + 2);
+       if (!ls)
                return ls0;
 
-       sz = strlen(str) + 1;
-       p = malloc(sizeof(struct ul_env_list) + sz);
-       if (!p)
-               return ls0;
+       ls->name = ((char *) ls) + sizeof(struct ul_env_list);
+       ls->value = ls->name + namesz + 1;
 
-       ls = (struct ul_env_list *) p;
-       p += sizeof(struct ul_env_list);
-       memcpy(p, str, sz);
-       ls->env = p;
+       memcpy(ls->name, name, namesz);
+       memcpy(ls->value, value, valsz);
 
        ls->next = ls0;
        return ls;
 }
 
+
+/*
+ * Saves the @str (with the name=value string) to the @ls and returns a pointer
+ * to the new head of the list.
+ */
+static struct ul_env_list *env_list_add_from_string(struct ul_env_list *ls,
+                                                   const char *str)
+{
+       size_t namesz = 0, valsz = 0;
+       const char *val;
+
+       if (!str || !*str)
+               return ls;
+
+       val = strchr(str, '=');
+       if (!val)
+               return NULL;
+       namesz = val - str;
+
+       val++;
+       valsz = strlen(val);
+
+       return env_list_add(ls, str, namesz, val, valsz);
+}
+
+/*
+ * Saves the @name and @value to @ls0 and returns a pointer to the new head of
+ * the list.
+ */
+struct ul_env_list *env_list_add_variable(
+                               struct ul_env_list *ls,
+                               const char *name, const char *value)
+{
+       if (!name || !*name)
+               return ls;
+
+       return env_list_add(ls, name, strlen(name), value, value ? strlen(value) : 0);
+}
+
 /*
  * Use env_from_fd() to read environment from @fd.
  *
@@ -99,7 +137,7 @@ struct ul_env_list *env_from_fd(int fd)
        p = buf;
 
        while (rc > 0) {
-               ls = env_list_add(ls, p);
+               ls = env_list_add_from_string(ls, p);
                p += strlen(p) + 1;
                rc -= strlen(p) + 1;
        }
@@ -110,22 +148,14 @@ struct ul_env_list *env_from_fd(int fd)
 
 /*
  * 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 = '=';
-               }
+               if (ls->name && ls->value)
+                       rc = setenv(ls->name, ls->value, 0);
                ls = ls->next;
        }
        return rc;
@@ -158,7 +188,7 @@ void __sanitize_env(struct ul_env_list **org)
                 for (bad = forbid; *bad; bad++) {
                         if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
                                if (org)
-                                       *org = env_list_add(*org, *cur);
+                                       *org = env_list_add_from_string(*org, *cur);
                                 last = remove_entry(envp, cur - envp, last);
                                 cur--;
                                 break;
@@ -173,7 +203,7 @@ void __sanitize_env(struct ul_env_list **org)
                         if (!strchr(*cur, '/'))
                                 continue;  /* OK */
                        if (org)
-                               *org = env_list_add(*org, *cur);
+                               *org = env_list_add_from_string(*org, *cur);
                         last = remove_entry(envp, cur - envp, last);
                         cur--;
                         break;
@@ -217,12 +247,13 @@ int main(void)
        int retval = EXIT_SUCCESS;
        struct ul_env_list *removed = NULL;
 
+       /* define env. */
        for (bad = forbid; *bad; bad++) {
                strcpy(copy, *bad);
                p = strchr(copy, '=');
                if (p)
                        *p = '\0';
-               setenv(copy, copy, 1);
+               setenv(copy, "abc", 1);
        }
 
        /* removed */