dll: reparse point implementation: fixes

This commit is contained in:
Bill Zissimopoulos 2016-08-20 02:47:14 -07:00
parent d2d2dd5099
commit 2f73bfa069
2 changed files with 60 additions and 59 deletions

View File

@ -40,6 +40,43 @@
extern "C" { extern "C" {
#endif #endif
/*
* The REPARSE_DATA_BUFFER definitions appear to be missing from the user mode headers.
*/
#if !defined(SYMLINK_FLAG_RELATIVE)
#define SYMLINK_FLAG_RELATIVE 1
typedef struct _REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct
{
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
/** /**
* @group File System * @group File System
* *

View File

@ -17,39 +17,6 @@
#include <dll/library.h> #include <dll/library.h>
/* the following definitions appear to be missing from the user mode headers */
#define SYMLINK_FLAG_RELATIVE 1
typedef struct _REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct
{
UCHAR DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem, FSP_API NTSTATUS FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
{ {
@ -168,6 +135,7 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
PSECURITY_DESCRIPTOR *PSecurityDescriptor) PSECURITY_DESCRIPTOR *PSecurityDescriptor)
{ {
NTSTATUS Result; NTSTATUS Result;
UINT32 GrantedAccess;
/* /*
* CreateCheck consists of checking the parent directory for the * CreateCheck consists of checking the parent directory for the
@ -181,12 +149,9 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck, Result = FspAccessCheckEx(FileSystem, Request, TRUE, AllowTraverseCheck,
(Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ? (Request->Req.Create.CreateOptions & FILE_DIRECTORY_FILE) ?
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
PGrantedAccess, PSecurityDescriptor); &GrantedAccess, PSecurityDescriptor);
if (STATUS_REPARSE == Result) if (STATUS_REPARSE == Result)
{ Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
*PGrantedAccess = 0;
}
else if (NT_SUCCESS(Result)) else if (NT_SUCCESS(Result))
{ {
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ? *PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
@ -202,6 +167,7 @@ NTSTATUS FspFileSystemOpenCheck(FSP_FILE_SYSTEM *FileSystem,
BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess) BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess)
{ {
NTSTATUS Result; NTSTATUS Result;
UINT32 GrantedAccess;
/* /*
* OpenCheck consists of checking the file for the desired access, * OpenCheck consists of checking the file for the desired access,
@ -216,14 +182,12 @@ NTSTATUS FspFileSystemOpenCheck(FSP_FILE_SYSTEM *FileSystem,
Result = FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck, Result = FspAccessCheck(FileSystem, Request, FALSE, AllowTraverseCheck,
Request->Req.Create.DesiredAccess | Request->Req.Create.DesiredAccess |
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0), ((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
PGrantedAccess); &GrantedAccess);
if (STATUS_REPARSE == Result) if (STATUS_REPARSE == Result)
{ Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
*PGrantedAccess = 0;
}
else if (NT_SUCCESS(Result)) else if (NT_SUCCESS(Result))
{ {
*PGrantedAccess = GrantedAccess;
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED)) if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
*PGrantedAccess &= ~DELETE | (Request->Req.Create.DesiredAccess & DELETE); *PGrantedAccess &= ~DELETE | (Request->Req.Create.DesiredAccess & DELETE);
} }
@ -237,6 +201,7 @@ NTSTATUS FspFileSystemOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess) BOOLEAN AllowTraverseCheck, PUINT32 PGrantedAccess)
{ {
NTSTATUS Result; NTSTATUS Result;
UINT32 GrantedAccess;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff); BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
/* /*
@ -254,14 +219,12 @@ NTSTATUS FspFileSystemOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
Request->Req.Create.DesiredAccess | Request->Req.Create.DesiredAccess |
(Supersede ? DELETE : FILE_WRITE_DATA) | (Supersede ? DELETE : FILE_WRITE_DATA) |
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0), ((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
PGrantedAccess); &GrantedAccess);
if (STATUS_REPARSE == Result) if (STATUS_REPARSE == Result)
{ Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
*PGrantedAccess = 0;
}
else if (NT_SUCCESS(Result)) else if (NT_SUCCESS(Result))
{ {
*PGrantedAccess = GrantedAccess;
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED)) if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
*PGrantedAccess &= ~(DELETE | FILE_WRITE_DATA) | *PGrantedAccess &= ~(DELETE | FILE_WRITE_DATA) |
(Request->Req.Create.DesiredAccess & (DELETE | FILE_WRITE_DATA)); (Request->Req.Create.DesiredAccess & (DELETE | FILE_WRITE_DATA));
@ -276,6 +239,7 @@ NTSTATUS FspFileSystemOpenTargetDirectoryCheck(FSP_FILE_SYSTEM *FileSystem,
PUINT32 PGrantedAccess) PUINT32 PGrantedAccess)
{ {
NTSTATUS Result; NTSTATUS Result;
UINT32 GrantedAccess;
/* /*
* OpenTargetDirectoryCheck consists of checking the parent directory * OpenTargetDirectoryCheck consists of checking the parent directory
@ -283,12 +247,11 @@ NTSTATUS FspFileSystemOpenTargetDirectoryCheck(FSP_FILE_SYSTEM *FileSystem,
*/ */
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Request->Req.Create.DesiredAccess, Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Request->Req.Create.DesiredAccess,
PGrantedAccess); &GrantedAccess);
if (STATUS_REPARSE == Result) if (STATUS_REPARSE == Result)
{ Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, GrantedAccess);
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess); else if (NT_SUCCESS(Result))
*PGrantedAccess = 0; *PGrantedAccess = GrantedAccess;
}
return Result; return Result;
} }
@ -932,8 +895,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
if (0 != FileSystem->Interface->GetReparsePoint) if (0 != FileSystem->Interface->GetReparsePoint)
{ {
ReparseData = (PREPARSE_DATA_BUFFER)Response->Buffer; ReparseData = (PREPARSE_DATA_BUFFER)Response->Buffer;
memset(ReparseData, 0, memset(ReparseData, 0, sizeof *ReparseData);
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer));
if (FileSystem->ReparsePointsSymbolicLinks) if (FileSystem->ReparsePointsSymbolicLinks)
{ {
@ -966,7 +928,9 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
ReparseData->SymbolicLinkReparseBuffer.Flags = 0 == Offset ? ReparseData->SymbolicLinkReparseBuffer.Flags = 0 == Offset ?
0 : SYMLINK_FLAG_RELATIVE; 0 : SYMLINK_FLAG_RELATIVE;
Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)Size; Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)(
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
Size);
} }
} }
else else
@ -1132,7 +1096,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
{ {
REPARSE_DATA_BUFFER V; REPARSE_DATA_BUFFER V;
UINT8 B[FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + UINT8 B[FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
/* assumption: the substitute and print paths are stored in the same buffer */ /* assumption: the substitute and print paths fit in the same buffer */
FSP_FSCTL_TRANSACT_PATH_SIZEMAX]; FSP_FSCTL_TRANSACT_PATH_SIZEMAX];
} ReparseDataBuf; } ReparseDataBuf;
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V; PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
@ -1173,7 +1137,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
/* dot */ /* dot */
continue; continue;
if (L'.' == lastp[1] && p == lastp + 1) if (L'.' == lastp[1] && p == lastp + 2)
{ {
/* dotdot */ /* dotdot */
p = lastp; p = lastp;
@ -1214,7 +1178,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
continue; continue;
else if (!NT_SUCCESS(Result)) else if (!NT_SUCCESS(Result))
{ {
if (STATUS_OBJECT_NAME_NOT_FOUND == Result && '\0' == *p) if (STATUS_OBJECT_NAME_NOT_FOUND == Result && '\0' != c)
Result = STATUS_OBJECT_PATH_NOT_FOUND; Result = STATUS_OBJECT_PATH_NOT_FOUND;
return Result; return Result;
} }