Skip to content

Commit cad7861

Browse files
authored
Merge pull request #1829 from tyrielv/fix-clone-permissions
Fix ownership when cloning elevated
2 parents 720e23c + 4e23d28 commit cad7861

File tree

5 files changed

+46
-1
lines changed

5 files changed

+46
-1
lines changed

GVFS/GVFS.Common/FileSystem/IPlatformFileSystem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ public interface IPlatformFileSystem
1818
bool TryCreateDirectoryWithAdminAndUserModifyPermissions(string directoryPath, out string error);
1919
bool TryCreateOrUpdateDirectoryToAdminModifyPermissions(ITracer tracer, string directoryPath, out string error);
2020
bool IsFileSystemSupported(string path, out string error);
21+
void EnsureDirectoryIsOwnedByCurrentUser(string workingDirectoryRoot);
2122
}
2223
}

GVFS/GVFS.Common/GVFSEnlistment.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ public bool TryCreateEnlistmentSubFolders()
217217
{
218218
try
219219
{
220-
Directory.CreateDirectory(this.WorkingDirectoryRoot);
220+
GVFSPlatform.Instance.FileSystem.EnsureDirectoryIsOwnedByCurrentUser(this.WorkingDirectoryRoot);
221221
this.CreateHiddenDirectory(this.DotGVFSRoot);
222222
}
223223
catch (IOException)

GVFS/GVFS.Platform.Windows/WindowsFileSystem.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,34 @@ public bool IsFileSystemSupported(string path, out string error)
272272
return true;
273273
}
274274

275+
/// <summary>
276+
/// On Windows, if the current user is elevated, the owner of the directory will be the Administrators group by default.
277+
/// This runs afoul of the git "dubious ownership" check, which can fail if either the .git directory or the working directory
278+
/// are not owned by the current user.
279+
///
280+
/// At the moment git for windows does not consider a non-elevated admin to be the owner of a directory owned by the Administrators group,
281+
/// though a fix is in progress in the microsoft fork of git. Libgit2(sharp) also does not have this fix.
282+
///
283+
/// Also, even if the fix were in place, automount would still fail because it runs under SYSTEM account.
284+
///
285+
/// This method ensures that the directory is owned by the current user (which is verified to work for SYSTEM account for automount).
286+
/// </summary>
287+
public void EnsureDirectoryIsOwnedByCurrentUser(string directoryPath)
288+
{
289+
// Ensure directory exists, inheriting all other ACLS
290+
Directory.CreateDirectory(directoryPath);
291+
// If the user is currently elevated, the owner of the directory will be the Administrators group.
292+
DirectorySecurity directorySecurity = Directory.GetAccessControl(directoryPath);
293+
IdentityReference directoryOwner = directorySecurity.GetOwner(typeof(SecurityIdentifier));
294+
SecurityIdentifier administratorsSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
295+
if (directoryOwner == administratorsSid)
296+
{
297+
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
298+
directorySecurity.SetOwner(currentUser.User);
299+
Directory.SetAccessControl(directoryPath, directorySecurity);
300+
}
301+
}
302+
275303
private class NativeFileReader
276304
{
277305
private const uint GenericRead = 0x80000000;

GVFS/GVFS.UnitTests/Mock/FileSystem/MockPlatformFileSystem.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,10 @@ public bool IsFileSystemSupported(string path, out string error)
7070
error = null;
7171
return true;
7272
}
73+
74+
public void EnsureDirectoryIsOwnedByCurrentUser(string workingDirectoryRoot)
75+
{
76+
throw new NotSupportedException();
77+
}
7378
}
7479
}

GVFS/GVFS/CommandLine/CloneVerb.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,17 @@ private Result TryInitRepo(ITracer tracer, GitRefs refs, Enlistment enlistmentTo
716716
return new Result(error);
717717
}
718718

719+
try
720+
{
721+
GVFSPlatform.Instance.FileSystem.EnsureDirectoryIsOwnedByCurrentUser(enlistmentToInit.DotGitRoot);
722+
}
723+
catch (IOException e)
724+
{
725+
string error = string.Format("Could not ensure .git directory is owned by current user: {0}", e.Message);
726+
tracer.RelatedError(error);
727+
return new Result(error);
728+
}
729+
719730
GitProcess.Result remoteAddResult = new GitProcess(enlistmentToInit).RemoteAdd("origin", enlistmentToInit.RepoUrl);
720731
if (remoteAddResult.ExitCodeIsFailure)
721732
{

0 commit comments

Comments
 (0)