fs, win: add support for user symlinks

Add SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE to CreateSymbolicLink
which allows unelevated users to create symbolic links on supported
platforms.

Fixes: https://github.com/libuv/libuv/issues/1157
PR-URL: https://github.com/libuv/libuv/pull/1466
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Bartosz Sosnowski 2017-08-18 14:21:58 +02:00
parent c8ee8bef9b
commit 89d31932a5
2 changed files with 41 additions and 15 deletions

View File

@ -113,6 +113,7 @@ const WCHAR LONG_PATH_PREFIX_LEN = 4;
const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
const WCHAR UNC_PATH_PREFIX_LEN = 8;
static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
void uv_fs_init(void) {
_fmode = _O_BINARY;
@ -1713,25 +1714,46 @@ error:
static void fs__symlink(uv_fs_t* req) {
WCHAR* pathw = req->file.pathw;
WCHAR* new_pathw = req->fs.info.new_pathw;
int flags = req->fs.info.file_flags;
int result;
WCHAR* pathw;
WCHAR* new_pathw;
int flags;
int err;
pathw = req->file.pathw;
new_pathw = req->fs.info.new_pathw;
if (flags & UV_FS_SYMLINK_JUNCTION) {
if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
fs__create_junction(req, pathw, new_pathw);
} else if (pCreateSymbolicLinkW) {
result = pCreateSymbolicLinkW(new_pathw,
pathw,
flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
if (result == -1) {
SET_REQ_WIN32_ERROR(req, GetLastError());
} else {
SET_REQ_RESULT(req, result);
}
} else {
return;
}
if (!pCreateSymbolicLinkW) {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
return;
}
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
else
flags = uv__file_symlink_usermode_flag;
if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
SET_REQ_RESULT(req, 0);
return;
}
/* Something went wrong. We will test if it is because of user-mode
* symlinks.
*/
err = GetLastError();
if (err == ERROR_INVALID_PARAMETER &&
flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {
/* This system does not support user-mode symlinks. We will clear the
* unsupported flag and retry.
*/
uv__file_symlink_usermode_flag = 0;
fs__symlink(req);
} else {
SET_REQ_WIN32_ERROR(req, err);
}
}

View File

@ -4104,6 +4104,10 @@
# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000
#endif
#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002
#endif
/* from winternl.h */
typedef struct _UNICODE_STRING {
USHORT Length;