[dev] [PATCH v2] Check $HOME and home dir of $USER before getpwuid()->pw_dir

From: Reiner Herrmann <reiner_AT_reiner-h.de>
Date: Sun, 29 May 2016 16:06:33 +0200

From: Dmitry Bogatov <KAction_AT_gnu.org>

getpwnam(3) recommends to use $HOME instead of getpwuid()->pw_dir,
as it allows users to point programs to a different path.

Using getpwuid() also breaks namespaces-related use cases,
like `unshare -r`.

Patch was submitted by Dmitry Bogatov on the Debian bug tracker:
https://bugs.debian.org/825397
---
 surf.c | 46 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)
diff --git a/surf.c b/surf.c
index 23c49bd..029c774 100644
--- a/surf.c
+++ b/surf.c
_AT_@ -115,6 +115,8 @@ static void addaccelgroup(Client *c);
 static void beforerequest(WebKitWebView *w, WebKitWebFrame *f,
                           WebKitWebResource *r, WebKitNetworkRequest *req,
                           WebKitNetworkResponse *resp, Client *c);
+static const char *getuserhomedir(const char *user);
+static const char *getcurrentuserhomedir(void);
 static char *buildfile(const char *path);
 static char *buildpath(const char *path);
 static gboolean buttonrelease(WebKitWebView *web, GdkEventButton *e, Client *c);
_AT_@ -287,29 +289,59 @@ buildfile(const char *path)
 	return fpath;
 }
 
+const char *
+getuserhomedir(const char *user)
+{
+	struct passwd *pw = getpwnam(user);
+
+	if (!pw)
+		die("Can't get user %s login information\n", user);
+
+	return pw->pw_dir;
+}
+
+const char *
+getcurrentuserhomedir(void)
+{
+	const char *homedir;
+	const char *user;
+	struct passwd *pw;
+
+	homedir = getenv("HOME");
+	if (homedir)
+		return homedir;
+
+	user = getenv("USER");
+	if (user)
+		return getuserhomedir(user);
+
+	pw = getpwuid(geteuid());
+	if (!pw)
+		die("Can't get current user home directory\n");
+
+	return pw->pw_dir;
+}
+
 char *
 buildpath(const char *path)
 {
-	struct passwd *pw;
 	char *apath, *name, *p, *fpath;
 
 	if (path[0] == '~') {
+		const char *homedir;
 		if (path[1] == '/' || path[1] == '\0') {
 			p = (char *)&path[1];
-			pw = getpwuid(getuid());
+			homedir = getcurrentuserhomedir();
 		} else {
 			if ((p = strchr(path, '/')))
 				name = g_strndup(&path[1], --p - path);
 			else
 				name = g_strdup(&path[1]);
 
-			if (!(pw = getpwnam(name))) {
-				die("Can't get user %s home directory: %s.\n",
-				    name, path);
-			}
+			homedir = getuserhomedir(name);
 			g_free(name);
 		}
-		apath = g_build_filename(pw->pw_dir, p, NULL);
+		apath = g_build_filename(homedir, p, NULL);
 	} else {
 		apath = g_strdup(path);
 	}
-- 
2.8.1
Received on Sun May 29 2016 - 16:06:33 CEST

This archive was generated by hypermail 2.3.0 : Sun May 29 2016 - 16:12:09 CEST