repo: make ownership checks optional Introduce the `GIT_OPT_SET_OWNER_VALIDATION` option, so that users can disable repository ownership validation.
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
diff --git a/include/git2/common.h b/include/git2/common.h
index 52000e8..c3e3e7b 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -225,7 +225,9 @@ typedef enum {
GIT_OPT_SET_ODB_PACKED_PRIORITY,
GIT_OPT_SET_ODB_LOOSE_PRIORITY,
GIT_OPT_GET_EXTENSIONS,
- GIT_OPT_SET_EXTENSIONS
+ GIT_OPT_SET_EXTENSIONS,
+ GIT_OPT_GET_OWNER_VALIDATION,
+ GIT_OPT_SET_OWNER_VALIDATION
} git_libgit2_opt_t;
/**
@@ -463,6 +465,14 @@ typedef enum {
* > to support repositories with the `noop` extension but does want
* > to support repositories with the `newext` extension.
*
+ * opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled)
+ * > Gets the owner validation setting for repository
+ * > directories.
+ *
+ * opts(GIT_OPT_SET_OWNER_VALIDATION, int enabled)
+ * > Set that repository directories should be owned by the current
+ * > user. The default is to validate ownership.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c
index efad3bf..2fda072 100644
--- a/src/libgit2/libgit2.c
+++ b/src/libgit2/libgit2.c
@@ -406,6 +406,14 @@ int git_libgit2_opts(int key, ...)
}
break;
+ case GIT_OPT_GET_OWNER_VALIDATION:
+ *(va_arg(ap, int *)) = git_repository__validate_ownership;
+ break;
+
+ case GIT_OPT_SET_OWNER_VALIDATION:
+ git_repository__validate_ownership = (va_arg(ap, int) != 0);
+ break;
+
default:
git_error_set(GIT_ERROR_INVALID, "invalid option key");
error = -1;
diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c
index 89fad82..48a0b70 100644
--- a/src/libgit2/repository.c
+++ b/src/libgit2/repository.c
@@ -39,6 +39,7 @@
# include "win32/w32_util.h"
#endif
+bool git_repository__validate_ownership = true;
bool git_repository__fsync_gitdir = false;
static const struct {
@@ -977,7 +978,8 @@ int git_repository_open_ext(
*/
validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
- if ((error = validate_ownership(validation_path)) < 0)
+ if (git_repository__validate_ownership &&
+ (error = validate_ownership(validation_path)) < 0)
goto cleanup;
cleanup:
diff --git a/src/libgit2/repository.h b/src/libgit2/repository.h
index 3c3aa1e..a488f2b 100644
--- a/src/libgit2/repository.h
+++ b/src/libgit2/repository.h
@@ -34,6 +34,7 @@
#define GIT_DIR_SHORTNAME "GIT~1"
extern bool git_repository__fsync_gitdir;
+extern bool git_repository__validate_ownership;
/** Cvar cache identifiers */
typedef enum {
diff --git a/tests/clar/clar_libgit2.c b/tests/clar/clar_libgit2.c
index 55a09d1..783b457 100644
--- a/tests/clar/clar_libgit2.c
+++ b/tests/clar/clar_libgit2.c
@@ -599,6 +599,11 @@ void cl_sandbox_set_search_path_defaults(void)
git_str_dispose(&path);
}
+void cl_sandbox_disable_ownership_validation(void)
+{
+ git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 0);
+}
+
#ifdef GIT_WIN32
bool cl_sandbox_supports_8dot3(void)
{
diff --git a/tests/clar/clar_libgit2.h b/tests/clar/clar_libgit2.h
index e3b7bd9..da3f415 100644
--- a/tests/clar/clar_libgit2.h
+++ b/tests/clar/clar_libgit2.h
@@ -222,6 +222,7 @@ void cl_fake_home(void);
void cl_fake_home_cleanup(void *);
void cl_sandbox_set_search_path_defaults(void);
+void cl_sandbox_disable_ownership_validation(void);
#ifdef GIT_WIN32
# define cl_msleep(x) Sleep(x)
diff --git a/tests/clar/main.c b/tests/clar/main.c
index 56751c2..d879073 100644
--- a/tests/clar/main.c
+++ b/tests/clar/main.c
@@ -26,6 +26,7 @@ int main(int argc, char *argv[])
cl_global_trace_register();
cl_sandbox_set_search_path_defaults();
+ cl_sandbox_disable_ownership_validation();
/* Run the test suite */
res = clar_test_run();
diff --git a/tests/libgit2/repo/open.c b/tests/libgit2/repo/open.c
index 7fe3668..4b6609a 100644
--- a/tests/libgit2/repo/open.c
+++ b/tests/libgit2/repo/open.c
@@ -3,11 +3,13 @@
#include "sysdir.h"
#include <ctype.h>
+static int validate_ownership = 0;
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));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_OWNER_VALIDATION, &validate_ownership));
}
void test_repo_open__cleanup(void)
@@ -23,6 +25,8 @@ void test_repo_open__cleanup(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr));
git_buf_dispose(&config_path);
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, validate_ownership));
}
void test_repo_open__bare_empty_repo(void)
@@ -470,6 +474,8 @@ void test_repo_open__validates_dir_ownership(void)
{
git_repository *repo;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
cl_fixture_sandbox("empty_standard_repo");
cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
@@ -494,6 +500,8 @@ void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
config_filename = GIT_STR_INIT,
config_data = GIT_STR_INIT;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
cl_fixture_sandbox("empty_standard_repo");
cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
@@ -537,6 +545,8 @@ void test_repo_open__can_reset_safe_directory_list(void)
config_filename = GIT_STR_INIT,
config_data = GIT_STR_INIT;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
cl_fixture_sandbox("empty_standard_repo");
cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));