From 459e811de123e54efb3d98601c955419580277da Mon Sep 17 00:00:00 2001
From: jikai <jikai11@huawei.com>
Date: Mon, 29 Apr 2024 09:14:53 +0800
Subject: [PATCH 211/213] bugfix for hostname env: set only once

Signed-off-by: jikai <jikai11@huawei.com>
---
 src/daemon/modules/spec/specs.c        | 11 +++++-
 src/daemon/modules/spec/specs_extend.c | 52 +++++++++++++++++---------
 src/daemon/modules/spec/specs_extend.h |  2 +
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
index d2088a8e..bbe73bf5 100644
--- a/src/daemon/modules/spec/specs.c
+++ b/src/daemon/modules/spec/specs.c
@@ -1793,14 +1793,21 @@ static int merge_process_conf(oci_runtime_spec *oci_spec, const host_config *hos
         goto out;
     }
 
-    /* environment variables */
+    /* 1. merge env from container_spec: --env or --env-file */
     ret = merge_env(oci_spec, (const char **)container_spec->env, container_spec->env_len);
     if (ret != 0) {
         ERROR("Failed to merge environment variables");
         goto out;
     }
 
-    /* env target file */
+    /* 2. merge default env hostname, only if hostname not set before */
+    ret = merge_hostname_env(oci_spec);
+    if (ret != 0) {
+        ERROR("Failed to merge hostname env");
+        goto out;
+    }
+
+    /* 3. persist env from --env-target-file, only if the env not set before, system container only */
     ret = merge_env_target_file(oci_spec, host_spec->env_target_file);
     if (ret != 0) {
         ERROR("Failed to merge env target file");
diff --git a/src/daemon/modules/spec/specs_extend.c b/src/daemon/modules/spec/specs_extend.c
index a9e8142e..b4b8af5a 100644
--- a/src/daemon/modules/spec/specs_extend.c
+++ b/src/daemon/modules/spec/specs_extend.c
@@ -421,34 +421,23 @@ out:
 int merge_env(oci_runtime_spec *oci_spec, const char **env, size_t env_len)
 {
     int ret = 0;
-    int nret = 0;
     size_t new_size = 0;
     size_t old_size = 0;
     size_t i;
     char **temp = NULL;
-    // 10 is lenght of "HOSTNAME=" and '\0'
-    char host_name_env[MAX_HOST_NAME_LEN + 10] = { 0 };
-
-    nret = snprintf(host_name_env, sizeof(host_name_env), "HOSTNAME=%s", oci_spec->hostname);
-    if (nret < 0 || (size_t)nret >= sizeof(host_name_env)) {
-        ret = -1;
-        ERROR("Sprint failed");
-        goto out;
-    }
 
     ret = make_sure_oci_spec_process(oci_spec);
     if (ret < 0) {
         goto out;
     }
 
-    if (env_len > LIST_ENV_SIZE_MAX - oci_spec->process->env_len - 1) {
+    if (env_len > LIST_ENV_SIZE_MAX - oci_spec->process->env_len) {
         ERROR("The length of envionment variables is too long, the limit is %lld", LIST_ENV_SIZE_MAX);
         isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
         ret = -1;
         goto out;
     }
-    // add 1 for hostname env
-    new_size = (oci_spec->process->env_len + env_len + 1) * sizeof(char *);
+    new_size = (oci_spec->process->env_len + env_len) * sizeof(char *);
     old_size = oci_spec->process->env_len * sizeof(char *);
     ret = util_mem_realloc((void **)&temp, new_size, oci_spec->process->env, old_size);
     if (ret != 0) {
@@ -459,10 +448,6 @@ int merge_env(oci_runtime_spec *oci_spec, const char **env, size_t env_len)
 
     oci_spec->process->env = temp;
 
-    // append hostname env into default oci spec env list
-    oci_spec->process->env[oci_spec->process->env_len] = util_strdup_s(host_name_env);
-    oci_spec->process->env_len++;
-
     for (i = 0; i < env_len && env != NULL; i++) {
         oci_spec->process->env[oci_spec->process->env_len] = util_strdup_s(env[i]);
         oci_spec->process->env_len++;
@@ -471,6 +456,39 @@ out:
     return ret;
 }
 
+int merge_hostname_env(oci_runtime_spec *oci_spec)
+{
+    int nret = 0;
+    bool is_append = true;
+    // 10 is lenght of "HOSTNAME=" and '\0'
+    char host_name_env[MAX_HOST_NAME_LEN + 10] = { 0 };
+    const char *envs[1] = {host_name_env};
+
+    if (make_sure_oci_spec_process(oci_spec) < 0) {
+        return -1;
+    }
+
+    if (check_env_need_append(oci_spec, "HOSTNAME", &is_append) < 0) {
+        return -1;
+    }
+
+    if (!is_append) {
+        return 0;
+    }
+
+    nret = snprintf(host_name_env, sizeof(host_name_env), "HOSTNAME=%s", oci_spec->hostname);
+    if (nret < 0 || (size_t)nret >= sizeof(host_name_env)) {
+        ERROR("Sprint failed");
+        return -1;
+    }
+
+    if (merge_env(oci_spec, (const char **)envs, 1) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
 char *oci_container_get_env(const oci_runtime_spec *oci_spec, const char *key)
 {
     const defs_process *op = NULL;
diff --git a/src/daemon/modules/spec/specs_extend.h b/src/daemon/modules/spec/specs_extend.h
index d70f5bec..15ec6b2f 100644
--- a/src/daemon/modules/spec/specs_extend.h
+++ b/src/daemon/modules/spec/specs_extend.h
@@ -50,6 +50,8 @@ int make_userns_remap(oci_runtime_spec *container, const char *user_remap);
 
 int merge_env(oci_runtime_spec *oci_spec, const char **env, size_t env_len);
 
+int merge_hostname_env(oci_runtime_spec *oci_spec);
+
 int merge_env_target_file(oci_runtime_spec *oci_spec, const char *env_target_file);
 
 char *oci_container_get_env(const oci_runtime_spec *oci_spec, const char *key);
-- 
2.25.1

