Skip to content

Commit 10f9eab

Browse files
committed
Merge branch 'js/safe-directory-plus' into maint
Platform-specific code that determines if a directory is OK to use as a repository has been taught to report more details, especially on Windows. source: <[email protected]> * js/safe-directory-plus: mingw: handle a file owned by the Administrators group correctly mingw: be more informative when ownership check fails on FAT32 mingw: provide details about unsafe directories' ownership setup: prepare for more detailed "dubious ownership" messages setup: fix some formatting
2 parents 6283c1e + 3f7207e commit 10f9eab

File tree

4 files changed

+81
-15
lines changed

4 files changed

+81
-15
lines changed

compat/mingw.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "../git-compat-util.h"
22
#include "win32.h"
33
#include <aclapi.h>
4+
#include <sddl.h>
45
#include <conio.h>
56
#include <wchar.h>
67
#include "../strbuf.h"
@@ -2670,7 +2671,22 @@ static PSID get_current_user_sid(void)
26702671
return result;
26712672
}
26722673

2673-
int is_path_owned_by_current_sid(const char *path)
2674+
static int acls_supported(const char *path)
2675+
{
2676+
size_t offset = offset_1st_component(path);
2677+
WCHAR wroot[MAX_PATH];
2678+
DWORD file_system_flags;
2679+
2680+
if (offset &&
2681+
xutftowcsn(wroot, path, MAX_PATH, offset) > 0 &&
2682+
GetVolumeInformationW(wroot, NULL, 0, NULL, NULL,
2683+
&file_system_flags, NULL, 0))
2684+
return !!(file_system_flags & FILE_PERSISTENT_ACLS);
2685+
2686+
return 0;
2687+
}
2688+
2689+
int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
26742690
{
26752691
WCHAR wpath[MAX_PATH];
26762692
PSID sid = NULL;
@@ -2709,6 +2725,7 @@ int is_path_owned_by_current_sid(const char *path)
27092725
else if (sid && IsValidSid(sid)) {
27102726
/* Now, verify that the SID matches the current user's */
27112727
static PSID current_user_sid;
2728+
BOOL is_member;
27122729

27132730
if (!current_user_sid)
27142731
current_user_sid = get_current_user_sid();
@@ -2717,6 +2734,46 @@ int is_path_owned_by_current_sid(const char *path)
27172734
IsValidSid(current_user_sid) &&
27182735
EqualSid(sid, current_user_sid))
27192736
result = 1;
2737+
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
2738+
CheckTokenMembership(NULL, sid, &is_member) &&
2739+
is_member)
2740+
/*
2741+
* If owned by the Administrators group, and the
2742+
* current user is an administrator, we consider that
2743+
* okay, too.
2744+
*/
2745+
result = 1;
2746+
else if (report &&
2747+
IsWellKnownSid(sid, WinWorldSid) &&
2748+
!acls_supported(path)) {
2749+
/*
2750+
* On FAT32 volumes, ownership is not actually recorded.
2751+
*/
2752+
strbuf_addf(report, "'%s' is on a file system that does"
2753+
"not record ownership\n", path);
2754+
} else if (report) {
2755+
LPSTR str1, str2, to_free1 = NULL, to_free2 = NULL;
2756+
2757+
if (ConvertSidToStringSidA(sid, &str1))
2758+
to_free1 = str1;
2759+
else
2760+
str1 = "(inconvertible)";
2761+
2762+
if (!current_user_sid)
2763+
str2 = "(none)";
2764+
else if (!IsValidSid(current_user_sid))
2765+
str2 = "(invalid)";
2766+
else if (ConvertSidToStringSidA(current_user_sid, &str2))
2767+
to_free2 = str2;
2768+
else
2769+
str2 = "(inconvertible)";
2770+
strbuf_addf(report,
2771+
"'%s' is owned by:\n"
2772+
"\t'%s'\nbut the current user is:\n"
2773+
"\t'%s'\n", path, str1, str2);
2774+
LocalFree(to_free1);
2775+
LocalFree(to_free2);
2776+
}
27202777
}
27212778

27222779
/*

compat/mingw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ char *mingw_query_user_email(void);
463463
* Verifies that the specified path is owned by the user running the
464464
* current process.
465465
*/
466-
int is_path_owned_by_current_sid(const char *path);
466+
int is_path_owned_by_current_sid(const char *path, struct strbuf *report);
467467
#define is_path_owned_by_current_user is_path_owned_by_current_sid
468468

469469
/**

git-compat-util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include <crtdbg.h>
2424
#endif
2525

26+
struct strbuf;
27+
28+
2629
#define _FILE_OFFSET_BITS 64
2730

2831

@@ -487,7 +490,7 @@ static inline void extract_id_from_env(const char *env, uid_t *id)
487490
}
488491
}
489492

490-
static inline int is_path_owned_by_current_uid(const char *path)
493+
static inline int is_path_owned_by_current_uid(const char *path, struct strbuf *report)
491494
{
492495
struct stat st;
493496
uid_t euid;

setup.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,16 +1138,17 @@ static int safe_directory_cb(const char *key, const char *value, void *d)
11381138
* added, for bare ones their git directory.
11391139
*/
11401140
static int ensure_valid_ownership(const char *gitfile,
1141-
const char *worktree, const char *gitdir)
1141+
const char *worktree, const char *gitdir,
1142+
struct strbuf *report)
11421143
{
11431144
struct safe_directory_data data = {
11441145
.path = worktree ? worktree : gitdir
11451146
};
11461147

11471148
if (!git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0) &&
1148-
(!gitfile || is_path_owned_by_current_user(gitfile)) &&
1149-
(!worktree || is_path_owned_by_current_user(worktree)) &&
1150-
(!gitdir || is_path_owned_by_current_user(gitdir)))
1149+
(!gitfile || is_path_owned_by_current_user(gitfile, report)) &&
1150+
(!worktree || is_path_owned_by_current_user(worktree, report)) &&
1151+
(!gitdir || is_path_owned_by_current_user(gitdir, report)))
11511152
return 1;
11521153

11531154
/*
@@ -1187,6 +1188,7 @@ enum discovery_result {
11871188
*/
11881189
static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
11891190
struct strbuf *gitdir,
1191+
struct strbuf *report,
11901192
int die_on_error)
11911193
{
11921194
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
@@ -1271,10 +1273,11 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
12711273
strbuf_setlen(dir, offset);
12721274
if (gitdirenv) {
12731275
enum discovery_result ret;
1276+
const char *gitdir_candidate =
1277+
gitdir_path ? gitdir_path : gitdirenv;
12741278

1275-
if (ensure_valid_ownership(gitfile,
1276-
dir->buf,
1277-
(gitdir_path ? gitdir_path : gitdirenv))) {
1279+
if (ensure_valid_ownership(gitfile, dir->buf,
1280+
gitdir_candidate, report)) {
12781281
strbuf_addstr(gitdir, gitdirenv);
12791282
ret = GIT_DIR_DISCOVERED;
12801283
} else
@@ -1297,7 +1300,7 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
12971300
}
12981301

12991302
if (is_git_directory(dir->buf)) {
1300-
if (!ensure_valid_ownership(NULL, NULL, dir->buf))
1303+
if (!ensure_valid_ownership(NULL, NULL, dir->buf, report))
13011304
return GIT_DIR_INVALID_OWNERSHIP;
13021305
strbuf_addstr(gitdir, ".");
13031306
return GIT_DIR_BARE;
@@ -1330,7 +1333,7 @@ int discover_git_directory(struct strbuf *commondir,
13301333
return -1;
13311334

13321335
cwd_len = dir.len;
1333-
if (setup_git_directory_gently_1(&dir, gitdir, 0) <= 0) {
1336+
if (setup_git_directory_gently_1(&dir, gitdir, NULL, 0) <= 0) {
13341337
strbuf_release(&dir);
13351338
return -1;
13361339
}
@@ -1377,7 +1380,7 @@ int discover_git_directory(struct strbuf *commondir,
13771380
const char *setup_git_directory_gently(int *nongit_ok)
13781381
{
13791382
static struct strbuf cwd = STRBUF_INIT;
1380-
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
1383+
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT, report = STRBUF_INIT;
13811384
const char *prefix = NULL;
13821385
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
13831386

@@ -1402,7 +1405,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
14021405
die_errno(_("Unable to read current working directory"));
14031406
strbuf_addbuf(&dir, &cwd);
14041407

1405-
switch (setup_git_directory_gently_1(&dir, &gitdir, 1)) {
1408+
switch (setup_git_directory_gently_1(&dir, &gitdir, &report, 1)) {
14061409
case GIT_DIR_EXPLICIT:
14071410
prefix = setup_explicit_git_dir(gitdir.buf, &cwd, &repo_fmt, nongit_ok);
14081411
break;
@@ -1434,12 +1437,14 @@ const char *setup_git_directory_gently(int *nongit_ok)
14341437
if (!nongit_ok) {
14351438
struct strbuf quoted = STRBUF_INIT;
14361439

1440+
strbuf_complete(&report, '\n');
14371441
sq_quote_buf_pretty(&quoted, dir.buf);
14381442
die(_("detected dubious ownership in repository at '%s'\n"
1443+
"%s"
14391444
"To add an exception for this directory, call:\n"
14401445
"\n"
14411446
"\tgit config --global --add safe.directory %s"),
1442-
dir.buf, quoted.buf);
1447+
dir.buf, report.buf, quoted.buf);
14431448
}
14441449
*nongit_ok = 1;
14451450
break;
@@ -1518,6 +1523,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
15181523

15191524
strbuf_release(&dir);
15201525
strbuf_release(&gitdir);
1526+
strbuf_release(&report);
15211527
clear_repository_format(&repo_fmt);
15221528

15231529
return prefix;

0 commit comments

Comments
 (0)