]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
fix getpwuid() thread safe issue
authorDonghwa Jeong <dh48.jeong@samsung.com>
Thu, 14 Jun 2018 06:32:03 +0000 (15:32 +0900)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 10 Dec 2018 08:16:00 +0000 (09:16 +0100)
Signed-off-by: Donghwa Jeong <dh48.jeong@samsung.com>
src/lxc/attach.c
src/lxc/conf.c
src/lxc/lxc_user_nic.c
src/lxc/tools/lxc_usernsexec.c

index 6d921223f9c7149d18c2702f12fbbe54889bfef0..ff2164abc8679e73bb3a366b61f0b711e192176c 100644 (file)
@@ -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;
 }
index 3a0684482feea8143c3e416d993c347f2e4f285a..fb61d285afadba91c79635c8ee62bc229d14cc19 100644 (file)
@@ -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 */
index b7c72abd777b753585160067e885c44f17b7ea7e..032c4310b077b283a4789e623e274960d6d11964 100644 (file)
@@ -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;
index 1e1b982459f5f474157676395883b8d6aad29c5f..454b664a209ce59ddb9426a9cd5cc73be213f1bc 100644 (file)
@@ -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[])