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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
diff --git a/include/git2/errors.h b/include/git2/errors.h
index aba6d75..a61964b 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 f202623..7562fc2 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);