diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt index 9e57855f27c799..57ef566a3f735f 100644 --- a/Documentation/config/safe.txt +++ b/Documentation/config/safe.txt @@ -25,3 +25,10 @@ Unix' simpler permission model, it can be a bit tricky to figure out why a directory is considered unsafe. To help with this, Git will provide more detailed information when the environment variable `GIT_TEST_DEBUG_UNSAFE_DIRECTORIES` is set to `true`. ++ +To completely opt-out of this security check, set `safe.directory` to the +string `*`. This will allow all repositories to be treated as if their +directory was listed in the `safe.directory` list. If `safe.directory=*` +is set in system config and you want to re-enable this protection, then +initialize your list with an empty value before listing the repositories +that you deem safe. diff --git a/compat/mingw.c b/compat/mingw.c index ea34ec5f6d2490..f3acdc57ad1538 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -3509,9 +3509,7 @@ int is_path_owned_by_current_sid(const char *path) DACL_SECURITY_INFORMATION, &sid, NULL, NULL, NULL, &descriptor); - if (err != ERROR_SUCCESS) - error(_("failed to get owner for '%s' (%ld)"), path, err); - else if (sid && IsValidSid(sid)) { + if (err == ERROR_SUCCESS && sid && IsValidSid(sid)) { /* Now, verify that the SID matches the current user's */ static PSID current_user_sid; BOOL is_member; diff --git a/setup.c b/setup.c index c8f67bfed5206f..3f66dd5173ae03 100644 --- a/setup.c +++ b/setup.c @@ -1100,9 +1100,14 @@ static int safe_directory_cb(const char *key, const char *value, void *d) { struct safe_directory_data *data = d; - if (!value || !*value) + if (strcmp(key, "safe.directory")) + return 0; + + if (!value || !*value) { data->is_safe = 0; - else { + } else if (!strcmp(value, "*")) { + data->is_safe = 1; + } else { const char *interpolated = NULL; if (!git_config_pathname(&interpolated, key, value) && @@ -1119,7 +1124,8 @@ static int ensure_valid_ownership(const char *path) { struct safe_directory_data data = { .path = path }; - if (is_path_owned_by_current_user(path)) + if (is_path_owned_by_current_user(path) && + !git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0)) return 1; read_very_early_config(safe_directory_cb, &data); @@ -1368,9 +1374,17 @@ const char *setup_git_directory_gently(int *nongit_ok) break; case GIT_DIR_INVALID_OWNERSHIP: if (!nongit_ok) { + struct strbuf prequoted = STRBUF_INIT; struct strbuf quoted = STRBUF_INIT; - sq_quote_buf_pretty("ed, dir.buf); +#ifdef __MINGW32__ + if (dir.buf[0] == '/') + strbuf_addstr(&prequoted, "%(prefix)/"); +#endif + + strbuf_add(&prequoted, dir.buf, dir.len); + sq_quote_buf_pretty("ed, prequoted.buf); + die(_("unsafe repository ('%s' is owned by someone else)\n" "To add an exception for this directory, call:\n" "\n" diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh new file mode 100755 index 00000000000000..239d93f4d21141 --- /dev/null +++ b/t/t0033-safe-directory.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +test_description='verify safe.directory checks' + +. ./test-lib.sh + +GIT_TEST_ASSUME_DIFFERENT_OWNER=1 +export GIT_TEST_ASSUME_DIFFERENT_OWNER + +expect_rejected_dir () { + test_must_fail git status 2>err && + grep "safe.directory" err +} + +test_expect_success 'safe.directory is not set' ' + expect_rejected_dir +' + +test_expect_success 'safe.directory does not match' ' + git config --global safe.directory bogus && + expect_rejected_dir +' + +test_expect_success 'path exist as different key' ' + git config --global foo.bar "$(pwd)" && + expect_rejected_dir +' + +test_expect_success 'safe.directory matches' ' + git config --global --add safe.directory "$(pwd)" && + git status +' + +test_expect_success 'safe.directory matches, but is reset' ' + git config --global --add safe.directory "" && + expect_rejected_dir +' + +test_expect_success 'safe.directory=*' ' + git config --global --add safe.directory "*" && + git status +' + +test_expect_success 'safe.directory=*, but is reset' ' + git config --global --add safe.directory "" && + expect_rejected_dir +' + +test_done