Check $HOME and home dir of $USER before getpwuid()->pw_dir

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

Signed-off-by: Christoph Lohmann <20h@r-36.net>
This commit is contained in:
Dmitry Bogatov 2016-05-29 11:56:51 +02:00 committed by Quentin Rameau
parent 3530d18d8e
commit cee8f0186c
1 changed files with 36 additions and 7 deletions

43
surf.c
View File

@ -350,29 +350,58 @@ buildfile(const char *path)
return fpath;
}
static const char*
get_user_homedir(const char *user) {
struct passwd *pw = getpwnam(user);
if (!pw) {
die("Can't get user `%s' home directory.\n", user);
}
return pw->pw_dir;
}
static const char*
get_current_user_homedir() {
const char *homedir;
const char *user;
struct passwd *pw;
homedir = getenv("HOME");
if (homedir) {
return homedir;
}
user = getenv("USER");
if (user) {
return get_user_homedir(user);
}
pw = getpwuid(getuid());
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 = get_current_user_homedir();
} 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 = get_user_homedir(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);
}