Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
libgit2
0006-repo-honor-safe.directory-during-ownership...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0006-repo-honor-safe.directory-during-ownership-checks.patch of Package libgit2
From eb8c3e5dabdeaeb51d8fea39545b4c0c9ddff07a Mon Sep 17 00:00:00 2001 From: Edward Thomson <ethomson@edwardthomson.com> Date: Mon, 11 Apr 2022 15:18:44 -0400 Subject: [PATCH 06/20] repo: honor safe.directory during ownership checks Obey the `safe.directory` configuration variable if it is set in the global or system configuration. (Do not try to load this from the repository configuration - to avoid malicious repositories that then mark themselves as safe.) --- src/repository.c | 51 ++++++++++++++++++++--- tests/repo/open.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 5 deletions(-) diff --git a/src/repository.c b/src/repository.c index e8ea1e75c..ac2581167 100644 --- a/src/repository.c +++ b/src/repository.c @@ -64,6 +64,7 @@ static const struct { # # static int check_repositoryformatversion(int *version, git_config *config); # static int check_extensions(git_config *config, int version); }; static int check_repositoryformatversion(git_config *config); +static int load_global_config(git_config **config); #define GIT_COMMONDIR_FILE "commondir" #define GIT_GITDIR_FILE "gitdir" @@ -482,21 +483,61 @@ static int read_gitfile(git_buf *path_out, const char *file_path) return error; } +typedef struct { + const char *repo_path; + git_buf tmp; + bool is_safe; +} validate_ownership_data; + +static int validate_ownership_cb(const git_config_entry *entry, void *payload) +{ + validate_ownership_data *data = payload; + + if (strcmp(entry->value, "") == 0) + data->is_safe = false; + + if (git_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 && + strcmp(data->tmp.ptr, data->repo_path) == 0) + data->is_safe = true; + + return 0; +} + static int validate_ownership(const char *repo_path) { + git_config *config = NULL; + validate_ownership_data data = { repo_path, GIT_BUF_INIT, false }; bool is_safe; int error; - if ((error = git_path_owner_is_current_user(&is_safe, repo_path)) < 0) - return (error == GIT_ENOTFOUND) ? 0 : error; + if ((error = git_path_owner_is_current_user(&is_safe, repo_path)) < 0) { + if (error == GIT_ENOTFOUND) + error = 0; - if (is_safe) - return 0; + goto done; + } + + if (is_safe) { + error = 0; + goto done; + } + + if (load_global_config(&config) == 0) { + error = git_config_get_multivar_foreach(config, "safe.directory", NULL, validate_ownership_cb, &data); + + if (!error && data.is_safe) + goto done; + } # giterr_set(GIT_ERROR_CONFIG, giterr_set(GITERR_CONFIG, "repository path '%s' is not owned by current user", repo_path); - return GIT_EOWNER; + error = GIT_EOWNER; + +done: + git_config_free(config); + git_buf_free(&data.tmp); + return error; } static int find_repo( diff --git a/tests/repo/open.c b/tests/repo/open.c index c7e7a4ccf..f23ba1c18 100644 --- a/tests/repo/open.c +++ b/tests/repo/open.c @@ -3,16 +3,26 @@ #include "sysdir.h" #include <ctype.h> +static git_buf config_path = GIT_BUF_INIT; + +void test_repo_open__initialize(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &config_path)); +} void test_repo_open__cleanup(void) { cl_git_sandbox_cleanup(); cl_fixture_cleanup("empty_standard_repo"); + cl_fixture_cleanup("__global_config"); if (git_path_isdir("alternate")) git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES); git_path__set_owner(GIT_PATH_MOCK_OWNER_NONE); + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr)); + git_buf_free(&config_path); } void test_repo_open__bare_empty_repo(void) @@ -480,6 +490,9 @@ void test_repo_open__validates_dir_ownership(void) void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void) { git_repository *repo; + git_buf config_path = GIT_BUF_INIT, + config_filename = GIT_BUF_INIT, + config_data = GIT_BUF_INIT; cl_fixture_sandbox("empty_standard_repo"); cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); @@ -487,4 +500,93 @@ void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void) git_path__set_owner(GIT_PATH_MOCK_OWNER_OTHER); cl_git_fail(git_repository_open(&repo, "empty_standard_repo")); + /* Add safe.directory options to the global configuration */ + git_buf_joinpath(&config_path, clar_sandbox_path(), "__global_config"); + cl_must_pass(p_mkdir(config_path.ptr, 0777)); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr); + + git_buf_joinpath(&config_filename, config_path.ptr, ".gitconfig"); + + git_buf_printf(&config_data, + "[foo]\n" \ + "\tbar = Foobar\n" \ + "\tbaz = Baz!\n" \ + "[safe]\n" \ + "\tdirectory = /non/existent/path\n" \ + "\tdirectory = /\n" \ + "\tdirectory = c:\\\\temp\n" \ + "\tdirectory = %s/%s\n" \ + "\tdirectory = /tmp\n" \ + "[bar]\n" \ + "\tfoo = barfoo\n", + clar_sandbox_path(), "empty_standard_repo"); + cl_git_rewritefile(config_filename.ptr, config_data.ptr); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository_free(repo); + + git_buf_free(&config_path); + git_buf_free(&config_filename); + git_buf_free(&config_data); +} + +void test_repo_open__can_reset_safe_directory_list(void) +{ + git_repository *repo; + git_buf config_path = GIT_BUF_INIT, + config_filename = GIT_BUF_INIT, + config_data = GIT_BUF_INIT; + + cl_fixture_sandbox("empty_standard_repo"); + cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); + + git_path__set_owner(GIT_PATH_MOCK_OWNER_OTHER); + cl_git_fail(git_repository_open(&repo, "empty_standard_repo")); + + /* Add safe.directory options to the global configuration */ + git_buf_joinpath(&config_path, clar_sandbox_path(), "__global_config"); + cl_must_pass(p_mkdir(config_path.ptr, 0777)); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr); + + git_buf_joinpath(&config_filename, config_path.ptr, ".gitconfig"); + + /* The blank resets our sandbox directory and opening fails */ + + git_buf_printf(&config_data, + "[foo]\n" \ + "\tbar = Foobar\n" \ + "\tbaz = Baz!\n" \ + "[safe]\n" \ + "\tdirectory = %s/%s\n" \ + "\tdirectory = \n" \ + "\tdirectory = /tmp\n" \ + "[bar]\n" \ + "\tfoo = barfoo\n", + clar_sandbox_path(), "empty_standard_repo"); + cl_git_rewritefile(config_filename.ptr, config_data.ptr); + + cl_git_fail(git_repository_open(&repo, "empty_standard_repo")); + + /* The blank resets tmp and allows subsequent declarations to succeed */ + + git_buf_clear(&config_data); + git_buf_printf(&config_data, + "[foo]\n" \ + "\tbar = Foobar\n" \ + "\tbaz = Baz!\n" \ + "[safe]\n" \ + "\tdirectory = /tmp\n" \ + "\tdirectory = \n" \ + "\tdirectory = %s/%s\n" \ + "[bar]\n" \ + "\tfoo = barfoo\n", + clar_sandbox_path(), "empty_standard_repo"); + cl_git_rewritefile(config_filename.ptr, config_data.ptr); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository_free(repo); + + git_buf_free(&config_path); + git_buf_free(&config_filename); + git_buf_free(&config_data); } -- 2.37.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor