Skip to content

git init failed in case of user have access to a directory but not have "List Directory" access to some of the parent directories of that directory #598

Closed
@skvoboo

Description

@skvoboo

OS/Git version

C:\inetpub\wwwroot>git version
git version 2.7.0.windows.1

C:\inetpub\wwwroot>ver
Microsoft Windows [Version 6.3.9600]

Steps to reproduce

  1. Create user
  2. Allow full access control on C:\inetpub\wwwroot directory for created user
  3. Deny List Directory permission (this folder only) on C:\inetpub directory for created user
  4. Login to server by created user and execute:
C:\Users\user1>cd C:\inetpub\wwwroot
C:\inetpub\wwwroot>git init
fatal: unable to get current working directory: No error

Root cause
mingw_getcwd function in compat\mingw.c file uses GetLongPathNameW WinAPI function, GetLongPathName may fail when it is unable to query the parent directory of a path component to determine the long name for that component.

Proposed solution
Get handle of current directory and use GetFinalPathNameByHandleW function to get long path.

The solution proposed for Windows Server 2008/Windows Vista or high.

Patch

 char *mingw_getcwd(char *pointer, int len)
 {
-   int i;
    wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
+   DECLARE_PROC_ADDR(kernel32.dll, DWORD, GetFinalPathNameByHandleW,
+             HANDLE, LPWSTR, DWORD, DWORD);
    DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);

    if (ret < 0 || ret >= ARRAY_SIZE(cwd))
        return NULL;
-   ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
-   if (!ret || ret >= ARRAY_SIZE(wpointer))
+
+   if (INIT_PROC_ADDR(GetFinalPathNameByHandleW)) {
+       HANDLE hnd = CreateFileW(cwd, 0,
+           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+       if (hnd == INVALID_HANDLE_VALUE)
+           return NULL;
+       ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
+       CloseHandle(hnd);
+   } else {
+       ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
+   }
+
+   if (!ret || ret >= ARRAY_SIZE(wpointer))
        return NULL;
-   if (xwcstoutf(pointer, wpointer, len) < 0)
+   if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
        return NULL;
-   for (i = 0; pointer[i]; i++)
-       if (pointer[i] == '\\')
-           pointer[i] = '/';
    return pointer;
 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions