Skip to content

Commit 51a8889

Browse files
committed
mingw: special-case administrators even more
The check for dubious ownership has one particular quirk on Windows: if running as an administrator, files owned by the Administrators _group_ are considered owned by the user. The rationale for that is: When running in elevated mode, Git creates files that aren't owned by the individual user but by the Administrators group. There is yet another quirk, though: The check I introduced to determine whether the current user is an administrator uses the `CheckTokenMembership()` function with the current process token. And that check only succeeds when running in elevated mode! Let's be a bit more lenient here and look harder whether the current user is an administrator. We do this by looking for a so-called "linked token". That token exists when administrators run in non-elevated mode, and can be used to create a new process in elevated mode. And feeding _that_ token to the `CheckTokenMembership()` function succeeds! Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 58f679d commit 51a8889

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

compat/mingw.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3717,31 +3717,44 @@ static void setup_windows_environment(void)
37173717
has_symlinks = 0;
37183718
}
37193719

3720-
static PSID get_current_user_sid(void)
3720+
static void get_current_user_sid(PSID *sid, HANDLE *linked_token)
37213721
{
37223722
HANDLE token;
37233723
DWORD len = 0;
3724-
PSID result = NULL;
3724+
TOKEN_ELEVATION_TYPE elevationType;
3725+
DWORD size;
3726+
3727+
*sid = NULL;
3728+
*linked_token = NULL;
37253729

37263730
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
3727-
return NULL;
3731+
return;
37283732

37293733
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
37303734
TOKEN_USER *info = xmalloc((size_t)len);
37313735
if (GetTokenInformation(token, TokenUser, info, len, &len)) {
37323736
len = GetLengthSid(info->User.Sid);
3733-
result = xmalloc(len);
3734-
if (!CopySid(len, result, info->User.Sid)) {
3737+
*sid = xmalloc(len);
3738+
if (!CopySid(len, *sid, info->User.Sid)) {
37353739
error(_("failed to copy SID (%ld)"),
37363740
GetLastError());
3737-
FREE_AND_NULL(result);
3741+
FREE_AND_NULL(*sid);
37383742
}
37393743
}
37403744
FREE_AND_NULL(info);
37413745
}
3742-
CloseHandle(token);
37433746

3744-
return result;
3747+
if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &size) &&
3748+
elevationType == TokenElevationTypeLimited) {
3749+
/*
3750+
* The current process is run by a member of the Administrators
3751+
* group, but is not running elevated.
3752+
*/
3753+
if (!GetTokenInformation(token, TokenLinkedToken, linked_token, sizeof(*linked_token), &size))
3754+
linked_token = NULL; /* there is no linked token */
3755+
}
3756+
3757+
CloseHandle(token);
37453758
}
37463759

37473760
static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
@@ -3820,18 +3833,22 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
38203833
if (err == ERROR_SUCCESS && sid && IsValidSid(sid)) {
38213834
/* Now, verify that the SID matches the current user's */
38223835
static PSID current_user_sid;
3836+
static HANDLE linked_token;
38233837
BOOL is_member;
38243838

38253839
if (!current_user_sid)
3826-
current_user_sid = get_current_user_sid();
3840+
get_current_user_sid(&current_user_sid, &linked_token);
38273841

38283842
if (current_user_sid &&
38293843
IsValidSid(current_user_sid) &&
38303844
EqualSid(sid, current_user_sid))
38313845
result = 1;
38323846
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
3833-
CheckTokenMembership(NULL, sid, &is_member) &&
3834-
is_member)
3847+
((CheckTokenMembership(NULL, sid, &is_member) &&
3848+
is_member) ||
3849+
(linked_token &&
3850+
CheckTokenMembership(linked_token, sid, &is_member) &&
3851+
is_member)))
38353852
/*
38363853
* If owned by the Administrators group, and the
38373854
* current user is an administrator, we consider that

0 commit comments

Comments
 (0)