summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2022-04-11 09:56:26 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2022-04-11 22:15:45 -0400
commitc0dfd1ad973eaf0ca41e787d696745c02412a2bb (patch)
tree8396b105c73e07096890eaf4c2dcc339b13fb277
parentbf2620bcefa64e9c0c28621d9ea7c16e5a40c61b (diff)
downloadlibgit2-c0dfd1ad973eaf0ca41e787d696745c02412a2bb.tar.gz
repo: ensure that repo dir is owned by current user
Ensure that the repository directory is owned by the current user; this prevents us from opening configuration files that may have been created by an attacker.
-rw-r--r--include/git2/errors.h3
-rw-r--r--src/libgit2/repository.c31
2 files changed, 30 insertions, 4 deletions
diff --git a/include/git2/errors.h b/include/git2/errors.h
index aba6d75e3..a61964bbb 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -57,7 +57,8 @@ typedef enum {
GIT_RETRY = -32, /**< Internal only */
GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
GIT_EINDEXDIRTY = -34, /**< Unsaved changes in the index would be overwritten */
- GIT_EAPPLYFAIL = -35 /**< Patch application failed */
+ GIT_EAPPLYFAIL = -35, /**< Patch application failed */
+ GIT_EOWNER = -36 /**< The object is not owned by the current user */
} git_error_code;
/**
diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c
index f202623d6..7562fc2af 100644
--- a/src/libgit2/repository.c
+++ b/src/libgit2/repository.c
@@ -483,6 +483,23 @@ static int read_gitfile(git_str *path_out, const char *file_path)
return error;
}
+static int validate_ownership(const char *repo_path)
+{
+ bool is_safe;
+ int error;
+
+ if ((error = git_fs_path_owner_is_current_user(&is_safe, repo_path)) < 0)
+ return (error == GIT_ENOTFOUND) ? 0 : error;
+
+ if (is_safe)
+ return 0;
+
+ git_error_set(GIT_ERROR_CONFIG,
+ "repository path '%s' is not owned by current user",
+ repo_path);
+ return GIT_EOWNER;
+}
+
static int find_repo(
git_str *gitdir_path,
git_str *workdir_path,
@@ -856,6 +873,7 @@ int git_repository_open_ext(
gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
git_repository *repo = NULL;
git_config *config = NULL;
+ const char *validation_path;
int version = 0;
if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
@@ -904,16 +922,23 @@ int git_repository_open_ext(
if ((error = check_extensions(config, version)) < 0)
goto cleanup;
- if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
+ if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
repo->is_bare = 1;
- else {
-
+ } else {
if (config &&
((error = load_config_data(repo, config)) < 0 ||
(error = load_workdir(repo, config, &workdir)) < 0))
goto cleanup;
}
+ /*
+ * Ensure that the git directory is owned by the current user.
+ */
+ validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
+
+ if ((error = validate_ownership(validation_path)) < 0)
+ goto cleanup;
+
cleanup:
git_str_dispose(&gitdir);
git_str_dispose(&workdir);