diff --git a/0044-fix-HOME-env-unset-error.patch b/0044-fix-HOME-env-unset-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfd41f53c0dc6f3008318e1fab037d647b33634a --- /dev/null +++ b/0044-fix-HOME-env-unset-error.patch @@ -0,0 +1,321 @@ +From d86ad6bf0acaa98b11344627a8118a2945b8da1e Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Mon, 25 Jul 2022 11:08:29 +0800 +Subject: [PATCH] fix HOME env unset error + +Signed-off-by: haozi007 +--- + src/lxc/isulad_utils.c | 190 +++++++++++++++++++++++++++++++++++++++++ + src/lxc/isulad_utils.h | 3 + + src/lxc/start.c | 14 +-- + src/lxc/utils.c | 22 ++++- + 4 files changed, 218 insertions(+), 11 deletions(-) + +diff --git a/src/lxc/isulad_utils.c b/src/lxc/isulad_utils.c +index b282404..f72b5fe 100644 +--- a/src/lxc/isulad_utils.c ++++ b/src/lxc/isulad_utils.c +@@ -6,11 +6,21 @@ + * Create: 2020-04-11 + ******************************************************************************/ + ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE 1 ++#endif ++ ++#include ++#include + #include + #include + #include + #include + #include ++#include ++#include ++#include ++#include + + #include "isulad_utils.h" + #include "log.h" +@@ -97,3 +107,183 @@ FILE *lxc_fopen(const char *filename, const char *mode) + + return fopen_cloexec(rpath, mode); + } ++ ++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 7a6ab00..1368c83 100644 +--- a/src/lxc/isulad_utils.h ++++ b/src/lxc/isulad_utils.h +@@ -9,6 +9,7 @@ + #define __iSULAD_UTILS_H + + #include ++#include + + extern int lxc_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); + extern void *lxc_common_calloc_s(size_t size); +@@ -17,4 +18,6 @@ extern char *safe_strdup(const char *src); + extern int lxc_open(const char *filename, int flags, mode_t mode); + extern FILE *lxc_fopen(const char *filename, const char *mode); + ++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 c1563e0..aeafd47 100644 +--- a/src/lxc/start.c ++++ b/src/lxc/start.c +@@ -1716,6 +1716,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; +@@ -1723,13 +1730,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) +diff --git a/src/lxc/utils.c b/src/lxc/utils.c +index b39b6a8..20ca181 100644 +--- a/src/lxc/utils.c ++++ b/src/lxc/utils.c +@@ -2213,20 +2213,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'"); +-- +2.25.1 + diff --git a/lxc.spec b/lxc.spec index ed79a7d07c14ec15c9800cf1168d6e77a760faf5..e3aaa5925cf658a4fe934d0bc19827d9b39fe7ae 100644 --- a/lxc.spec +++ b/lxc.spec @@ -1,4 +1,4 @@ -%global _release 2022052501 +%global _release 2022072501 Name: lxc Version: 4.0.3 @@ -51,6 +51,7 @@ Patch0040: 0040-refactor-the-way-to-convert-selinux-label-to-shared.path Patch0041: 0041-do-not-free-the-pointer-returned-by-dirname.patch Patch0042: 0042-add-x-permission-when-create-directory.patch Patch0043: 0043-do-not-operate-playload-and-attach-cgroup-if-no-cont.patch +Patch0044: 0044-fix-HOME-env-unset-error.patch BuildRequires: systemd-units git libtool graphviz docbook2X doxygen chrpath BuildRequires: pkgconfig(libseccomp) @@ -222,6 +223,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 + * Wed May 25 2022 hejunjie - 4.0.3-2022052501 - Type:bugfix - ID:NA diff --git a/series.conf b/series.conf index 00d07d0bad247d70bd08e89647c8ffaf712f8f15..e1db9bbca5931d1367e3d6ce66938dd3a1cb576b 100644 --- a/series.conf +++ b/series.conf @@ -41,3 +41,4 @@ 0041-do-not-free-the-pointer-returned-by-dirname.patch 0042-add-x-permission-when-create-directory.patch 0043-do-not-operate-playload-and-attach-cgroup-if-no-cont.patch +0044-fix-HOME-env-unset-error.patch