Merge branch 'safe.directory-and-windows'

These two patches made it into Git for Windows v2.35.2, but not into Git
v2.35.2.

Signed-off-by: Victoria Dye <vdye@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Victoria Dye
2022-04-12 11:25:04 -07:00
committed by Johannes Schindelin
3 changed files with 72 additions and 2 deletions

View File

@@ -40,3 +40,9 @@ which id the original user has.
If that is not what you would prefer and want git to only trust
repositories that are owned by root instead, then you can remove
the `SUDO_UID` variable from root's environment before invoking git.
+
Due to the permission model on Windows where ACLs are used instead of
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`.

View File

@@ -1,6 +1,7 @@
#include "../git-compat-util.h"
#include "win32.h"
#include <aclapi.h>
#include <sddl.h>
#include <conio.h>
#include <wchar.h>
#include "../strbuf.h"
@@ -2989,6 +2990,22 @@ static PSID get_current_user_sid(void)
return result;
}
static int acls_supported(const char *path)
{
size_t offset = offset_1st_component(path);
WCHAR wroot[MAX_PATH];
DWORD file_system_flags;
if (offset &&
xutftowcs_path_ex(wroot, path, MAX_PATH, offset,
MAX_PATH, 0) > 0 &&
GetVolumeInformationW(wroot, NULL, 0, NULL, NULL,
&file_system_flags, NULL, 0))
return !!(file_system_flags & FILE_PERSISTENT_ACLS);
return 0;
}
int is_path_owned_by_current_sid(const char *path)
{
WCHAR wpath[MAX_PATH];
@@ -3028,6 +3045,7 @@ int is_path_owned_by_current_sid(const char *path)
else if (sid && IsValidSid(sid)) {
/* Now, verify that the SID matches the current user's */
static PSID current_user_sid;
BOOL is_member;
if (!current_user_sid)
current_user_sid = get_current_user_sid();
@@ -3036,6 +3054,42 @@ int is_path_owned_by_current_sid(const char *path)
IsValidSid(current_user_sid) &&
EqualSid(sid, current_user_sid))
result = 1;
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
CheckTokenMembership(NULL, sid, &is_member) &&
is_member)
/*
* If owned by the Administrators group, and the
* current user is an administrator, we consider that
* okay, too.
*/
result = 1;
else if (IsWellKnownSid(sid, WinWorldSid) &&
git_env_bool("GIT_TEST_DEBUG_UNSAFE_DIRECTORIES", 0) &&
!acls_supported(path)) {
/*
* On FAT32 volumes, ownership is not actually recorded.
*/
warning("'%s' is on a file system that does not record ownership", path);
} else if (git_env_bool("GIT_TEST_DEBUG_UNSAFE_DIRECTORIES", 0)) {
LPSTR str1, str2, to_free1 = NULL, to_free2 = NULL;
if (ConvertSidToStringSidA(sid, &str1))
to_free1 = str1;
else
str1 = "(inconvertible)";
if (!current_user_sid)
str2 = "(none)";
else if (!IsValidSid(current_user_sid))
str2 = "(invalid)";
else if (ConvertSidToStringSidA(current_user_sid, &str2))
to_free2 = str2;
else
str2 = "(inconvertible)";
warning("'%s' is owned by:\n\t'%s'\nbut the current user is:\n\t'%s'", path, str1, str2);
LocalFree(to_free1);
LocalFree(to_free2);
}
}
/*

14
setup.c
View File

@@ -1433,13 +1433,23 @@ const char *setup_git_directory_gently(int *nongit_ok)
case GIT_DIR_INVALID_OWNERSHIP:
if (!nongit_ok) {
struct strbuf quoted = STRBUF_INIT;
struct strbuf hint = STRBUF_INIT;
#ifdef __MINGW32__
if (!git_env_bool("GIT_TEST_DEBUG_UNSAFE_DIRECTORIES", 0))
strbuf_addstr(&hint,
_("\n\nSet the environment variable "
"GIT_TEST_DEBUG_UNSAFE_DIRECTORIES=true "
"and run\n"
"again for more information."));
#endif
sq_quote_buf_pretty(&quoted, dir.buf);
die(_("detected dubious ownership in repository at '%s'\n"
"To add an exception for this directory, call:\n"
"\n"
"\tgit config --global --add safe.directory %s"),
dir.buf, quoted.buf);
"\tgit config --global --add safe.directory %s%s"),
dir.buf, quoted.buf, hint.buf);
}
*nongit_ok = 1;
break;