This commit is contained in:
DavidXanatos 2023-07-22 21:43:39 +02:00
parent dc5a2013c8
commit 372cf04a52
4 changed files with 159 additions and 17 deletions

View File

@ -30,6 +30,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- fixed Remove Sandbox only deletes the contents of the sandbox when an application is running in the sandbox [#3118](https://github.com/sandboxie-plus/Sandboxie/issues/3118) - fixed Remove Sandbox only deletes the contents of the sandbox when an application is running in the sandbox [#3118](https://github.com/sandboxie-plus/Sandboxie/issues/3118)
- fixed crash issue with not peroeprly termianted script engine [#3120](https://github.com/sandboxie-plus/Sandboxie/issues/3120) - fixed crash issue with not peroeprly termianted script engine [#3120](https://github.com/sandboxie-plus/Sandboxie/issues/3120)
- fixed ImDisk under Sandboxie supervision causes SBIE2337 and sometimes BSoD [#1092)(https://github.com/sandboxie-plus/Sandboxie/issues/1092) - fixed ImDisk under Sandboxie supervision causes SBIE2337 and sometimes BSoD [#1092)(https://github.com/sandboxie-plus/Sandboxie/issues/1092)
- fixed Snapshots don't merge duplicate directory junctions [#3016](https://github.com/sandboxie-plus/Sandboxie/issues/3016)

View File

@ -189,6 +189,10 @@ static NTSTATUS File_MigrateFile(
const WCHAR *TruePath, const WCHAR *CopyPath, const WCHAR *TruePath, const WCHAR *CopyPath,
BOOLEAN IsWritePath, BOOLEAN WithContents); BOOLEAN IsWritePath, BOOLEAN WithContents);
static NTSTATUS File_MigrateJunction(
const WCHAR *TruePath, const WCHAR *CopyPath,
BOOLEAN IsWritePath);
static NTSTATUS File_CopyShortName( static NTSTATUS File_CopyShortName(
const WCHAR *TruePath, const WCHAR *CopyPath); const WCHAR *TruePath, const WCHAR *CopyPath);
@ -3382,7 +3386,12 @@ ReparseLoop:
// write access, or else it would have been handled earlier already) // write access, or else it would have been handled earlier already)
// //
if (CreateDisposition == FILE_OPEN || if (FileType & TYPE_REPARSE_POINT) {
status = File_MigrateJunction(
TruePath, CopyPath, IsWritePath);
} else if (CreateDisposition == FILE_OPEN ||
CreateDisposition == FILE_OPEN_IF || CreateDisposition == FILE_OPEN_IF ||
TruePathColon) { TruePathColon) {

View File

@ -466,3 +466,112 @@ _FX NTSTATUS File_MigrateFile(
return status; return status;
} }
//---------------------------------------------------------------------------
// File_MigrateJunction
//---------------------------------------------------------------------------
_FX NTSTATUS File_MigrateJunction(
const WCHAR* TruePath, const WCHAR* CopyPath,
BOOLEAN IsWritePath)
{
NTSTATUS status;
HANDLE TrueHandle, CopyHandle;
OBJECT_ATTRIBUTES objattrs;
UNICODE_STRING objname;
IO_STATUS_BLOCK IoStatusBlock;
FILE_NETWORK_OPEN_INFORMATION open_info;
InitializeObjectAttributes(
&objattrs, &objname, OBJ_CASE_INSENSITIVE, NULL, Secure_NormalSD);
//
// open TruePath. if we get a sharing violation trying to open it,
// try to get the driver to open it bypassing share access. if even
// this fails, then we can't copy the data, but can still create an
// empty file
//
RtlInitUnicodeString(&objname, TruePath);
status = __sys_NtCreateFile(
&TrueHandle, FILE_GENERIC_READ, &objattrs, &IoStatusBlock,
NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
/*if (IsWritePath && status == STATUS_ACCESS_DENIED)
status = STATUS_SHARING_VIOLATION;
if (status == STATUS_SHARING_VIOLATION) {
status = SbieApi_OpenFile(&TrueHandle, TruePath);
}*/
if (!NT_SUCCESS(status))
return status;
//
// query attributes and size of the TruePath file
//
status = __sys_NtQueryInformationFile(
TrueHandle, &IoStatusBlock, &open_info,
sizeof(FILE_NETWORK_OPEN_INFORMATION), FileNetworkOpenInformation);
//
// Get the reparse point data from the source
//
BYTE buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; // We need a large buffer
REPARSE_DATA_BUFFER* reparseDataBuffer = (REPARSE_DATA_BUFFER*)buf;
status = __sys_NtFsControlFile(TrueHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_GET_REPARSE_POINT, NULL, 0, reparseDataBuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (!NT_SUCCESS(status))
return status;
//
// Create the destination file with reparse point data
//
RtlInitUnicodeString(&objname, CopyPath);
status = __sys_NtCreateFile(
&CopyHandle, FILE_GENERIC_WRITE, &objattrs, &IoStatusBlock,
NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS,
FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT,
NULL, 0);
if (!NT_SUCCESS(status))
return status;
//
// Set the reparse point data to the destination
//
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
status = __sys_NtFsControlFile(CopyHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, reparseDataBuffer, REPARSE_MOUNTPOINT_HEADER_SIZE + reparseDataBuffer->ReparseDataLength, NULL, 0);
//
// set information on the CopyPath file
//
if (NT_SUCCESS(status)) {
FILE_BASIC_INFORMATION info;
info.CreationTime.QuadPart = open_info.CreationTime.QuadPart;
info.LastAccessTime.QuadPart = open_info.LastAccessTime.QuadPart;
info.LastWriteTime.QuadPart = open_info.LastWriteTime.QuadPart;
info.ChangeTime.QuadPart = open_info.ChangeTime.QuadPart;
info.FileAttributes = open_info.FileAttributes;
status = File_SetAttributes(CopyHandle, CopyPath, &info);
}
NtClose(TrueHandle);
NtClose(CopyHandle);
return status;
}

View File

@ -98,6 +98,34 @@ NTSTATUS NtIo_RemoveJunction(POBJECT_ATTRIBUTES objattrs)
return status; return status;
} }
NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param), void* param);
NTSTATUS NtIo_DeleteFileImpl(ULONG FileAttributes, OBJECT_ATTRIBUTES* attr, bool (*cb)(const WCHAR* info, void* param), void* param)
{
NTSTATUS status;
if (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
NtIo_RemoveProblematicAttributes(attr);
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
status = NtIo_RemoveJunction(attr);
else if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
status = NtIo_DeleteFolderRecursivelyImpl(attr, cb, param);
if (NT_SUCCESS(status))
status = NtDeleteFile(attr);
return status;
}
NTSTATUS NtIo_DeleteFileImpl(SNtObject& ntObject, bool (*cb)(const WCHAR* info, void* param), void* param)
{
FILE_BASIC_INFORMATION info = { 0 };
NtQueryAttributesFile(&ntObject.attr, &info);
return NtIo_DeleteFileImpl(info.FileAttributes, &ntObject.attr, cb, param);
}
NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param), void* param) NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb)(const WCHAR* info, void* param), void* param)
{ {
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
@ -147,16 +175,7 @@ NTSTATUS NtIo_DeleteFolderRecursivelyImpl(POBJECT_ATTRIBUTES objattrs, bool (*cb
SNtObject ntFoundObject(FileName, Handle); SNtObject ntFoundObject(FileName, Handle);
if (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) status = NtIo_DeleteFileImpl(FileAttributes, &ntFoundObject.attr, cb, param);
NtIo_RemoveProblematicAttributes(&ntFoundObject.attr);
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
status = NtIo_RemoveJunction(&ntFoundObject.attr);
else if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
status = NtIo_DeleteFolderRecursivelyImpl(&ntFoundObject.attr, cb, param);
if (NT_SUCCESS(status))
status = NtDeleteFile(&ntFoundObject.attr);
} }
NtClose(Handle); NtClose(Handle);
@ -255,7 +274,7 @@ BOOLEAN NtIo_FileExists(POBJECT_ATTRIBUTES objattrs)
IO_STATUS_BLOCK Iosb; IO_STATUS_BLOCK Iosb;
HANDLE handle; HANDLE handle;
status = NtCreateFile(&handle, SYNCHRONIZE, objattrs, &Iosb, NULL, 0, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); status = NtCreateFile(&handle, SYNCHRONIZE, objattrs, &Iosb, NULL, 0, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, 0);
if (NT_SUCCESS(status)) if (NT_SUCCESS(status))
{ {
// STATUS_OBJECT_NAME_NOT_FOUND // STATUS_OBJECT_PATH_NOT_FOUND // STATUS_OBJECT_NAME_NOT_FOUND // STATUS_OBJECT_PATH_NOT_FOUND
@ -325,11 +344,15 @@ NTSTATUS NtIo_MergeFolder(POBJECT_ATTRIBUTES src_objattrs, POBJECT_ATTRIBUTES de
//if (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) //if (FileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
// NtIo_RemoveProblematicAttributes(&ntFoundObject.attr); // NtIo_RemoveProblematicAttributes(&ntFoundObject.attr);
if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
{ if (TargetExists)
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) status = NtIo_DeleteFileImpl(ntDestObject, cb, param);
if (NT_SUCCESS(status))
status = NtIo_RenameJunction(&ntSrcObject.attr, dest_objattrs, FileName.c_str()); status = NtIo_RenameJunction(&ntSrcObject.attr, dest_objattrs, FileName.c_str());
else if (TargetExists) }
else if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (TargetExists)
status = NtIo_MergeFolder(&ntSrcObject.attr, &ntDestObject.attr, cb, param); status = NtIo_MergeFolder(&ntSrcObject.attr, &ntDestObject.attr, cb, param);
else else
status = NtIo_RenameFolder(&ntSrcObject.attr, dest_objattrs, FileName.c_str()); status = NtIo_RenameFolder(&ntSrcObject.attr, dest_objattrs, FileName.c_str());
@ -337,7 +360,7 @@ NTSTATUS NtIo_MergeFolder(POBJECT_ATTRIBUTES src_objattrs, POBJECT_ATTRIBUTES de
else else
{ {
if (TargetExists) if (TargetExists)
status = NtDeleteFile(&ntDestObject.attr); status = NtIo_DeleteFileImpl(ntDestObject, cb, param);
if (NT_SUCCESS(status)) if (NT_SUCCESS(status))
status = NtIo_RenameFile(&ntSrcObject.attr, dest_objattrs, FileName.c_str()); status = NtIo_RenameFile(&ntSrcObject.attr, dest_objattrs, FileName.c_str());
} }