]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
su: use lib/env.c for --whitelist-environment
authorKarel Zak <kzak@redhat.com>
Wed, 28 Aug 2024 10:08:30 +0000 (12:08 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 4 Sep 2024 11:39:03 +0000 (13:39 +0200)
Do not use a local implementation, instead use code from the lib/
directory.

Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/su-common.c

index 5365575353641d3ff428dfa5e507d2650a65c6b4..12c9336339cd9331c19a6b0d5717c494fc869bd8 100644 (file)
@@ -144,8 +144,7 @@ struct su_context {
        pid_t           child;                  /* fork() baby */
        int             childstatus;            /* wait() status */
 
-       char            **env_whitelist_names;  /* environment whitelist */
-       char            **env_whitelist_vals;
+       struct ul_env_list *env_whitelist;      /* environment whitelist */
 
        struct sigaction oldact[SIGNALS_IDX_COUNT];     /* original sigactions indexed by SIG*_IDX */
 #ifdef USE_PTY
@@ -663,56 +662,6 @@ static void create_watching_parent(struct su_context *su)
        exit(status);
 }
 
-/* Adds @name from the current environment to the whitelist. If @name is not
- * set then nothing is added to the whitelist and returns 1.
- */
-static int env_whitelist_add(struct su_context *su, const char *name)
-{
-       const char *env = getenv(name);
-
-       if (!env)
-               return 1;
-       if (strv_extend(&su->env_whitelist_names, name))
-                err_oom();
-       if (strv_extend(&su->env_whitelist_vals, env))
-                err_oom();
-       return 0;
-}
-
-static int env_whitelist_setenv(struct su_context *su, int overwrite)
-{
-       char **one;
-       size_t i = 0;
-       int rc;
-
-       STRV_FOREACH(one, su->env_whitelist_names) {
-               rc = setenv(*one, su->env_whitelist_vals[i], overwrite);
-               if (rc)
-                       return rc;
-               i++;
-       }
-
-       return 0;
-}
-
-/* Creates (add to) whitelist from comma delimited string */
-static int env_whitelist_from_string(struct su_context *su, const char *str)
-{
-       char **all = strv_split(str, ",");
-       char **one;
-
-       if (!all) {
-               if (errno == ENOMEM)
-                       err_oom();
-               return -EINVAL;
-       }
-
-       STRV_FOREACH(one, all)
-               env_whitelist_add(su, *one);
-       strv_free(all);
-       return 0;
-}
-
 static void setenv_path(const struct passwd *pw)
 {
        int rc;
@@ -743,7 +692,7 @@ static void modify_environment(struct su_context *su, const char *shell)
         */
        if (su->simulate_login) {
                /* leave TERM unchanged */
-               env_whitelist_add(su, "TERM");
+               su->env_whitelist = env_list_add_getenv(su->env_whitelist, "TERM", NULL);
 
                /* Note that original su(1) has allocated environ[] by malloc
                 * to the number of expected variables. This seems unnecessary
@@ -768,7 +717,8 @@ static void modify_environment(struct su_context *su, const char *shell)
                xsetenv("LOGNAME", pw->pw_name, 1);
 
                /* apply all from whitelist, but no overwrite */
-               env_whitelist_setenv(su, 0);
+               if (env_list_setenv(su->env_whitelist, 0) != 0)
+                       err(EXIT_FAILURE, _("failed to set environment variables"));
 
        /* Set HOME, SHELL, and (if not becoming a superuser) USER and LOGNAME.
         */
@@ -787,6 +737,9 @@ static void modify_environment(struct su_context *su, const char *shell)
        }
 
        supam_export_environment(su);
+
+       env_list_free(su->env_whitelist);
+       su->env_whitelist = NULL;
 }
 
 static void init_groups(struct su_context *su, gid_t *groups, size_t ngroups)
@@ -1123,7 +1076,7 @@ int su_main(int argc, char **argv, int mode)
                        break;
 
                case 'w':
-                       env_whitelist_from_string(su, optarg);
+                       su->env_whitelist = env_list_add_getenvs(su->env_whitelist, optarg);
                        break;
 
                case 'P':