[lxc-devel] [lxc/master] fix getpwuid() thread safe issue

2xsec on Github lxc-bot at linuxcontainers.org
Thu Jun 14 06:52:52 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 413 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180614/641fc72b/attachment.bin>
-------------- next part --------------
From cb7aa5e8cae121f2d63db60d9e3687a8ac554800 Mon Sep 17 00:00:00 2001
From: Donghwa Jeong <dh48.jeong at samsung.com>
Date: Thu, 14 Jun 2018 15:32:03 +0900
Subject: [PATCH] fix getpwuid() thread safe issue

Signed-off-by: Donghwa Jeong <dh48.jeong at 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 */


More information about the lxc-devel mailing list