Skip to content

Commit 52a33b6

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
Merge pull request #1188 from dscho/unprivileged-symlinks
Support creating symlinks outside elevated sessions
2 parents 556c87d + c8670bf commit 52a33b6

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

compat/mingw.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ int mingw_core_config(const char *var, const char *value, void *cb)
271271
return 0;
272272
}
273273

274+
static DWORD symlink_file_flags = 0, symlink_directory_flags = 1;
274275
DECLARE_PROC_ADDR(kernel32.dll, BOOLEAN, CreateSymbolicLinkW, LPCWSTR, LPCWSTR, DWORD);
275276

276277
enum phantom_symlink_result {
@@ -358,7 +359,8 @@ process_phantom_symlink(const wchar_t *wtarget, const wchar_t *wlink)
358359
return PHANTOM_SYMLINK_DONE;
359360

360361
/* otherwise recreate the symlink with directory flag */
361-
if (DeleteFileW(wlink) && CreateSymbolicLinkW(wlink, wtarget, 1))
362+
if (DeleteFileW(wlink) &&
363+
CreateSymbolicLinkW(wlink, wtarget, symlink_directory_flags))
362364
return PHANTOM_SYMLINK_DIRECTORY;
363365

364366
errno = err_win_to_posix(GetLastError());
@@ -2613,7 +2615,7 @@ int symlink(const char *target, const char *link)
26132615
wtarget[len] = '\\';
26142616

26152617
/* create file symlink */
2616-
if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
2618+
if (!CreateSymbolicLinkW(wlink, wtarget, symlink_file_flags)) {
26172619
errno = err_win_to_posix(GetLastError());
26182620
return -1;
26192621
}
@@ -3135,6 +3137,24 @@ static void maybe_redirect_std_handles(void)
31353137
GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
31363138
}
31373139

3140+
static void adjust_symlink_flags(void)
3141+
{
3142+
/*
3143+
* Starting with Windows 10 Build 14972, symbolic links can be created
3144+
* using CreateSymbolicLink() without elevation by passing the flag
3145+
* SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
3146+
* parameter, provided the Developer Mode has been enabled. Some
3147+
* earlier Windows versions complain about this flag with an
3148+
* ERROR_INVALID_PARAMETER, hence we have to test the build number
3149+
* specifically.
3150+
*/
3151+
if (GetVersion() >= 14972 << 16) {
3152+
symlink_file_flags |= 2;
3153+
symlink_directory_flags |= 2;
3154+
}
3155+
3156+
}
3157+
31383158
#if defined(_MSC_VER)
31393159

31403160
#ifdef _DEBUG
@@ -3174,6 +3194,7 @@ int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
31743194
#endif
31753195

31763196
maybe_redirect_std_handles();
3197+
adjust_symlink_flags();
31773198

31783199
/* determine size of argv conversion buffer */
31793200
maxlen = wcslen(_wpgmptr);
@@ -3240,6 +3261,7 @@ void mingw_startup(void)
32403261
_startupinfo si;
32413262

32423263
maybe_redirect_std_handles();
3264+
adjust_symlink_flags();
32433265

32443266
/* get wide char arguments and environment */
32453267
si.newmode = 0;

0 commit comments

Comments
 (0)