The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/2400
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Hello, fix getpwuid() thread safe issue. Thanks. Signed-off-by: Donghwa Jeong <dh48.je...@samsung.com>
From cb7aa5e8cae121f2d63db60d9e3687a8ac554800 Mon Sep 17 00:00:00 2001 From: Donghwa Jeong <dh48.je...@samsung.com> Date: Thu, 14 Jun 2018 15:32:03 +0900 Subject: [PATCH] fix getpwuid() thread safe issue Signed-off-by: Donghwa Jeong <dh48.je...@samsung.com> --- src/lxc/attach.c | 29 ++++++++++++++++++++++++----- src/lxc/cmd/lxc_user_nic.c | 31 ++++++++++++++++++++++++++----- src/lxc/cmd/lxc_usernsexec.c | 38 +++++++++++++++++++++++++++++++++----- src/lxc/conf.c | 30 ++++++++++++++++++++++++++---- 4 files changed, 109 insertions(+), 19 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 9bbdd0e6a..dd98a6d33 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -1501,14 +1501,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 @@ -1516,10 +1534,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); @@ -1528,7 +1546,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/cmd/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c index d071ce0b5..2b0ee6059 100644 --- a/src/lxc/cmd/lxc_user_nic.c +++ b/src/lxc/cmd/lxc_user_nic.c @@ -103,15 +103,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) @@ -1170,6 +1190,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/cmd/lxc_usernsexec.c b/src/lxc/cmd/lxc_usernsexec.c index 725796270..56e1bdbcb 100644 --- a/src/lxc/cmd/lxc_usernsexec.c +++ b/src/lxc/cmd/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[]) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index c5586b33c..66f5c915b 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -4508,13 +4508,35 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, /* 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; - return strdup(result->pw_name); + 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 username; } /* not thread-safe, do not use from api without first forking */
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel