This commit is contained in:
DavidXanatos 2024-01-28 17:20:59 +01:00
parent 9dec3f6f97
commit 604961a02f
2 changed files with 176 additions and 169 deletions

View File

@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- fixed Cannot run explorer.exe on emulate admin sandbox [#3516](https://github.com/sandboxie-plus/Sandboxie/issues/3516)
- fixed potential BSOD issue with WFP when trace loging is enabled
- fixed Run from Sandbox > Run > Program and Run from folder doesn't use the same working dir [#3555](https://github.com/sandboxie-plus/Sandboxie/issues/3555)
- fixed UseNewSymlinkResolver causes applications to create both the link and the target folder [#3481](https://github.com/sandboxie-plus/Sandboxie/issues/3481)

View File

@ -917,6 +917,82 @@ _FX NTSTATUS File_GetFileName(HANDLE FileHandle, ULONG NameLen, WCHAR* NameBuf)
}
//---------------------------------------------------------------------------
// File_OpenForAddTempLink
//---------------------------------------------------------------------------
_FX NTSTATUS File_OpenForAddTempLink(HANDLE* handle, WCHAR *path, ULONG CreateOptions)
{
NTSTATUS status;
OBJECT_ATTRIBUTES objattrs;
UNICODE_STRING objname;
IO_STATUS_BLOCK IoStatusBlock;
P_NtCreateFile pNtCreateFile = __sys_NtCreateFile;
// special case for File_InitRecoverFolders as its called bfore we hook those functions
if (! pNtCreateFile)
pNtCreateFile = NtCreateFile;
InitializeObjectAttributes(
&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
//
// first try the copy path
//
if (_wcsnicmp(path, Dll_BoxFilePath, Dll_BoxFilePathLen) != 0)
{
WCHAR* CopyPath = NULL;
THREAD_DATA* TlsData = Dll_GetTlsData(NULL);
Dll_PushTlsNameBuffer(TlsData);
File_GetCopyPath(path, &CopyPath);
//
// get template file if present, and reparse the path
//
WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
if (TmplName != NULL)
RtlInitUnicodeString(&objname, TmplName);
else
RtlInitUnicodeString(&objname, CopyPath);
status = pNtCreateFile(
handle, FILE_GENERIC_READ | SYNCHRONIZE, &objattrs,
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, CreateOptions,
NULL, 0);
Dll_PopTlsNameBuffer(TlsData);
}
else // its already a copy path
status = STATUS_BAD_INITIAL_PC;
//
// then try the true path
//
if (!NT_SUCCESS(status)) {
RtlInitUnicodeString(&objname, path);
status = pNtCreateFile(
handle, FILE_GENERIC_READ | SYNCHRONIZE, &objattrs,
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN,
CreateOptions,
NULL, 0);
}
return status;
}
//---------------------------------------------------------------------------
// File_AddTempLink
//---------------------------------------------------------------------------
@ -926,113 +1002,37 @@ _FX FILE_LINK *File_AddTempLink(WCHAR *path)
{
NTSTATUS status;
HANDLE handle;
OBJECT_ATTRIBUTES objattrs;
UNICODE_STRING objname;
IO_STATUS_BLOCK IoStatusBlock;
FILE_LINK *link;
WCHAR *newpath;
BOOLEAN stop;
BOOLEAN bPermLinkPath = FALSE;
WCHAR* CopyPath = NULL;
//
// try to open the path
//
P_NtCreateFile pNtCreateFile = __sys_NtCreateFile;
P_NtClose pNtClose = __sys_NtClose;
P_NtFsControlFile pNtFsControlFile = __sys_NtFsControlFile;
// special case for File_InitRecoverFolders as its called bfore we hook those functions
if (! pNtCreateFile)
pNtCreateFile = NtCreateFile;
if (! pNtClose)
pNtClose = NtClose;
if (! pNtFsControlFile)
pNtFsControlFile = NtFsControlFile;
stop = TRUE;
InitializeObjectAttributes(
&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, NULL);
newpath = NULL;
BOOLEAN UserReparse = SbieApi_QueryConfBool(NULL, L"UseNewSymlinkResolver", TRUE);
if (UserReparse) {
//
// first try the copy path
//
status = File_OpenForAddTempLink(&handle, path, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
if (_wcsnicmp(path, Dll_BoxFilePath, Dll_BoxFilePathLen) != 0)
{
THREAD_DATA* TlsData = Dll_GetTlsData(NULL);
Dll_PushTlsNameBuffer(TlsData);
File_GetCopyPath(path, &CopyPath);
//
// get template file if present, and reparse the path
//
WCHAR* TmplName = File_FindSnapshotPath(CopyPath);
if (TmplName != NULL)
RtlInitUnicodeString(&objname, TmplName);
else
RtlInitUnicodeString(&objname, CopyPath);
status = pNtCreateFile(
&handle, FILE_GENERIC_READ | SYNCHRONIZE, &objattrs,
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT,
NULL, 0);
Dll_PopTlsNameBuffer(TlsData);
if (!NT_SUCCESS(status))
CopyPath = NULL;
}
else // its already a copy path
status = STATUS_BAD_INITIAL_PC;
//
// then try the true path
//
if (!NT_SUCCESS(status)) {
RtlInitUnicodeString(&objname, path);
status = pNtCreateFile(
&handle, FILE_GENERIC_READ | SYNCHRONIZE, &objattrs,
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT,
NULL, 0);
if (!NT_SUCCESS(status))
UserReparse = FALSE;
}
}
if (!UserReparse) {
RtlInitUnicodeString(&objname, path);
status = pNtCreateFile(
&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objattrs,
&IoStatusBlock, NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
}
if (NT_SUCCESS(status)) {
if (UserReparse) {
if (NT_SUCCESS(status)) {
REPARSE_DATA_BUFFER* reparseDataBuffer = Dll_AllocTemp(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
status = pNtFsControlFile(handle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_GET_REPARSE_POINT, NULL, 0, reparseDataBuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
newpath = NULL;
if (NT_SUCCESS(status)) {
@ -1053,133 +1053,139 @@ _FX FILE_LINK *File_AddTempLink(WCHAR *path)
SubstituteNameBuffer[reparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)] = 0;
}
if (SubstituteNameBuffer && !RelativePath) // todo RelativePath - for now we fall back to UserReparse = FALSE;
if (SubstituteNameBuffer)
{
WCHAR* input_str = SubstituteNameBuffer;
if (_wcsnicmp(input_str, L"\\??\\Volume{", 11) == 0)
input_str = File_TranslateGuidToNtPath(SubstituteNameBuffer);
else if (_wcsnicmp(input_str, File_BQQB, 4) == 0)
input_str = File_TranslateDosToNtPath(SubstituteNameBuffer + 4);
if (RelativePath)
{
// todo RelativePath - for now we fall back to the old method
}
else
{
WCHAR* input_str = SubstituteNameBuffer;
if (_wcsnicmp(input_str, L"\\??\\Volume{", 11) == 0)
input_str = File_TranslateGuidToNtPath(SubstituteNameBuffer);
else if (_wcsnicmp(input_str, File_BQQB, 4) == 0)
input_str = File_TranslateDosToNtPath(SubstituteNameBuffer + 4);
if (input_str) {
if (input_str) {
ULONG input_len = wcslen(input_str);
while (input_len > 0 && input_str[input_len - 1] == L'\\')
input_len -= 1; // remove trailing backslash
ULONG input_len = wcslen(input_str);
while (input_len > 0 && input_str[input_len - 1] == L'\\')
input_len -= 1; // remove trailing backslash
newpath = File_TranslateTempLinks_2(input_str, input_len);
newpath = File_TranslateTempLinks_2(input_str, input_len);
if (input_str != SubstituteNameBuffer)
Dll_Free(input_str);
if (input_str != SubstituteNameBuffer)
Dll_Free(input_str);
}
}
}
/*THREAD_DATA* TlsData = Dll_GetTlsData(NULL);
Dll_PushTlsNameBuffer(TlsData);
WCHAR* TruePath = NULL;
if (NT_SUCCESS(File_GetTruePath(newpath, &TruePath))) {
Dll_Free(newpath);
newpath = Dll_AllocTemp((wcslen(TruePath) + 1) * sizeof(WCHAR));
wcscpy(newpath, TruePath);
}
Dll_PopTlsNameBuffer(TlsData);*/
}
//else if (status == STATUS_NOT_A_REPARSE_POINT)
if (!newpath) {
if (CopyPath) {
newpath = Dll_AllocTemp((wcslen(path) + 1) * sizeof(WCHAR));
wcscpy(newpath, path);
} else
UserReparse = FALSE;
status = STATUS_SUCCESS;
}
Dll_Free(reparseDataBuffer);
pNtClose(handle);
}
}
const ULONG PATH_BUF_LEN = 1024;
//
// get the reparsed absolute path
//
if (!newpath) {
const ULONG PATH_BUF_LEN = 1024;
if (!UserReparse) {
newpath = Dll_AllocTemp(PATH_BUF_LEN);
status = File_GetFileName(handle, PATH_BUF_LEN - 4, newpath);
}
status = File_OpenForAddTempLink(&handle, path, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(status)) {
//
// make sure path does not contain duplicate backslashes
// get the reparsed absolute path
//
ULONG len = wcslen(newpath);
WCHAR *name = newpath;
while (name[0]) {
if (name[0] == L'\\' && name[1] == L'\\') {
ULONG move_len = len - (ULONG)(name - newpath) + 1;
wmemmove(name, name + 1, move_len);
--len;
} else
++name;
newpath = Dll_AllocTemp(PATH_BUF_LEN);
status = File_GetFileName(handle, PATH_BUF_LEN - 4, newpath);
if (!NT_SUCCESS(status)) {
Dll_Free(newpath);
newpath = NULL;
}
//
// convert permanent links (i.e. drive mount points)
//
pNtClose(handle);
}
}
len = File_FixPermLinksForTempLink(
newpath, len, (PATH_BUF_LEN - 4) / sizeof(WCHAR));
if (newpath) {
//
// verify the link points to a local drive
//
//
// check if what we got is a copy path and convert it to a true path
//
if (File_FindPermLinksForMatchPath(newpath, len))
{
// release lock by File_FindPermLinksForMatchPath
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
bPermLinkPath = TRUE;
}
THREAD_DATA* TlsData = Dll_GetTlsData(NULL);
if (! FILE_IS_REDIRECTOR_OR_MUP(newpath, len) && !bPermLinkPath) {
const FILE_DRIVE *drive = File_GetDriveForPath(newpath, len);
const FILE_GUID *guid = NULL;
if(!drive)
guid = File_GetGuidForPath(newpath, len);
if (drive || guid) {
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
stop = FALSE;
}
}
Dll_PushTlsNameBuffer(TlsData);
WCHAR* TruePath = NULL;
if (NT_SUCCESS(File_GetTruePath(newpath, &TruePath))) {
} else {
Dll_Free(newpath);
newpath = NULL;
newpath = Dll_AllocTemp((wcslen(TruePath) + 1) * sizeof(WCHAR));
wcscpy(newpath, TruePath);
}
pNtClose(handle);
Dll_PopTlsNameBuffer(TlsData);
//
// make sure path does not contain duplicate backslashes
//
ULONG len = wcslen(newpath);
WCHAR *name = newpath;
while (name[0]) {
if (name[0] == L'\\' && name[1] == L'\\') {
ULONG move_len = len - (ULONG)(name - newpath) + 1;
wmemmove(name, name + 1, move_len);
--len;
} else
++name;
}
//
// convert permanent links (i.e. drive mount points)
//
len = File_FixPermLinksForTempLink(
newpath, len, (PATH_BUF_LEN - 4) / sizeof(WCHAR));
//
// verify the link points to a local drive
//
if (File_FindPermLinksForMatchPath(newpath, len))
{
// release lock by File_FindPermLinksForMatchPath
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
bPermLinkPath = TRUE;
}
if (! FILE_IS_REDIRECTOR_OR_MUP(newpath, len) && !bPermLinkPath) {
const FILE_DRIVE *drive = File_GetDriveForPath(newpath, len);
const FILE_GUID *guid = NULL;
if(!drive)
guid = File_GetGuidForPath(newpath, len);
if (drive || guid) {
LeaveCriticalSection(File_DrivesAndLinks_CritSec);
stop = FALSE;
}
}
} else
newpath = NULL;
newpath = path;
//
// add the new link and return
//
if (! newpath)
newpath = path;
if (File_AddLink(FALSE, path, newpath)) {
link = List_Head(File_TempLinks);
if (link)