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

Reply via email to