Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b45219f
Implement custom thread local storage for user of library
implausible Mar 29, 2021
7a76a33
checkout: cleanup duplication in checkout_create_the_new
implausible Aug 12, 2020
07493cc
thread checkout: move checkout buffers to tls
implausible Mar 29, 2021
e1a1eaa
thread checkout: add locks around shared state
implausible Aug 12, 2020
dc4e588
thread checkout: add locks around non thread-safe actions
implausible Apr 9, 2021
0739689
thread checkout: stub indirection for threading
implausible Aug 12, 2020
27f3c80
thread checkout: add threading to checkout_create_the_new
implausible Mar 29, 2021
37caa8d
meta: show build status for v1.3 branch
ethomson Feb 26, 2022
6b12762
online: test with https instead of git protocol
ethomson Jan 11, 2022
670415a
clone: update bitbucket tests
ethomson Mar 23, 2022
973d959
path: refactor ownership checks into current user and system
ethomson Apr 10, 2022
62d492d
repo: ensure that repo dir is owned by current user
ethomson Apr 11, 2022
e4eabb0
fs_path: mock ownership checks
ethomson Apr 12, 2022
caee92e
repo: test configuration ownership validation
ethomson Apr 11, 2022
f683806
repo: refactor global config loader function
ethomson Apr 11, 2022
eb8c3e5
repo: honor safe.directory during ownership checks
ethomson Apr 11, 2022
b58e905
repo: make ownership checks optional
ethomson Apr 12, 2022
a9eac6a
Merge pull request #6268 from libgit2/ethomson/ownership_13
ethomson Apr 12, 2022
1f39aac
meta: update version numbers for v1.3.1
ethomson Apr 12, 2022
23c24f8
meta: changelog for v1.3.1
ethomson Apr 12, 2022
1f5e7f9
Merge pull request #6271 from libgit2/ethomson/v1.3.1
ethomson Apr 12, 2022
6da6a10
Merge remote-tracking branch 'zawata/feature/custom-tls-for-external-…
zawata Apr 13, 2022
30d5c08
Merge remote-tracking branch 'zawata/multithread/checkout_create_the_…
zawata Apr 13, 2022
4b193b1
New checkout option: disabled_filters
julianmesa-gitkraken May 6, 2022
fe44f25
Merge branch 'disabled-filters-checkout' into libgit-next
ianhattendorf May 7, 2022
e78ee33
Fix degraded performance using GIT_USE_NSEC on repos cloned with GIT_…
julianmesa-gitkraken May 18, 2022
013d416
Merge pull request #7 from julianmesa-gitkraken/fix-nanoseconds-on-no…
ianhattendorf May 18, 2022
3ad710a
Fix the GIT_USE_NSEC performance fix
julianmesa-gitkraken May 26, 2022
4c98283
Merge pull request #8 from julianmesa-gitkraken/fix-nsecs-fix
ianhattendorf May 26, 2022
8254d2e
Do not add the .gitignore file if it not existing
julianmesa-gitkraken Jun 20, 2022
45f0e26
iterator: don't stat directories
julianmesa-gitkraken Jun 20, 2022
a4c112d
path: use fstatat instead of lstat
julianmesa-gitkraken Jun 20, 2022
110e29c
iterator: replace O(N) skip-to-start with O(log N)
julianmesa-gitkraken Jun 20, 2022
8bbbfab
push ignore frames lazily
julianmesa-gitkraken Jun 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.)
  • Loading branch information
ethomson committed Apr 12, 2022
commit eb8c3e5dabdeaeb51d8fea39545b4c0c9ddff07a
51 changes: 46 additions & 5 deletions src/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 load_global_config(git_config **config);

#define GIT_COMMONDIR_FILE "commondir"
#define GIT_GITDIR_FILE "gitdir"
Expand Down Expand Up @@ -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;
}

git_error_set(GIT_ERROR_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_dispose(&data.tmp);
return error;
}

static int find_repo(
Expand Down
102 changes: 102 additions & 0 deletions tests/repo/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_dispose(&config_path);
}

void test_repo_open__bare_empty_repo(void)
Expand Down Expand Up @@ -480,11 +490,103 @@ 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"));

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_dispose(&config_path);
git_buf_dispose(&config_filename);
git_buf_dispose(&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_dispose(&config_path);
git_buf_dispose(&config_filename);
git_buf_dispose(&config_data);
}