1. A few Nt vs. Zw fixes

2. Fixed and extended RtlCaptureUnicodeString()
3. securely access buffers in NtQuerySystemEnvironmentValue() and NtSetSystemEnvironmentValue() and check for required SeSystemEnvironmentPrivilege privilege

svn path=/trunk/; revision=13208
This commit is contained in:
Thomas Bluemel 2005-01-22 12:20:12 +00:00
parent 9fbbec950f
commit 72ae3c4197
9 changed files with 294 additions and 243 deletions

View file

@ -139,7 +139,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
0 );
allocsize.u.LowPart = allocsize.u.HighPart = 0;
Status = NtOpenFile( &file,
Status = ZwOpenFile( &file,
GENERIC_READ,
&objattr,
&iosb,
@ -157,7 +157,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
0,
0,
0 );
Status = NtCreateEvent( &event,
Status = ZwCreateEvent( &event,
0,
&objattr,
NotificationEvent,
@ -168,7 +168,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
goto cleanfile;
}
Status = NtQueryInformationFile( file,
Status = ZwQueryInformationFile( file,
&iosb,
&finfo,
sizeof( finfo ),
@ -187,7 +187,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
goto cleanevent;
}
Status = NtReadFile( file,
Status = ZwReadFile( file,
event,
0,
0,
@ -202,7 +202,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
DPRINT( "Failed to read floppy\n" );
goto cleantbuff;
}
Status = NtWaitForSingleObject( event, FALSE, 0 );
Status = ZwWaitForSingleObject( event, FALSE, 0 );
if( Status != STATUS_WAIT_0 || !NT_SUCCESS( iosb.Status ) )
{
DPRINT( "Failed to read floppy\n" );
@ -221,16 +221,16 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
}
else DbgPrint( "RAMDRV: Failed to decomparess image, error: %d\n", err );
ExFreePool( tbuff );
NtClose( file );
NtClose( event );
ZwClose( file );
ZwClose( event );
return STATUS_SUCCESS;
cleantbuff:
ExFreePool( tbuff );
cleanevent:
NtClose( event );
ZwClose( event );
cleanfile:
NtClose( file );
ZwClose( file );
cleanbuffer:
ExFreePool( devext->Buffer );

View file

@ -3107,19 +3107,19 @@ ZwQuerySymbolicLinkObject(
NTSTATUS
STDCALL
NtQuerySystemEnvironmentValue(
IN PUNICODE_STRING Name,
OUT PVOID Value,
ULONG Length,
PULONG ReturnLength
IN PUNICODE_STRING VariableName,
OUT PWSTR ValueBuffer,
IN ULONG ValueBufferLength,
OUT PULONG ReturnLength OPTIONAL
);
NTSTATUS
STDCALL
ZwQuerySystemEnvironmentValue(
IN PUNICODE_STRING Name,
OUT PVOID Value,
ULONG Length,
PULONG ReturnLength
IN PUNICODE_STRING VariableName,
OUT PWSTR ValueBuffer,
IN ULONG ValueBufferLength,
OUT PULONG ReturnLength OPTIONAL
);

View file

@ -90,10 +90,10 @@ ExGetCurrentProcessorCounts (
}
NTSTATUS STDCALL
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
OUT PVOID UnsafeValue,
IN ULONG Length,
IN OUT PULONG UnsafeReturnLength)
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
OUT PWCHAR ValueBuffer,
IN ULONG ValueBufferLength,
IN OUT PULONG ReturnLength OPTIONAL)
{
NTSTATUS Status;
ANSI_STRING AName;
@ -102,225 +102,197 @@ NtQuerySystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
PCH Value;
ANSI_STRING AValue;
UNICODE_STRING WValue;
ULONG ReturnLength;
KPROCESSOR_MODE PreviousMode;
PreviousMode = ExGetPreviousMode();
/*
* Copy the name to kernel space if necessary and convert it to ANSI.
*/
if (ExGetPreviousMode() != KernelMode)
Status = RtlCaptureUnicodeString(&WName,
PreviousMode,
NonPagedPool,
FALSE,
VariableName);
if(NT_SUCCESS(Status))
{
if(PreviousMode != KernelMode)
{
Status = RtlCaptureUnicodeString(&WName, UnsafeName);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
ProbeForWrite(ValueBuffer,
ValueBufferLength,
sizeof(WCHAR));
if(ReturnLength != NULL)
{
ProbeForWrite(ReturnLength,
sizeof(ULONG),
sizeof(ULONG));
}
}
else
/*
* according to ntinternals the SeSystemEnvironmentName privilege is required!
*/
if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
PreviousMode))
{
Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
RtlRelaseCapturedUnicodeString(&WName,
PreviousMode,
FALSE);
return STATUS_PRIVILEGE_NOT_HELD;
}
/*
* convert the value name to ansi
*/
Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
RtlRelaseCapturedUnicodeString(&WName,
PreviousMode,
FALSE);
if(!NT_SUCCESS(Status))
{
return Status;
}
/*
* Create a temporary buffer for the value
*/
Value = ExAllocatePool(NonPagedPool, Length);
if (Value == NULL)
Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
if (Value == NULL)
{
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
}
return(STATUS_NO_MEMORY);
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* Get the environment variable
*/
Result = HalGetEnvironmentVariable(AName.Buffer, Value, Length);
if (!Result)
/*
* Get the environment variable
*/
Result = HalGetEnvironmentVariable(AName.Buffer, Value, ValueBufferLength);
if(!Result)
{
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
}
ExFreePool(Value);
return(STATUS_UNSUCCESSFUL);
return STATUS_UNSUCCESSFUL;
}
/*
* Convert the result to UNICODE.
*/
RtlInitAnsiString(&AValue, Value);
Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
if (!NT_SUCCESS(Status))
/*
* Convert the result to UNICODE, protect with SEH in case the value buffer
* isn't NULL-terminated!
*/
_SEH_TRY
{
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
}
ExFreePool(Value);
return(Status);
RtlInitAnsiString(&AValue, Value);
Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
}
ReturnLength = WValue.Length;
/*
* Copy the result back to the caller.
*/
if (ExGetPreviousMode() != KernelMode)
_SEH_HANDLE
{
Status = MmCopyToCaller(UnsafeValue, WValue.Buffer, ReturnLength);
if (!NT_SUCCESS(Status))
{
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
}
ExFreePool(Value);
RtlFreeUnicodeString(&WValue);
return(Status);
}
Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
}
ExFreePool(Value);
RtlFreeUnicodeString(&WValue);
return(Status);
}
Status = _SEH_GetExceptionCode();
}
else
_SEH_END;
if(NT_SUCCESS(Status))
{
memcpy(UnsafeValue, WValue.Buffer, ReturnLength);
memcpy(UnsafeReturnLength, &ReturnLength, sizeof(ULONG));
}
/*
* Copy the result back to the caller.
*/
_SEH_TRY
{
RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
if(ReturnLength != NULL)
{
*ReturnLength = WValue.Length + sizeof(WCHAR);
}
/*
* Free temporary buffers.
*/
RtlFreeAnsiString(&AName);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
Status = STATUS_SUCCESS;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
ExFreePool(Value);
RtlFreeUnicodeString(&WValue);
/*
* Cleanup allocated resources.
*/
RtlFreeAnsiString(&AName);
ExFreePool(Value);
}
return(STATUS_SUCCESS);
return Status;
}
NTSTATUS STDCALL
NtSetSystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
IN PUNICODE_STRING UnsafeValue)
NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
IN PUNICODE_STRING Value)
{
UNICODE_STRING WName;
ANSI_STRING AName;
UNICODE_STRING WValue;
ANSI_STRING AValue;
BOOLEAN Result;
UNICODE_STRING CapturedName, CapturedValue;
ANSI_STRING AName, AValue;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PreviousMode = ExGetPreviousMode();
/*
* Check for required privilege.
* Copy the strings to kernel space if necessary
*/
/* FIXME: Not implemented. */
Status = RtlCaptureUnicodeString(&CapturedName,
PreviousMode,
NonPagedPool,
FALSE,
VariableName);
if(NT_SUCCESS(Status))
{
Status = RtlCaptureUnicodeString(&CapturedValue,
PreviousMode,
NonPagedPool,
FALSE,
Value);
if(NT_SUCCESS(Status))
{
/*
* according to ntinternals the SeSystemEnvironmentName privilege is required!
*/
if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
PreviousMode))
{
/*
* convert the strings to ANSI
*/
Status = RtlUnicodeStringToAnsiString(&AName,
&CapturedName,
TRUE);
if(NT_SUCCESS(Status))
{
Status = RtlUnicodeStringToAnsiString(&AValue,
&CapturedValue,
TRUE);
if(NT_SUCCESS(Status))
{
BOOLEAN Result = HalSetEnvironmentVariable(AName.Buffer,
AValue.Buffer);
/*
* Copy the name to kernel space if necessary and convert it to ANSI.
*/
if (ExGetPreviousMode() != KernelMode)
{
Status = RtlCaptureUnicodeString(&WName, UnsafeName);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
}
else
{
Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
}
}
else
{
Status = STATUS_PRIVILEGE_NOT_HELD;
}
RtlRelaseCapturedUnicodeString(&CapturedValue,
PreviousMode,
FALSE);
}
/*
* Copy the value to kernel space and convert to ANSI.
*/
if (ExGetPreviousMode() != KernelMode)
{
Status = RtlCaptureUnicodeString(&WValue, UnsafeValue);
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(&WName);
RtlFreeAnsiString(&AName);
return(Status);
}
Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString(&WName);
RtlFreeAnsiString(&AName);
RtlFreeUnicodeString(&WValue);
return(Status);
}
}
else
{
Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
if (!NT_SUCCESS(Status))
{
RtlFreeAnsiString(&AName);
return(Status);
}
}
/*
* Set the environment variable
*/
Result = HalSetEnvironmentVariable(AName.Buffer, AValue.Buffer);
/*
* Free everything and return status.
*/
RtlFreeAnsiString(&AName);
RtlFreeAnsiString(&AValue);
if (ExGetPreviousMode() != KernelMode)
{
RtlFreeUnicodeString(&WName);
RtlFreeUnicodeString(&WValue);
}
if (!Result)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
RtlRelaseCapturedUnicodeString(&CapturedName,
PreviousMode,
FALSE);
}
return Status;
}

View file

@ -10,7 +10,15 @@ NTSTATUS STDCALL
MmCopyToCaller(PVOID Dest, const VOID *Src, ULONG NumberOfBytes);
NTSTATUS
RtlCaptureUnicodeString(PUNICODE_STRING Dest,
PUNICODE_STRING UnsafeSrc);
RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest,
IN KPROCESSOR_MODE CurrentMode,
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
IN PUNICODE_STRING UnsafeSrc);
VOID
RtlRelaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
IN KPROCESSOR_MODE CurrentMode,
IN BOOLEAN CaptureIfKernel);
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SAFE_Hb */

View file

@ -34,7 +34,7 @@ IoCreateNotificationEvent(PUNICODE_STRING EventName,
NULL,
NULL);
Status = NtCreateEvent(&Handle,
Status = ZwCreateEvent(&Handle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
NotificationEvent,
@ -65,21 +65,40 @@ IoCreateSynchronizationEvent(PUNICODE_STRING EventName,
PHANDLE EventHandle)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING CapturedEventName;
KPROCESSOR_MODE PreviousMode;
PKEVENT Event;
HANDLE Handle;
NTSTATUS Status;
PreviousMode = ExGetPreviousMode();
Status = RtlCaptureUnicodeString(&CapturedEventName,
PreviousMode,
NonPagedPool,
FALSE,
EventName);
if (!NT_SUCCESS(Status))
{
return NULL;
}
InitializeObjectAttributes(&ObjectAttributes,
EventName,
&CapturedEventName,
OBJ_OPENIF,
NULL,
NULL);
Status = NtCreateEvent(&Handle,
Status = ZwCreateEvent(&Handle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
TRUE);
RtlRelaseCapturedUnicodeString(&CapturedEventName,
PreviousMode,
FALSE);
if (!NT_SUCCESS(Status))
{
return NULL;

View file

@ -748,7 +748,7 @@ ExpInitializeExecutive(VOID)
0,
NULL,
NULL);
Status = NtCreateEvent(&InitDoneEventHandle,
Status = ZwCreateEvent(&InitDoneEventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
@ -778,7 +778,7 @@ ExpInitializeExecutive(VOID)
/* Wait for the system to be initialized */
Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
Status = ZwWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
Handles,
WaitAny,
FALSE, /* Non-alertable */
@ -804,9 +804,9 @@ ExpInitializeExecutive(VOID)
InbvEnableBootDriver(FALSE);
}
NtSetEvent(InitDoneEventHandle, NULL);
ZwSetEvent(InitDoneEventHandle, NULL);
NtClose(InitDoneEventHandle);
ZwClose(InitDoneEventHandle);
}
else
{
@ -820,7 +820,7 @@ ExpInitializeExecutive(VOID)
* Crash the system if the initial process terminates within 5 seconds.
*/
Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
Status = NtWaitForSingleObject(ProcessHandle,
Status = ZwWaitForSingleObject(ProcessHandle,
FALSE,
&Timeout);
if (Status != STATUS_TIMEOUT)
@ -834,8 +834,8 @@ ExpInitializeExecutive(VOID)
KiTimerSystemAuditing = 1;
NtClose(ThreadHandle);
NtClose(ProcessHandle);
ZwClose(ThreadHandle);
ZwClose(ProcessHandle);
}
VOID __attribute((noinline))

View file

@ -35,43 +35,95 @@
/* FUNCTIONS *****************************************************************/
NTSTATUS
RtlCaptureUnicodeString(PUNICODE_STRING Dest,
PUNICODE_STRING UnsafeSrc)
RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest,
IN KPROCESSOR_MODE CurrentMode,
IN POOL_TYPE PoolType,
IN BOOLEAN CaptureIfKernel,
IN PUNICODE_STRING UnsafeSrc)
{
PUNICODE_STRING Src;
NTSTATUS Status;
UNICODE_STRING Src;
NTSTATUS Status = STATUS_SUCCESS;
ASSERT(Dest != NULL);
/*
* Copy the source string structure to kernel space.
*/
Status = MmCopyFromCaller(&Src, UnsafeSrc, sizeof(UNICODE_STRING));
if (!NT_SUCCESS(Status))
if(CurrentMode == UserMode)
{
_SEH_TRY
{
return(Status);
ProbeForRead(UnsafeSrc,
sizeof(UNICODE_STRING),
sizeof(ULONG));
Src = *UnsafeSrc;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
else if(!CaptureIfKernel)
{
/* just copy the UNICODE_STRING structure, the pointers are considered valid */
*Dest = *UnsafeSrc;
return STATUS_SUCCESS;
}
else
{
/* capture the string even though it is considered to be valid */
Src = *UnsafeSrc;
}
/*
* Initialize the destination string.
*/
Dest->Length = Src->Length;
Dest->MaximumLength = Src->MaximumLength;
Dest->Buffer = ExAllocatePool(NonPagedPool, Dest->MaximumLength);
Dest->Length = Src.Length;
Dest->MaximumLength = Src.Length + sizeof(WCHAR);
Dest->Buffer = ExAllocatePool(PoolType, Dest->MaximumLength);
if (Dest->Buffer == NULL)
{
return(STATUS_NO_MEMORY);
}
{
Dest->Length = Dest->MaximumLength = 0;
Dest->Buffer = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* Copy the source string to kernel space.
*/
Status = MmCopyFromCaller(Dest->Buffer, Src->Buffer, Dest->Length);
if (!NT_SUCCESS(Status))
if(Src.Length > 0)
{
_SEH_TRY
{
ExFreePool(Dest->Buffer);
return(Status);
RtlCopyMemory(Dest->Buffer, Src.Buffer, Src.Length);
Dest->Buffer[Src.Length / sizeof(WCHAR)] = L'\0';
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
return(STATUS_SUCCESS);
VOID
RtlRelaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString,
IN KPROCESSOR_MODE CurrentMode,
IN BOOLEAN CaptureIfKernel)
{
if(CurrentMode != KernelMode || CaptureIfKernel )
{
RtlFreeUnicodeString(CapturedString);
}
}
NTSTATUS

View file

@ -84,7 +84,7 @@ SeInitSRM(VOID)
OBJ_PERMANENT,
0,
NULL);
Status = NtCreateDirectoryObject(&DirectoryHandle,
Status = ZwCreateDirectoryObject(&DirectoryHandle,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
@ -101,7 +101,7 @@ SeInitSRM(VOID)
OBJ_PERMANENT,
DirectoryHandle,
SePublicDefaultSd);
Status = NtCreateEvent(&EventHandle,
Status = ZwCreateEvent(&EventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
@ -113,8 +113,8 @@ SeInitSRM(VOID)
return FALSE;
}
NtClose(EventHandle);
NtClose(DirectoryHandle);
ZwClose(EventHandle);
ZwClose(DirectoryHandle);
/* FIXME: Create SRM port and listener thread */

View file

@ -735,16 +735,16 @@ NTOSAPI
NTSTATUS
NTAPI
ZwQuerySystemEnvironmentValue(
IN PUNICODE_STRING Name,
OUT PVOID Value,
IN ULONG ValueLength,
OUT PULONG ReturnLength OPTIONAL);
IN PUNICODE_STRING VariableName,
OUT PWSTR ValueBuffer,
IN ULONG ValueBufferLength,
OUT PULONG ReturnLength OPTIONAL);
NTOSAPI
NTSTATUS
NTAPI
ZwSetSystemEnvironmentValue(
IN PUNICODE_STRING Name,
IN PUNICODE_STRING VariableName,
IN PUNICODE_STRING Value);
typedef enum _SHUTDOWN_ACTION {