safe.directory: allow "lead/ing/path/*" match
When safe.directory was introduced in v2.30.3 timeframe,8959555c
(setup_git_directory(): add an owner check for the top-level directory, 2022-03-02), it only allowed specific opt-out directories. Immediately after an embargoed release that included the change,0f85c4a3
(setup: opt-out of check with safe.directory=*, 2022-04-13) was done as a response to loosen the check so that a single '*' can be used to say "I trust all repositories" for folks who host too many repositories to list individually. Let's further loosen the check to allow people to say "everything under this hierarchy is deemed safe" by specifying such a leading directory with "/*" appended to it. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@ -44,7 +44,8 @@ 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.
|
||||
that you deem safe. Giving a directory with `/*` appended to it will
|
||||
allow access to all repositories under the named directory.
|
||||
+
|
||||
As explained, Git only allows you to access repositories owned by
|
||||
yourself, i.e. the user who is running Git, by default. When Git
|
||||
|
20
setup.c
20
setup.c
@ -1176,13 +1176,21 @@ static int safe_directory_cb(const char *key, const char *value,
|
||||
} else if (!strcmp(value, "*")) {
|
||||
data->is_safe = 1;
|
||||
} else {
|
||||
const char *interpolated = NULL;
|
||||
const char *allowed = NULL;
|
||||
|
||||
if (!git_config_pathname(&interpolated, key, value) &&
|
||||
!fspathcmp(data->path, interpolated ? interpolated : value))
|
||||
data->is_safe = 1;
|
||||
|
||||
free((char *)interpolated);
|
||||
if (!git_config_pathname(&allowed, key, value)) {
|
||||
if (!allowed)
|
||||
allowed = value;
|
||||
if (ends_with(allowed, "/*")) {
|
||||
size_t len = strlen(allowed);
|
||||
if (!fspathncmp(allowed, data->path, len - 1))
|
||||
data->is_safe = 1;
|
||||
} else if (!fspathcmp(data->path, allowed)) {
|
||||
data->is_safe = 1;
|
||||
}
|
||||
}
|
||||
if (allowed != value)
|
||||
free((char *)allowed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -71,7 +71,22 @@ test_expect_success 'safe.directory=*, but is reset' '
|
||||
expect_rejected_dir
|
||||
'
|
||||
|
||||
test_expect_success 'safe.directory with matching glob' '
|
||||
git config --global --unset-all safe.directory &&
|
||||
p=$(pwd) &&
|
||||
git config --global safe.directory "${p%/*}/*" &&
|
||||
git status
|
||||
'
|
||||
|
||||
test_expect_success 'safe.directory with unmatching glob' '
|
||||
git config --global --unset-all safe.directory &&
|
||||
p=$(pwd) &&
|
||||
git config --global safe.directory "${p%/*}no/*" &&
|
||||
expect_rejected_dir
|
||||
'
|
||||
|
||||
test_expect_success 'safe.directory in included file' '
|
||||
git config --global --unset-all safe.directory &&
|
||||
cat >gitconfig-include <<-EOF &&
|
||||
[safe]
|
||||
directory = "$(pwd)"
|
||||
|
Reference in New Issue
Block a user