From c0dfd1ad973eaf0ca41e787d696745c02412a2bb Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 11 Apr 2022 09:56:26 -0400 Subject: 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. --- include/git2/errors.h | 3 ++- src/libgit2/repository.c | 31 ++++++++++++++++++++++++++++--- 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); -- cgit v1.2.1