From: Donghwa Jeong Date: Thu, 14 Jun 2018 06:32:03 +0000 (+0900) Subject: fix getpwuid() thread safe issue X-Git-Tag: lxc-2.0.10~99 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4e4e025e36557cd4f5e5c99316cff1fc628b70fc;p=thirdparty%2Flxc.git fix getpwuid() thread safe issue Signed-off-by: Donghwa Jeong --- diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 6d921223f..ff2164abc 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -1426,14 +1426,32 @@ int lxc_attach_run_command(void* payload) int lxc_attach_run_shell(void* payload) { uid_t uid; - struct passwd *passwd; + struct passwd pwent; + struct passwd *pwentp = NULL; char *user_shell; + char *buf; + size_t bufsize; + int ret; /* Ignore payload parameter. */ (void)payload; uid = getuid(); - passwd = getpwuid(uid); + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + buf = malloc(bufsize); + if (buf) { + ret = getpwuid_r(uid, &pwent, buf, bufsize, &pwentp); + if (!pwentp) { + if (ret == 0) + WARN("Could not find matched password record."); + + WARN("Failed to get password record - %u", uid); + } + } /* This probably happens because of incompatible nss implementations in * host and container (remember, this code is still using the host's @@ -1441,10 +1459,10 @@ int lxc_attach_run_shell(void* payload) * the information by spawning a [getent passwd uid] process and parsing * the result. */ - if (!passwd) + if (!pwentp) user_shell = lxc_attach_getpwshell(uid); else - user_shell = passwd->pw_shell; + user_shell = pwent.pw_shell; if (user_shell) execlp(user_shell, user_shell, (char *)NULL); @@ -1453,7 +1471,8 @@ int lxc_attach_run_shell(void* payload) */ execlp("/bin/sh", "/bin/sh", (char *)NULL); SYSERROR("Failed to execute shell"); - if (!passwd) + if (!pwentp) free(user_shell); + free(buf); return -1; } diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 3a0684482..fb61d285a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -4241,13 +4241,35 @@ on_error: /* not thread-safe, do not use from api without first forking */ static char* getuname(void) { - struct passwd *result; + struct passwd pwent; + struct passwd *pwentp = NULL; + char *buf; + char *username; + size_t bufsize; + int ret; - result = getpwuid(geteuid()); - if (!result) + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + ret = getpwuid_r(geteuid(), &pwent, buf, bufsize, &pwentp); + if (!pwentp) { + if (ret == 0) + WARN("Could not find matched password record."); + + ERROR("Failed to get password record - %u", geteuid()); + free(buf); return NULL; + } + + username = strdup(pwent.pw_name); + free(buf); - return strdup(result->pw_name); + return username; } /* not thread-safe, do not use from api without first forking */ diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c index b7c72abd7..032c4310b 100644 --- a/src/lxc/lxc_user_nic.c +++ b/src/lxc/lxc_user_nic.c @@ -102,15 +102,35 @@ static int open_and_lock(char *path) static char *get_username(void) { - struct passwd *pwd; + struct passwd pwent; + struct passwd *pwentp = NULL; + char *buf; + char *username; + size_t bufsize; + int ret; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + ret = getpwuid_r(getuid(), &pwent, buf, bufsize, &pwentp); + if (!pwentp) { + if (ret == 0) + usernic_error("%s", "Could not find matched password record\n"); - pwd = getpwuid(getuid()); - if (!pwd) { - usernic_error("Failed to get username: %s\n", strerror(errno)); + usernic_error("Failed to get username: %s(%u)\n", strerror(errno), getuid()); + free(buf); return NULL; } - return pwd->pw_name; + username = strdup(pwent.pw_name); + free(buf); + + return username; } static void free_groupnames(char **groupnames) @@ -1198,6 +1218,7 @@ int main(int argc, char *argv[]) } n = get_alloted(me, args.type, args.link, &alloted); + free(me); if (request == LXC_USERNIC_DELETE) { int ret; diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c index 1e1b98245..454b664a2 100644 --- a/src/lxc/tools/lxc_usernsexec.c +++ b/src/lxc/tools/lxc_usernsexec.c @@ -253,14 +253,42 @@ static int read_default_map(char *fnam, int which, char *username) static int find_default_map(void) { - struct passwd *p = getpwuid(getuid()); - if (!p) + struct passwd pwent; + struct passwd *pwentp = NULL; + char *buf; + size_t bufsize; + int ret; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + buf = malloc(bufsize); + if (!buf) return -1; - if (read_default_map(subuidfile, ID_TYPE_UID, p->pw_name) < 0) + + ret = getpwuid_r(getuid(), &pwent, buf, bufsize, &pwentp); + if (!pwentp) { + if (ret == 0) + printf("WARN: could not find matched password record\n"); + + printf("Failed to get password record - %u\n", getuid()); + free(buf); return -1; - if (read_default_map(subgidfile, ID_TYPE_GID, p->pw_name) < 0) + } + + if (read_default_map(subuidfile, ID_TYPE_UID, pwent.pw_name) < 0) { + free(buf); return -1; - return 0; + } + + if (read_default_map(subgidfile, ID_TYPE_GID, pwent.pw_name) < 0) { + free(buf); + return -1; + } + + free(buf); + return 0; } int main(int argc, char *argv[])