Skip to content

Commit 97c2c93

Browse files
committed
Merge pull request #1188 from dscho/unprivileged-symlinks
Support creating symlinks outside elevated sessions
2 parents 456f46c + 89ae9e9 commit 97c2c93

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());
@@ -2576,7 +2578,7 @@ int symlink(const char *target, const char *link)
25762578
wtarget[len] = '\\';
25772579

25782580
/* create file symlink */
2579-
if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
2581+
if (!CreateSymbolicLinkW(wlink, wtarget, symlink_file_flags)) {
25802582
errno = err_win_to_posix(GetLastError());
25812583
return -1;
25822584
}
@@ -3098,6 +3100,24 @@ static void maybe_redirect_std_handles(void)
30983100
GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
30993101
}
31003102

3103+
static void adjust_symlink_flags(void)
3104+
{
3105+
/*
3106+
* Starting with Windows 10 Build 14972, symbolic links can be created
3107+
* using CreateSymbolicLink() without elevation by passing the flag
3108+
* SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
3109+
* parameter, provided the Developer Mode has been enabled. Some
3110+
* earlier Windows versions complain about this flag with an
3111+
* ERROR_INVALID_PARAMETER, hence we have to test the build number
3112+
* specifically.
3113+
*/
3114+
if (GetVersion() >= 14972 << 16) {
3115+
symlink_file_flags |= 2;
3116+
symlink_directory_flags |= 2;
3117+
}
3118+
3119+
}
3120+
31013121
#if defined(_MSC_VER)
31023122

31033123
#ifdef _DEBUG
@@ -3137,6 +3157,7 @@ int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
31373157
#endif
31383158

31393159
maybe_redirect_std_handles();
3160+
adjust_symlink_flags();
31403161

31413162
/* determine size of argv conversion buffer */
31423163
maxlen = wcslen(_wpgmptr);
@@ -3203,6 +3224,7 @@ void mingw_startup(void)
32033224
_startupinfo si;
32043225

32053226
maybe_redirect_std_handles();
3227+
adjust_symlink_flags();
32063228

32073229
/* get wide char arguments and environment */
32083230
si.newmode = 0;

0 commit comments

Comments
 (0)