summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-02-02 17:37:12 -0800
committerGitHub <noreply@github.com>2018-02-02 17:37:12 -0800
commit8abd514c270ba3b3fc42c6d5feefedc4cc65dd9b (patch)
tree13fc98625e3c150beab7b76c35b3ce713f532cca
parent2553cbe39eca5713f873c9e268461ad361d17a54 (diff)
parent0967459ebc9e57bb2a7373ce0d00361a16eebc55 (diff)
downloadlibgit2-8abd514c270ba3b3fc42c6d5feefedc4cc65dd9b.tar.gz
Merge pull request #4499 from pks-t/pks/setuid-config
sysdir: do not use environment in setuid case
-rw-r--r--src/sysdir.c81
1 files changed, 74 insertions, 7 deletions
diff --git a/src/sysdir.c b/src/sysdir.c
index 7480e82fd..509b23b82 100644
--- a/src/sysdir.c
+++ b/src/sysdir.c
@@ -13,6 +13,9 @@
#include <ctype.h>
#if GIT_WIN32
#include "win32/findfile.h"
+#else
+#include <unistd.h>
+#include <pwd.h>
#endif
static int git_sysdir_guess_programdata_dirs(git_buf *out)
@@ -34,12 +37,63 @@ static int git_sysdir_guess_system_dirs(git_buf *out)
#endif
}
+#ifndef GIT_WIN32
+static int get_passwd_home(git_buf *out, uid_t uid)
+{
+ struct passwd pwd, *pwdptr;
+ char *buf = NULL;
+ long buflen;
+ int error;
+
+ assert(out);
+
+ if ((buflen = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
+ buflen = 1024;
+
+ do {
+ buf = git__realloc(buf, buflen);
+ error = getpwuid_r(uid, &pwd, buf, buflen, &pwdptr);
+ buflen *= 2;
+ } while (error == ERANGE && buflen <= 8192);
+
+ if (error) {
+ giterr_set(GITERR_OS, "failed to get passwd entry");
+ goto out;
+ }
+
+ if (!pwdptr) {
+ giterr_set(GITERR_OS, "no passwd entry found for user");
+ goto out;
+ }
+
+ if ((error = git_buf_puts(out, pwdptr->pw_dir)) < 0)
+ goto out;
+
+out:
+ git__free(buf);
+ return error;
+}
+#endif
+
static int git_sysdir_guess_global_dirs(git_buf *out)
{
#ifdef GIT_WIN32
return git_win32__find_global_dirs(out);
#else
- int error = git__getenv(out, "HOME");
+ int error;
+ uid_t uid, euid;
+
+ uid = getuid();
+ euid = geteuid();
+
+ /*
+ * In case we are running setuid, use the configuration
+ * of the effective user.
+ */
+ if (uid == euid)
+ error = git__getenv(out, "HOME");
+ else
+ error = get_passwd_home(out, euid);
if (error == GIT_ENOTFOUND) {
giterr_clear();
@@ -57,12 +111,25 @@ static int git_sysdir_guess_xdg_dirs(git_buf *out)
#else
git_buf env = GIT_BUF_INIT;
int error;
-
- if ((error = git__getenv(&env, "XDG_CONFIG_HOME")) == 0)
- error = git_buf_joinpath(out, env.ptr, "git");
-
- if (error == GIT_ENOTFOUND && (error = git__getenv(&env, "HOME")) == 0)
- error = git_buf_joinpath(out, env.ptr, ".config/git");
+ uid_t uid, euid;
+
+ uid = getuid();
+ euid = geteuid();
+
+ /*
+ * In case we are running setuid, only look up passwd
+ * directory of the effective user.
+ */
+ if (uid == euid) {
+ if ((error = git__getenv(&env, "XDG_CONFIG_HOME")) == 0)
+ error = git_buf_joinpath(out, env.ptr, "git");
+
+ if (error == GIT_ENOTFOUND && (error = git__getenv(&env, "HOME")) == 0)
+ error = git_buf_joinpath(out, env.ptr, ".config/git");
+ } else {
+ if ((error = get_passwd_home(&env, euid)) == 0)
+ error = git_buf_joinpath(out, env.ptr, ".config/git");
+ }
if (error == GIT_ENOTFOUND) {
giterr_clear();