Skip to content

Commit 8abd514

Browse files
authored
Merge pull request libgit2#4499 from pks-t/pks/setuid-config
sysdir: do not use environment in setuid case
2 parents 2553cbe + 0967459 commit 8abd514

File tree

1 file changed

+74
-7
lines changed

1 file changed

+74
-7
lines changed

src/sysdir.c

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include <ctype.h>
1414
#if GIT_WIN32
1515
#include "win32/findfile.h"
16+
#else
17+
#include <unistd.h>
18+
#include <pwd.h>
1619
#endif
1720

1821
static int git_sysdir_guess_programdata_dirs(git_buf *out)
@@ -34,12 +37,63 @@ static int git_sysdir_guess_system_dirs(git_buf *out)
3437
#endif
3538
}
3639

40+
#ifndef GIT_WIN32
41+
static int get_passwd_home(git_buf *out, uid_t uid)
42+
{
43+
struct passwd pwd, *pwdptr;
44+
char *buf = NULL;
45+
long buflen;
46+
int error;
47+
48+
assert(out);
49+
50+
if ((buflen = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
51+
buflen = 1024;
52+
53+
do {
54+
buf = git__realloc(buf, buflen);
55+
error = getpwuid_r(uid, &pwd, buf, buflen, &pwdptr);
56+
buflen *= 2;
57+
} while (error == ERANGE && buflen <= 8192);
58+
59+
if (error) {
60+
giterr_set(GITERR_OS, "failed to get passwd entry");
61+
goto out;
62+
}
63+
64+
if (!pwdptr) {
65+
giterr_set(GITERR_OS, "no passwd entry found for user");
66+
goto out;
67+
}
68+
69+
if ((error = git_buf_puts(out, pwdptr->pw_dir)) < 0)
70+
goto out;
71+
72+
out:
73+
git__free(buf);
74+
return error;
75+
}
76+
#endif
77+
3778
static int git_sysdir_guess_global_dirs(git_buf *out)
3879
{
3980
#ifdef GIT_WIN32
4081
return git_win32__find_global_dirs(out);
4182
#else
42-
int error = git__getenv(out, "HOME");
83+
int error;
84+
uid_t uid, euid;
85+
86+
uid = getuid();
87+
euid = geteuid();
88+
89+
/*
90+
* In case we are running setuid, use the configuration
91+
* of the effective user.
92+
*/
93+
if (uid == euid)
94+
error = git__getenv(out, "HOME");
95+
else
96+
error = get_passwd_home(out, euid);
4397

4498
if (error == GIT_ENOTFOUND) {
4599
giterr_clear();
@@ -57,12 +111,25 @@ static int git_sysdir_guess_xdg_dirs(git_buf *out)
57111
#else
58112
git_buf env = GIT_BUF_INIT;
59113
int error;
60-
61-
if ((error = git__getenv(&env, "XDG_CONFIG_HOME")) == 0)
62-
error = git_buf_joinpath(out, env.ptr, "git");
63-
64-
if (error == GIT_ENOTFOUND && (error = git__getenv(&env, "HOME")) == 0)
65-
error = git_buf_joinpath(out, env.ptr, ".config/git");
114+
uid_t uid, euid;
115+
116+
uid = getuid();
117+
euid = geteuid();
118+
119+
/*
120+
* In case we are running setuid, only look up passwd
121+
* directory of the effective user.
122+
*/
123+
if (uid == euid) {
124+
if ((error = git__getenv(&env, "XDG_CONFIG_HOME")) == 0)
125+
error = git_buf_joinpath(out, env.ptr, "git");
126+
127+
if (error == GIT_ENOTFOUND && (error = git__getenv(&env, "HOME")) == 0)
128+
error = git_buf_joinpath(out, env.ptr, ".config/git");
129+
} else {
130+
if ((error = get_passwd_home(&env, euid)) == 0)
131+
error = git_buf_joinpath(out, env.ptr, ".config/git");
132+
}
66133

67134
if (error == GIT_ENOTFOUND) {
68135
giterr_clear();

0 commit comments

Comments
 (0)