From fe7b4968ce3c13cf76a9e26b8e701fb8244bb60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 24 Jan 2005 19:42:54 +0000 Subject: [PATCH] IoCreateFile should be passed kernelmode parameters. svn path=/trunk/; revision=13252 --- reactos/ntoskrnl/include/internal/safe.h | 26 +- reactos/ntoskrnl/io/create.c | 239 ++++++++++-- reactos/ntoskrnl/io/mailslot.c | 120 ++++-- reactos/ntoskrnl/io/npipe.c | 116 +++++- reactos/ntoskrnl/rtl/capture.c | 478 ++++++++++++++++++++++- 5 files changed, 896 insertions(+), 83 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/safe.h b/reactos/ntoskrnl/include/internal/safe.h index 692b4282bdb..87e74453c2c 100644 --- a/reactos/ntoskrnl/include/internal/safe.h +++ b/reactos/ntoskrnl/include/internal/safe.h @@ -21,4 +21,28 @@ RtlReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode, IN BOOLEAN CaptureIfKernel); -#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SAFE_Hb */ +NTSTATUS +RtlCaptureSecurityDescriptor(OUT PSECURITY_DESCRIPTOR Dest, + IN KPROCESSOR_MODE PreviousMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN PSECURITY_DESCRIPTOR UnsafeSrc); + +VOID +RtlReleaseCapturedSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, + IN KPROCESSOR_MODE CurrentMode, + IN BOOLEAN CaptureIfKernel); + +NTSTATUS +RtlCaptureObjectAttributes(OUT POBJECT_ATTRIBUTES Dest, + IN KPROCESSOR_MODE CurrentMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN POBJECT_ATTRIBUTES UnsafeSrc); + +VOID +RtlReleaseCapturedObjectAttributes(IN POBJECT_ATTRIBUTES CapturedObjectAttributes, + IN KPROCESSOR_MODE CurrentMode, + IN BOOLEAN CaptureIfKernel); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SAFE_H */ diff --git a/reactos/ntoskrnl/io/create.c b/reactos/ntoskrnl/io/create.c index 22bf1c37c16..4b287a9f1ef 100644 --- a/reactos/ntoskrnl/io/create.c +++ b/reactos/ntoskrnl/io/create.c @@ -17,7 +17,7 @@ /* GLOBALS *******************************************************************/ -#define TAG_FILE_NAME TAG('F', 'N', 'A', 'M') +#define TAG_IO_CREATE TAG('I', 'O', 'C', 'R') /* FUNCTIONS *************************************************************/ @@ -357,7 +357,7 @@ IoCreateFile(OUT PHANDLE FileHandle, PreviousMode = ExGetPreviousMode(); - Status = ObCreateObject(PreviousMode, + Status = ObCreateObject(KernelMode, IoFileObjectType, ObjectAttributes, PreviousMode, @@ -533,32 +533,132 @@ IoCreateFile(OUT PHANDLE FileHandle, * @implemented */ NTSTATUS STDCALL -NtCreateFile(PHANDLE FileHandle, +NtCreateFile(PHANDLE FileHandleUnsafe, ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PIO_STATUS_BLOCK IoStatusBlock, - PLARGE_INTEGER AllocateSize, + POBJECT_ATTRIBUTES ObjectAttributesUnsafe, + PIO_STATUS_BLOCK IoStatusBlockUnsafe, + PLARGE_INTEGER AllocateSizeUnsafe, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, - PVOID EaBuffer, + PVOID EaBufferUnsafe, ULONG EaLength) { - return IoCreateFile(FileHandle, - DesiredAccess, - ObjectAttributes, - IoStatusBlock, - AllocateSize, - FileAttributes, - ShareAccess, - CreateDisposition, - CreateOptions, - EaBuffer, - EaLength, - CreateFileTypeNone, - NULL, - 0); + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + LARGE_INTEGER AllocateSize; + PVOID EaBuffer; + + PreviousMode = ExGetPreviousMode(); + if (KernelMode == PreviousMode) + { + return IoCreateFile(FileHandleUnsafe, + DesiredAccess, + ObjectAttributesUnsafe, + IoStatusBlockUnsafe, + AllocateSizeUnsafe, + FileAttributes, + ShareAccess, + CreateDisposition, + CreateOptions, + EaBufferUnsafe, + EaLength, + CreateFileTypeNone, + NULL, + 0); + } + + Status = RtlCaptureObjectAttributes(&ObjectAttributes, + PreviousMode, + PagedPool, + FALSE, + ObjectAttributesUnsafe); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + if (0 != EaLength) + { + EaBuffer = ExAllocatePoolWithTag(PagedPool, EaLength, TAG_IO_CREATE); + if (NULL == EaBuffer) + { + RtlReleaseCapturedObjectAttributes(&ObjectAttributes, + PreviousMode, + FALSE); + return STATUS_NO_MEMORY; + } + } + + _SEH_TRY + { + if (NULL != AllocateSizeUnsafe) + { + ProbeForRead(AllocateSizeUnsafe, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + AllocateSize = *AllocateSizeUnsafe; + } + if (0 != EaLength) + { + ProbeForRead(EaBufferUnsafe, + EaLength, + sizeof(UCHAR)); + RtlCopyMemory(EaBuffer, EaBufferUnsafe, EaLength); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (! NT_SUCCESS(Status)) + { + return Status; + } + + Status = IoCreateFile(&FileHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + (NULL == AllocateSizeUnsafe ? NULL : &AllocateSize), + FileAttributes, + ShareAccess, + CreateDisposition, + CreateOptions, + (0 == EaLength ? NULL : EaBuffer), + EaLength, + CreateFileTypeNone, + NULL, + 0); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + _SEH_TRY + { + ProbeForWrite(FileHandleUnsafe, + sizeof(HANDLE), + sizeof(ULONG)); + *FileHandleUnsafe = FileHandle; + ProbeForWrite(IoStatusBlockUnsafe, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + *IoStatusBlockUnsafe = IoStatusBlock; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } @@ -598,27 +698,90 @@ NtCreateFile(PHANDLE FileHandle, * @implemented */ NTSTATUS STDCALL -NtOpenFile(PHANDLE FileHandle, +NtOpenFile(PHANDLE FileHandleUnsafe, ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PIO_STATUS_BLOCK IoStatusBlock, + POBJECT_ATTRIBUTES ObjectAttributesUnsafe, + PIO_STATUS_BLOCK IoStatusBlockUnsafe, ULONG ShareAccess, ULONG OpenOptions) { - return IoCreateFile(FileHandle, - DesiredAccess, - ObjectAttributes, - IoStatusBlock, - NULL, - 0, - ShareAccess, - FILE_OPEN, - OpenOptions, - NULL, - 0, - CreateFileTypeNone, - NULL, - 0); + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + PreviousMode = ExGetPreviousMode(); + if (KernelMode == PreviousMode) + { + return IoCreateFile(FileHandleUnsafe, + DesiredAccess, + ObjectAttributesUnsafe, + IoStatusBlockUnsafe, + NULL, + 0, + ShareAccess, + FILE_OPEN, + OpenOptions, + NULL, + 0, + CreateFileTypeNone, + NULL, + 0); + } + + Status = RtlCaptureObjectAttributes(&ObjectAttributes, + PreviousMode, + PagedPool, + FALSE, + ObjectAttributesUnsafe); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + if (! NT_SUCCESS(Status)) + { + return Status; + } + + Status = IoCreateFile(&FileHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + ShareAccess, + FILE_OPEN, + OpenOptions, + NULL, + 0, + CreateFileTypeNone, + NULL, + 0); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + _SEH_TRY + { + ProbeForWrite(FileHandleUnsafe, + sizeof(HANDLE), + sizeof(ULONG)); + *FileHandleUnsafe = FileHandle; + ProbeForWrite(IoStatusBlockUnsafe, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + *IoStatusBlockUnsafe = IoStatusBlock; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/io/mailslot.c b/reactos/ntoskrnl/io/mailslot.c index aa328408515..27d0bb4ca53 100644 --- a/reactos/ntoskrnl/io/mailslot.c +++ b/reactos/ntoskrnl/io/mailslot.c @@ -18,16 +18,21 @@ /* FUNCTIONS *****************************************************************/ NTSTATUS STDCALL -NtCreateMailslotFile(OUT PHANDLE FileHandle, +NtCreateMailslotFile(OUT PHANDLE FileHandleUnsafe, IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, + IN POBJECT_ATTRIBUTES ObjectAttributesUnsafe, + OUT PIO_STATUS_BLOCK IoStatusBlockUnsafe, IN ULONG CreateOptions, IN ULONG MailslotQuota, IN ULONG MaxMessageSize, - IN PLARGE_INTEGER TimeOut) + IN PLARGE_INTEGER TimeOutUnsafe) { MAILSLOT_CREATE_PARAMETERS Buffer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, " "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", @@ -36,32 +41,103 @@ NtCreateMailslotFile(OUT PHANDLE FileHandle, ASSERT_IRQL(PASSIVE_LEVEL); - if (TimeOut != NULL) + if (TimeOutUnsafe != NULL) { - Buffer.ReadTimeout.QuadPart = TimeOut->QuadPart; - Buffer.TimeoutSpecified = TRUE; + if (UserMode == PreviousMode) + { + Status = STATUS_SUCCESS; + _SEH_TRY + { + ProbeForRead(TimeOutUnsafe, + sizeof(LARGE_INTEGER), + sizeof(LARGE_INTEGER)); + Buffer.ReadTimeout.QuadPart = TimeOutUnsafe->QuadPart; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + else + { + Buffer.ReadTimeout.QuadPart = TimeOutUnsafe->QuadPart; + } + Buffer.TimeoutSpecified = TRUE; } else { - Buffer.TimeoutSpecified = FALSE; + Buffer.TimeoutSpecified = FALSE; } Buffer.MailslotQuota = MailslotQuota; Buffer.MaximumMessageSize = MaxMessageSize; - return IoCreateFile(FileHandle, - DesiredAccess, - ObjectAttributes, - IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_CREATE, - CreateOptions, - NULL, - 0, - CreateFileTypeMailslot, - (PVOID)&Buffer, - 0); + PreviousMode = ExGetPreviousMode(); + if (KernelMode == PreviousMode) + { + return IoCreateFile(FileHandleUnsafe, + DesiredAccess, + ObjectAttributesUnsafe, + IoStatusBlockUnsafe, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + CreateOptions, + NULL, + 0, + CreateFileTypeMailslot, + (PVOID)&Buffer, + 0); + } + + Status = RtlCaptureObjectAttributes(&ObjectAttributes, + PreviousMode, + PagedPool, + FALSE, + ObjectAttributesUnsafe); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + Status = IoCreateFile(&FileHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + CreateOptions, + NULL, + 0, + CreateFileTypeMailslot, + (PVOID)&Buffer, + 0); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + _SEH_TRY + { + ProbeForWrite(FileHandleUnsafe, + sizeof(HANDLE), + sizeof(ULONG)); + *FileHandleUnsafe = FileHandle; + ProbeForWrite(IoStatusBlockUnsafe, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + *IoStatusBlockUnsafe = IoStatusBlock; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/io/npipe.c b/reactos/ntoskrnl/io/npipe.c index fe1e1879b90..693f1c760f7 100644 --- a/reactos/ntoskrnl/io/npipe.c +++ b/reactos/ntoskrnl/io/npipe.c @@ -17,10 +17,10 @@ /* FUNCTIONS *****************************************************************/ NTSTATUS STDCALL -NtCreateNamedPipeFile(PHANDLE FileHandle, +NtCreateNamedPipeFile(PHANDLE FileHandleUnsafe, ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - PIO_STATUS_BLOCK IoStatusBlock, + POBJECT_ATTRIBUTES ObjectAttributesUnsafe, + PIO_STATUS_BLOCK IoStatusBlockUnsafe, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, @@ -30,9 +30,14 @@ NtCreateNamedPipeFile(PHANDLE FileHandle, ULONG MaximumInstances, ULONG InboundQuota, ULONG OutboundQuota, - PLARGE_INTEGER DefaultTimeout) + PLARGE_INTEGER DefaultTimeoutUnsafe) { NAMED_PIPE_CREATE_PARAMETERS Buffer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, " "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", @@ -41,9 +46,28 @@ NtCreateNamedPipeFile(PHANDLE FileHandle, ASSERT_IRQL(PASSIVE_LEVEL); - if (DefaultTimeout != NULL) + if (DefaultTimeoutUnsafe != NULL) { - Buffer.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart; + if (UserMode == PreviousMode) + { + Status = STATUS_SUCCESS; + _SEH_TRY + { + ProbeForRead(DefaultTimeoutUnsafe, + sizeof(LARGE_INTEGER), + sizeof(LARGE_INTEGER)); + Buffer.DefaultTimeout.QuadPart = DefaultTimeoutUnsafe->QuadPart; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + else + { + Buffer.DefaultTimeout.QuadPart = DefaultTimeoutUnsafe->QuadPart; + } Buffer.TimeoutSpecified = TRUE; } else @@ -57,20 +81,72 @@ NtCreateNamedPipeFile(PHANDLE FileHandle, Buffer.InboundQuota = InboundQuota; Buffer.OutboundQuota = OutboundQuota; - return IoCreateFile(FileHandle, - DesiredAccess, - ObjectAttributes, - IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - ShareAccess, - CreateDisposition, - CreateOptions, - NULL, - 0, - CreateFileTypeNamedPipe, - (PVOID)&Buffer, - 0); + PreviousMode = ExGetPreviousMode(); + if (KernelMode == PreviousMode) + { + return IoCreateFile(FileHandleUnsafe, + DesiredAccess, + ObjectAttributesUnsafe, + IoStatusBlockUnsafe, + NULL, + FILE_ATTRIBUTE_NORMAL, + ShareAccess, + CreateDisposition, + CreateOptions, + NULL, + 0, + CreateFileTypeNamedPipe, + (PVOID)&Buffer, + 0); + } + + Status = RtlCaptureObjectAttributes(&ObjectAttributes, + PreviousMode, + PagedPool, + FALSE, + ObjectAttributesUnsafe); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + Status = IoCreateFile(&FileHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + ShareAccess, + CreateDisposition, + CreateOptions, + NULL, + 0, + CreateFileTypeNamedPipe, + (PVOID)&Buffer, + 0); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + _SEH_TRY + { + ProbeForWrite(FileHandleUnsafe, + sizeof(HANDLE), + sizeof(ULONG)); + *FileHandleUnsafe = FileHandle; + ProbeForWrite(IoStatusBlockUnsafe, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + *IoStatusBlockUnsafe = IoStatusBlock; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/rtl/capture.c b/reactos/ntoskrnl/rtl/capture.c index 05238bfe118..e825eab784c 100644 --- a/reactos/ntoskrnl/rtl/capture.c +++ b/reactos/ntoskrnl/rtl/capture.c @@ -32,6 +32,8 @@ #define NDEBUG #include +#define TAG_CAPT TAG('C', 'A', 'P', 'T') + /* FUNCTIONS *****************************************************************/ NTSTATUS @@ -95,7 +97,7 @@ RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest, if(Src.Length > 0) { Dest->MaximumLength = Src.Length + sizeof(WCHAR); - Dest->Buffer = ExAllocatePool(PoolType, Dest->MaximumLength); + Dest->Buffer = ExAllocatePoolWithTag(PoolType, Dest->MaximumLength, TAG_CAPT); if (Dest->Buffer == NULL) { Dest->Length = Dest->MaximumLength = 0; @@ -164,7 +166,7 @@ RtlCaptureAnsiString(PANSI_STRING Dest, */ Dest->Length = Src->Length; Dest->MaximumLength = Src->MaximumLength; - Dest->Buffer = ExAllocatePool(NonPagedPool, Dest->MaximumLength); + Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->MaximumLength, TAG_CAPT); if (Dest->Buffer == NULL) { return(Status); @@ -183,6 +185,478 @@ RtlCaptureAnsiString(PANSI_STRING Dest, return(STATUS_SUCCESS); } +static NTSTATUS +CaptureSID(OUT PSID *Dest, + IN KPROCESSOR_MODE PreviousMode, + IN POOL_TYPE PoolType, + IN PSID UnsafeSrc) +{ + SID Src; + ULONG Length; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT(Dest != NULL); + + if(UserMode == PreviousMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + sizeof(SID), + sizeof(ULONG)); + RtlCopyMemory(&Src, UnsafeSrc, sizeof(SID)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + /* capture even though it is considered to be valid */ + RtlCopyMemory(&Src, UnsafeSrc, sizeof(SID)); + } + + if(SID_REVISION != Src.Revision) + { + return STATUS_INVALID_PARAMETER; + } + + Length = RtlLengthSid(&Src); + *Dest = ExAllocatePoolWithTag(PoolType, Length, TAG_CAPT); + if(NULL == *Dest) + { + return STATUS_NO_MEMORY; + } + + if(UserMode == PreviousMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + Length, + sizeof(ULONG)); + RtlCopyMemory(*Dest, UnsafeSrc, Length); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + RtlCopyMemory(*Dest, UnsafeSrc, Length); + } + + return Status; +} + +static NTSTATUS +CaptureACL(OUT PACL *Dest, + IN KPROCESSOR_MODE PreviousMode, + IN POOL_TYPE PoolType, + IN PACL UnsafeSrc) +{ + ACL Src; + ULONG Length; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT(Dest != NULL); + + if(UserMode == PreviousMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + sizeof(ACL), + sizeof(ULONG)); + RtlCopyMemory(&Src, UnsafeSrc, sizeof(ACL)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + /* capture even though it is considered to be valid */ + RtlCopyMemory(&Src, UnsafeSrc, sizeof(ACL)); + } + + if(Src.AclRevision < MIN_ACL_REVISION || MAX_ACL_REVISION < Src.AclRevision) + { + return STATUS_INVALID_PARAMETER; + } + + Length = Src.AclSize; + *Dest = ExAllocatePoolWithTag(PoolType, Length, TAG_CAPT); + if(NULL == *Dest) + { + return STATUS_NO_MEMORY; + } + + if(UserMode == PreviousMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + Length, + sizeof(ULONG)); + RtlCopyMemory(*Dest, UnsafeSrc, Length); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + RtlCopyMemory(*Dest, UnsafeSrc, Length); + } + + return Status; +} + +NTSTATUS +RtlCaptureSecurityDescriptor(OUT PSECURITY_DESCRIPTOR Dest, + IN KPROCESSOR_MODE PreviousMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN PSECURITY_DESCRIPTOR UnsafeSrc) +{ + SECURITY_DESCRIPTOR Src; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT(Dest != NULL); + + /* + * Copy the object attributes to kernel space. + */ + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + sizeof(SECURITY_DESCRIPTOR), + sizeof(ULONG)); + Src = *UnsafeSrc; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else if(!CaptureIfKernel) + { + /* just copy the structure, the pointers are considered valid */ + *Dest = *UnsafeSrc; + return STATUS_SUCCESS; + } + else + { + /* capture the object attributes even though it is considered to be valid */ + Src = *UnsafeSrc; + } + + if(SECURITY_DESCRIPTOR_REVISION1 != Src.Revision) + { + return STATUS_INVALID_PARAMETER; + } + + Dest->Revision = Src.Revision; + Dest->Sbz1 = Src.Sbz1; + Dest->Control = Src.Control; + Status = CaptureSID(&Dest->Owner, PreviousMode, PoolType, Src.Owner); + if(!NT_SUCCESS(Status)) + { + return Status; + } + Status = CaptureSID(&Dest->Group, PreviousMode, PoolType, Src.Group); + if(!NT_SUCCESS(Status)) + { + if(NULL != Dest->Owner) + { + ExFreePool(Dest->Owner); + } + return Status; + } + Status = CaptureACL(&Dest->Sacl, PreviousMode, PoolType, Src.Sacl); + if(!NT_SUCCESS(Status)) + { + if(NULL != Dest->Group) + { + ExFreePool(Dest->Group); + } + if(NULL != Dest->Owner) + { + ExFreePool(Dest->Owner); + } + return Status; + } + Status = CaptureACL(&Dest->Dacl, PreviousMode, PoolType, Src.Dacl); + if(!NT_SUCCESS(Status)) + { + if(NULL != Dest->Sacl) + { + ExFreePool(Dest->Sacl); + } + if(NULL != Dest->Group) + { + ExFreePool(Dest->Group); + } + if(NULL != Dest->Owner) + { + ExFreePool(Dest->Owner); + } + return Status; + } + + return Status; +} + +VOID +RtlReleaseCapturedSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor, + IN KPROCESSOR_MODE PreviousMode, + IN BOOLEAN CaptureIfKernel) +{ + ASSERT(SECURITY_DESCRIPTOR_REVISION1 == CapturedSecurityDescriptor->Revision); + + if(PreviousMode == KernelMode && !CaptureIfKernel) + { + return; + } + + if(NULL != CapturedSecurityDescriptor->Dacl) + { + ExFreePool(CapturedSecurityDescriptor->Dacl); + } + if(NULL != CapturedSecurityDescriptor->Sacl) + { + ExFreePool(CapturedSecurityDescriptor->Sacl); + } + if(NULL != CapturedSecurityDescriptor->Group) + { + ExFreePool(CapturedSecurityDescriptor->Group); + } + if(NULL != CapturedSecurityDescriptor->Owner) + { + ExFreePool(CapturedSecurityDescriptor->Owner); + } +} + +NTSTATUS +RtlCaptureObjectAttributes(OUT POBJECT_ATTRIBUTES Dest, + IN KPROCESSOR_MODE PreviousMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN POBJECT_ATTRIBUTES UnsafeSrc) +{ + OBJECT_ATTRIBUTES Src; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT(Dest != NULL); + + /* + * Copy the object attributes to kernel space. + */ + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForRead(UnsafeSrc, + sizeof(OBJECT_ATTRIBUTES), + sizeof(ULONG)); + Src = *UnsafeSrc; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else if(!CaptureIfKernel) + { + /* just copy the structure, the pointers are considered valid */ + *Dest = *UnsafeSrc; + return STATUS_SUCCESS; + } + else + { + /* capture the object attributes even though it is considered to be valid */ + Src = *UnsafeSrc; + } + + if(Src.Length < sizeof(OBJECT_ATTRIBUTES) || NULL == Src.ObjectName) + { + return STATUS_INVALID_PARAMETER; + } + + Dest->Length = sizeof(OBJECT_ATTRIBUTES); + Dest->RootDirectory = Src.RootDirectory; + Dest->ObjectName = ExAllocatePoolWithTag(PoolType, sizeof(UNICODE_STRING), TAG_CAPT); + if(NULL == Dest->ObjectName) + { + return STATUS_NO_MEMORY; + } + Status = RtlCaptureUnicodeString(Dest->ObjectName, + PreviousMode, + PoolType, + CaptureIfKernel, + Src.ObjectName); + if(!NT_SUCCESS(Status)) + { + ExFreePool(Dest->ObjectName); + return Status; + } + Dest->Attributes = Src.Attributes; + if(NULL == Src.SecurityDescriptor) + { + Dest->SecurityDescriptor = NULL; + } + else + { + Dest->SecurityDescriptor = ExAllocatePoolWithTag(PoolType, sizeof(SECURITY_DESCRIPTOR), TAG_CAPT); + if(NULL == Dest->SecurityDescriptor) + { + RtlReleaseCapturedUnicodeString(Dest->ObjectName, + PreviousMode, + CaptureIfKernel); + ExFreePool(Dest->ObjectName); + return STATUS_NO_MEMORY; + } + Status = RtlCaptureSecurityDescriptor(Dest->SecurityDescriptor, + PreviousMode, + PoolType, + CaptureIfKernel, + Src.SecurityDescriptor); + if(!NT_SUCCESS(Status)) + { + ExFreePool(Dest->SecurityDescriptor); + RtlReleaseCapturedUnicodeString(Dest->ObjectName, + PreviousMode, + CaptureIfKernel); + ExFreePool(Dest->ObjectName); + return Status; + } + } + if(NULL == Src.SecurityQualityOfService) + { + Dest->SecurityQualityOfService = NULL; + } + else + { + Dest->SecurityQualityOfService = ExAllocatePoolWithTag(PoolType, sizeof(SECURITY_QUALITY_OF_SERVICE), TAG_CAPT); + if(NULL == Dest->SecurityQualityOfService) + { + Status = STATUS_NO_MEMORY; + } + else + { + /* + * Copy the data to kernel space. + */ + _SEH_TRY + { + RtlCopyMemory(Dest->SecurityQualityOfService, + Src.SecurityQualityOfService, + sizeof(SECURITY_QUALITY_OF_SERVICE)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + if(!NT_SUCCESS(Status)) + { + ExFreePool(Dest->SecurityQualityOfService); + } + } + if(!NT_SUCCESS(Status)) + { + if(NULL != Dest->SecurityDescriptor) + { + RtlReleaseCapturedSecurityDescriptor(Dest->SecurityDescriptor, + PreviousMode, + CaptureIfKernel); + ExFreePool(Dest->SecurityDescriptor); + } + RtlReleaseCapturedUnicodeString(Dest->ObjectName, + PreviousMode, + CaptureIfKernel); + ExFreePool(Dest->ObjectName); + return Status; + } + } + + return Status; +} + +VOID +RtlReleaseCapturedObjectAttributes(IN POBJECT_ATTRIBUTES CapturedObjectAttributes, + IN KPROCESSOR_MODE PreviousMode, + IN BOOLEAN CaptureIfKernel) +{ + ASSERT(NULL != CapturedObjectAttributes->ObjectName); + + if(PreviousMode == KernelMode && !CaptureIfKernel) + { + return; + } + + if(NULL != CapturedObjectAttributes->SecurityQualityOfService) + { + ExFreePool(CapturedObjectAttributes->SecurityQualityOfService); + } + if(NULL != CapturedObjectAttributes->SecurityDescriptor) + { + RtlReleaseCapturedSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor, + PreviousMode, + CaptureIfKernel); + ExFreePool(CapturedObjectAttributes->SecurityDescriptor); + } + RtlReleaseCapturedUnicodeString(CapturedObjectAttributes->ObjectName, + PreviousMode, + CaptureIfKernel); + ExFreePool(CapturedObjectAttributes->ObjectName); +} + /* * @unimplemented */