From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH 1/2] mingw: special-case administrators even more
Date: Tue, 25 Mar 2025 10:38:29 +0000 [thread overview]
Message-ID: <90aec0788d075e11ae81fe192a2ac6a3b73728e5.1742899110.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1893.git.1742899110.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
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>
---
compat/mingw.c | 39 ++++++++++++++++++++++++++++-----------
1 file changed, 28 insertions(+), 11 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index f524c54d06d..305a999f1fc 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2826,31 +2826,44 @@ static void setup_windows_environment(void)
}
}
-static PSID get_current_user_sid(void)
+static void get_current_user_sid(PSID *sid, HANDLE *linked_token)
{
HANDLE token;
DWORD len = 0;
- PSID result = NULL;
+ TOKEN_ELEVATION_TYPE elevationType;
+ DWORD size;
+
+ *sid = NULL;
+ *linked_token = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
- return NULL;
+ return;
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
TOKEN_USER *info = xmalloc((size_t)len);
if (GetTokenInformation(token, TokenUser, info, len, &len)) {
len = GetLengthSid(info->User.Sid);
- result = xmalloc(len);
- if (!CopySid(len, result, info->User.Sid)) {
+ *sid = xmalloc(len);
+ if (!CopySid(len, *sid, info->User.Sid)) {
error(_("failed to copy SID (%ld)"),
GetLastError());
- FREE_AND_NULL(result);
+ FREE_AND_NULL(*sid);
}
}
FREE_AND_NULL(info);
}
- CloseHandle(token);
- return result;
+ if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &size) &&
+ elevationType == TokenElevationTypeLimited) {
+ /*
+ * The current process is run by a member of the Administrators
+ * group, but is not running elevated.
+ */
+ if (!GetTokenInformation(token, TokenLinkedToken, linked_token, sizeof(*linked_token), &size))
+ linked_token = NULL; /* there is no linked token */
+ }
+
+ CloseHandle(token);
}
static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
@@ -2931,18 +2944,22 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
else if (sid && IsValidSid(sid)) {
/* Now, verify that the SID matches the current user's */
static PSID current_user_sid;
+ static HANDLE linked_token;
BOOL is_member;
if (!current_user_sid)
- current_user_sid = get_current_user_sid();
+ get_current_user_sid(¤t_user_sid, &linked_token);
if (current_user_sid &&
IsValidSid(current_user_sid) &&
EqualSid(sid, current_user_sid))
result = 1;
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
- CheckTokenMembership(NULL, sid, &is_member) &&
- is_member)
+ ((CheckTokenMembership(NULL, sid, &is_member) &&
+ is_member) ||
+ (linked_token &&
+ CheckTokenMembership(linked_token, sid, &is_member) &&
+ is_member)))
/*
* If owned by the Administrators group, and the
* current user is an administrator, we consider that
--
gitgitgadget
next prev parent reply other threads:[~2025-03-25 10:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-25 10:38 [PATCH 0/2] mingw: special-case administrators even more Johannes Schindelin via GitGitGadget
2025-03-25 10:38 ` Johannes Schindelin via GitGitGadget [this message]
2025-03-25 10:38 ` [PATCH 2/2] test-tool path-utils: support debugging "dubious ownership" issues Johannes Schindelin via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=90aec0788d075e11ae81fe192a2ac6a3b73728e5.1742899110.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).