Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15:Update
libgit2.25920
0019-repo-validate-gitdir-and-gitlink-ownership...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0019-repo-validate-gitdir-and-gitlink-ownership.patch of Package libgit2.25920
From 2e4ea7b7fb593dea0b96e3bca659c3594e7fe734 Mon Sep 17 00:00:00 2001 From: Edward Thomson <ethomson@edwardthomson.com> Date: Sat, 2 Jul 2022 10:19:33 -0400 Subject: [PATCH 19/20] repo: validate gitdir and gitlink ownership To match git's behavior with CVE 2022-29187, validate not only the working directory, but also the gitdir and gitlink (if it exists). This a follow up to CVE-2022-24765 that was fixed earlier. --- src/repository.c | 107 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/src/repository.c b/src/repository.c index e770aa961..ac32085da 100644 --- a/src/repository.c +++ b/src/repository.c @@ -487,7 +487,7 @@ static int read_gitfile(git_buf *path_out, const char *file_path) typedef struct { const char *repo_path; git_buf tmp; - bool is_safe; + bool *is_safe; } validate_ownership_data; static int validate_ownership_cb(const git_config_entry *entry, void *payload) @@ -495,52 +495,101 @@ 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; + *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; + *data->is_safe = true; return 0; } -static int validate_ownership(const char *repo_path) +static int validate_ownership_config(bool *is_safe, const char *path) +{ + validate_ownership_data ownership_data = { + path, GIT_BUF_INIT, is_safe + }; + git_config *config; + int error; + + if (load_global_config(&config) != 0) + return 0; + + error = git_config_get_multivar_foreach(config, + "safe.directory", NULL, + validate_ownership_cb, + &ownership_data); + + git_config_free(config); + git_buf_free(&ownership_data.tmp); + + return error; +} + +static int validate_ownership_path(bool *is_safe, const char *path) { - git_config *config = NULL; - validate_ownership_data data = { repo_path, GIT_BUF_INIT, false }; git_path_owner_t owner_level = GIT_PATH_OWNER_CURRENT_USER | GIT_PATH_USER_IS_ADMINISTRATOR; - bool is_safe; - int error; - - if ((error = git_path_owner_is(&is_safe, repo_path, owner_level)) < 0) { - if (error == GIT_ENOTFOUND) - error = 0; + int error = 0; - goto done; - } + if (path) + error = git_path_owner_is(is_safe, path, owner_level); - if (is_safe) { + if (error == GIT_ENOTFOUND) { + *is_safe = true; error = 0; - goto done; } - if (load_global_config(&config) == 0) { - error = git_config_get_multivar_foreach(config, "safe.directory", NULL, validate_ownership_cb, &data); + return error; +} + +static int validate_ownership(git_repository *repo) +{ + const char *validation_paths[3] = { NULL }, *path; + size_t validation_len = 0, i; + bool is_safe = false; + int error = 0; + + /* + * If there's a worktree, validate the permissions to it *and* + * the git directory, and use the worktree as the configuration + * key for allowlisting the directory. In a bare setup, only + * look at the gitdir and use that as the allowlist. So we + * examine all `validation_paths` but use only the first as + * the configuration lookup. + */ + + if (repo->workdir) + validation_paths[validation_len++] = repo->workdir; - if (!error && data.is_safe) + if (repo->gitlink) + validation_paths[validation_len++] = repo->gitlink; + + validation_paths[validation_len++] = repo->gitdir; + + for (i = 0; i < validation_len; i++) { + path = validation_paths[i]; + + if ((error = validate_ownership_path(&is_safe, path)) < 0) goto done; + + if (!is_safe) + break; } #- giterr_set(GIT_ERROR_CONFIG, - giterr_set(GITERR_CONFIG, - "repository path '%s' is not owned by current user", - repo_path); - error = GIT_EOWNER; + if (is_safe || + (error = validate_ownership_config(&is_safe, validation_paths[0])) < 0) + goto done; + + if (!is_safe) { #+ giterr_set(GIT_ERROR_CONFIG, + giterr_set(GITERR_CONFIG, + "repository path '%s' is not owned by current user", + path); + error = GIT_EOWNER; + } done: - git_config_free(config); - git_buf_free(&data.tmp); return error; } @@ -917,7 +966,6 @@ int git_repository_open_ext( gitlink = GIT_BUF_INIT, commondir = GIT_BUF_INIT; git_repository *repo = NULL; git_config *config = NULL; - const char *validation_path; if (flags & GIT_REPOSITORY_OPEN_FROM_ENV) return _git_repository_open_ext_from_env(repo_ptr, start_path); # int version = 0; # # if (flags & GIT_REPOSITORY_OPEN_FROM_ENV) @@ -976,12 +1024,11 @@ int git_repository_open_ext( } /* - * Ensure that the git directory is owned by the current user. + * Ensure that the git directory and worktree are + * owned by the current user. */ - validation_path = repo->is_bare ? repo->gitdir : repo->workdir; - if (git_repository__validate_ownership && - (error = validate_ownership(validation_path)) < 0) + (error = validate_ownership(repo)) < 0) goto cleanup; cleanup: -- 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