diff --git a/0009-fix-HOME-env-of-container-unset-error.patch b/0009-fix-HOME-env-of-container-unset-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..799a7e71c85942f07524a88a0f116f16ec6b663f --- /dev/null +++ b/0009-fix-HOME-env-of-container-unset-error.patch @@ -0,0 +1,316 @@ +From 043b2483585a2d8168e0fde8b37054733a31f263 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Mon, 25 Jul 2022 15:36:23 +0800 +Subject: [PATCH] fix HOME env of container unset error + +Signed-off-by: haozi007 +--- + src/lxc/isulad_utils.c | 210 ++++++++++++++++++++++++++++++++++++++++- + src/lxc/isulad_utils.h | 3 + + src/lxc/start.c | 14 +-- + 3 files changed, 216 insertions(+), 11 deletions(-) + +diff --git a/src/lxc/isulad_utils.c b/src/lxc/isulad_utils.c +index 15d9323..cd7fca8 100644 +--- a/src/lxc/isulad_utils.c ++++ b/src/lxc/isulad_utils.c +@@ -6,6 +6,10 @@ + * Create: 2020-04-11 + ******************************************************************************/ + ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ + #include + #include + #include +@@ -13,6 +17,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + + #include "isulad_utils.h" + #include "log.h" +@@ -244,20 +252,34 @@ out: + // isulad: set env home in container + int lxc_setup_env_home(uid_t uid) + { ++#define __PASSWD_FILE__ "/etc/passwd" + char *homedir = "/"; // default home dir is / ++ FILE *stream = NULL; + struct passwd pw, *pwbufp = NULL; + char buf[BUFSIZ]; +- int ret; + +- ret = getpwuid_r(uid, &pw, buf, sizeof(buf), &pwbufp); +- if ((ret == 0) && (pwbufp != NULL) && (pwbufp->pw_uid == uid)) { +- homedir = pwbufp->pw_dir; ++ stream = fopen_cloexec(__PASSWD_FILE__, "r"); ++ if (stream == NULL) { ++ SYSWARN("Failed to open %s", __PASSWD_FILE__); + goto set_env; + } + ++#if IS_BIONIC ++ while (util_getpwent_r(stream, &pw, buf, sizeof(buf), &pwbufp) == 0 && pwbufp != NULL) { ++#else ++ while (fgetpwent_r(stream, &pw, buf, sizeof(buf), &pwbufp) == 0 && pwbufp != NULL) { ++#endif ++ if (pwbufp->pw_uid == uid) { ++ homedir = pwbufp->pw_dir; ++ goto set_env; ++ } ++ } + WARN("User invalid, can not find user '%u'", uid); + + set_env: ++ if (stream) ++ fclose(stream); ++ + // if we didn't configure HOME, set it based on uid + if (setenv("HOME", homedir, 0) < 0) { + SYSERROR("Unable to set env 'HOME'"); +@@ -317,3 +339,183 @@ bool is_non_negative_num(const char *s) + } + return true; + } ++ ++static int hold_int(const char delim, bool required, char **src, unsigned int *dst) ++{ ++ unsigned long long int res = 0; ++ char *err_str = NULL; ++ ++ // ensure *src not a empty string ++ if (**src == '\0') { ++ ERROR("Empty subject on given entrie is not allowed."); ++ return -1; ++ } ++ ++ errno = 0; ++ // covert string to long long ++ res = strtoull(*src, &err_str, 0); ++ if (errno != 0 && errno != ERANGE) { ++ ERROR("Parse int from string failed."); ++ return -1; ++ } ++ ++ // **src is not a digit ++ if (err_str == *src) { ++ if (!required) { ++ ERROR("Integer part is missing."); ++ return -1; ++ } ++ // if required, just set 0 ++ *dst = 0; ++ } else { ++ if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit ++ res = UINT_MAX; ++ } ++ res = res & UINT_MAX; ++ *dst = (uint32_t)res; ++ } ++ ++ // normal case ++ if (*err_str == delim) { ++ err_str++; ++ } else if (*err_str != '\0') { ++ ERROR("Invalid digit string."); ++ return -1; ++ } ++ ++ *src = err_str; // update src to next valid context in line. ++ return 0; ++} ++ ++static void hold_string(const char delim, char **src, char **dst) ++{ ++ for (*dst = *src; **src != delim; ++(*src)) { ++ if (**src == '\0') { ++ break; ++ } ++ } ++ ++ if (**src == delim) { ++ **src = '\0'; ++ ++(*src); ++ } ++} ++ ++static int parse_line_pw(const char delim, char *line, struct passwd *result) ++{ ++ int ret = 0; ++ bool required = false; ++ char *walker = NULL; ++ ++ walker = strpbrk(line, "\n"); ++ if (walker != NULL) { ++ // clear newline char ++ *walker = '\0'; ++ } ++ ++ hold_string(delim, &line, &result->pw_name); ++ ++ required = (result->pw_name[0] == '+' || result->pw_name[0] == '-') ? true : false; ++ ++ hold_string(delim, &line, &result->pw_passwd); ++ ++ ret = hold_int(delim, required, &line, &result->pw_uid); ++ if (ret != 0) { ++ // a legitimate line must have uid ++ ERROR("Parse uid error."); ++ return ret; ++ } ++ ++ ret = hold_int(delim, required, &line, &result->pw_gid); ++ if (ret != 0) { ++ // it's ok to not provide gid ++ ERROR("Parse gid error."); ++ return ret; ++ } ++ ++ hold_string(delim, &line, &result->pw_gecos); ++ ++ hold_string(delim, &line, &result->pw_dir); ++ ++ result->pw_shell = line; ++ return 0; ++} ++ ++char *util_left_trim_space(char *str) ++{ ++ char *begin = str; ++ char *tmp = str; ++ while (isspace(*begin)) { ++ begin++; ++ } ++ while ((*tmp++ = *begin++)) { ++ } ++ return str; ++} ++ ++int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t buflen, struct passwd **result) ++{ ++ const char delim = ':'; ++ char *buff_end = NULL; ++ char *walker = NULL; ++ bool got = false; ++ int ret = 0; ++ ++ if (stream == NULL || resbuf == NULL || buffer == NULL || result == NULL) { ++ ERROR("Password obj, params is NULL."); ++ return -1; ++ } ++ ++ if (buflen <= 1) { ++ ERROR("Inadequate buffer length was given."); ++ return -1; ++ } ++ ++ buff_end = buffer + buflen - 1; ++ flockfile(stream); ++ ++ while (1) { ++ *buff_end = '\xff'; ++ walker = fgets_unlocked(buffer, buflen, stream); ++ // if get NULL string ++ if (walker == NULL) { ++ *result = NULL; ++ // reach end of file, return error ++ if (feof(stream)) { ++ ret = ENOENT; ++ goto out; ++ } ++ // overflow buffer ++ ret = ERANGE; ++ goto out; ++ } ++ // just overflow last char in buffer ++ if (*buff_end != '\xff') { ++ *result = NULL; ++ ret = ERANGE; ++ goto out; ++ } ++ ++ (void)util_left_trim_space(buffer); ++ // skip comment line and empty line ++ if (walker[0] == '#' || walker[0] == '\0') { ++ continue; ++ } ++ ++ if (parse_line_pw(delim, walker, resbuf) == 0) { ++ got = true; ++ break; ++ } ++ } ++ if (!got) { ++ *result = NULL; ++ ret = ERANGE; ++ goto out; ++ } ++ ++ *result = resbuf; ++ ret = 0; ++out: ++ funlockfile(stream); ++ return ret; ++} +\ No newline at end of file +diff --git a/src/lxc/isulad_utils.h b/src/lxc/isulad_utils.h +index 345f511..7a5eb89 100644 +--- a/src/lxc/isulad_utils.h ++++ b/src/lxc/isulad_utils.h +@@ -10,6 +10,7 @@ + + #include + #include ++#include + + /* isulad: replace space with SPACE_MAGIC_STR */ + #define SPACE_MAGIC_STR "[#)" +@@ -96,4 +97,6 @@ extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); + + extern bool is_non_negative_num(const char *s); + ++int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t buflen, struct passwd **result); ++ + #endif +diff --git a/src/lxc/start.c b/src/lxc/start.c +index f82df34..6fe1203 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1727,6 +1727,13 @@ static int do_start(void *data) + new_uid = handler->conf->init_uid; + new_gid = handler->conf->init_gid; + ++#ifdef HAVE_ISULAD ++ // isulad: set env home in container, must before "Avoid unnecessary syscalls." ++ if (lxc_setup_env_home(new_uid) < 0) { ++ goto out_warn_father; ++ } ++#endif ++ + /* Avoid unnecessary syscalls. */ + if (new_uid == nsuid) + new_uid = LXC_INVALID_UID; +@@ -1734,13 +1741,6 @@ static int do_start(void *data) + if (new_gid == nsgid) + new_gid = LXC_INVALID_GID; + +-#ifdef HAVE_ISULAD +- // isulad: set env home in container +- if (lxc_setup_env_home(new_uid) < 0) { +- goto out_warn_father; +- } +-#endif +- + /* Make sure that the processes STDIO is correctly owned by the user that we are switching to */ + ret = fix_stdio_permissions(new_uid); + if (ret) +-- +2.25.1 + diff --git a/lxc.spec b/lxc.spec index e06e2b8f49004c848950a552f6503869642c5ad5..5dc52b687d5729a9ab0767b3fba51c2b3d8d5daf 100644 --- a/lxc.spec +++ b/lxc.spec @@ -1,4 +1,4 @@ -%global _release 2022072104 +%global _release 2022072501 Name: lxc Version: 4.0.3 @@ -16,6 +16,7 @@ Patch0005: 0005-refactor-patch-code-of-attach-and-seccomp.patch Patch0006: 0006-refactor-patch-about-namespace-log-terminal.patch Patch0007: 0007-refactor-patches-on-terminal.c-start.c-and-so-on.patch Patch0008: 0008-refactor-patch-code-of-json.patch +Patch0009: 0009-fix-HOME-env-of-container-unset-error.patch BuildRequires: systemd-units git libtool graphviz docbook2X doxygen chrpath BuildRequires: pkgconfig(libseccomp) @@ -187,6 +188,12 @@ make check %{_mandir}/*/man7/%{name}* %changelog +* Mon Jul 25 2022 haozi007 - 4.0.3-2022072501 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: fix HOME env unset error + * Thu Jul 21 2022 zhangxiaoyu - 4.0.3-2022072104 - Type:bugfix - ID:NA diff --git a/series.conf b/series.conf index 24c4e2818dcf853c2a66224acbdaf58dd1945892..2416293553ec785cf4ebb14fcdbf6bfb818a192e 100644 --- a/series.conf +++ b/series.conf @@ -6,4 +6,4 @@ 0006-refactor-patch-about-namespace-log-terminal.patch 0007-refactor-patches-on-terminal.c-start.c-and-so-on.patch 0008-refactor-patch-code-of-json.patch - +0009-fix-HOME-env-of-container-unset-error.patch