+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Internal header containing information class probing helpers
+ * COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org>
+ */
+
#pragma once
#include <reactos/probe.h>
+/**
+ * @brief
+ * Probe helper that validates the provided parameters whenever
+ * a NtSet*** system call is invoked from user or kernel mode.
+ *
+ * @param[in] Class
+ * The specific class information that the caller explicitly
+ * requested information to be set into an object.
+ *
+ * @param[in] ClassList
+ * An internal INFORMATION_CLASS_INFO consisting of a list array
+ * of information classes checked against the requested information
+ * classes given in Class parameter.
+ *
+ * @param[in] ClassListEntries
+ * Specifies the number of class entries in an array, provided by
+ * the ClassList parameter.
+ *
+ * @param[in] Buffer
+ * A pointer to an arbitrary data content in memory to be validated.
+ * Such pointer points to the actual arbitrary information class buffer
+ * to be set into the object. This buffer is validated only if the
+ * calling processor mode is UM (aka user mode).
+ *
+ * @param[in] BufferLength
+ * The length of the buffer pointed by the Buffer parameter, whose size
+ * is in bytes.
+ *
+ * @param[in] PreviousMode
+ * The processor calling level mode. This level mode determines the procedure
+ * of probing validation in action. If the level calling mode is KM (aka kernel mode)
+ * this function will only validate the properties of the information class itself
+ * such as the required information length size. If the calling mode is UM, the
+ * pointer buffer provided by Buffer parameter is also validated.
+ *
+ * @return
+ * The outcome of the probe validation is based upon the returned NTSTATUS code.
+ * STATUS_SUCCESS is returned if the validation succeeded. Otherwise, one of the
+ * following failure status codes is returned:
+ *
+ * STATUS_INVALID_INFO_CLASS -- Indicates the given information class is not a valid
+ * valid SET class (ICIF_SET flag is not set to the corresponding information class)
+ * or the actual class is not present in the class list array.
+ *
+ * STATUS_INFO_LENGTH_MISMATCH -- Indicates the information length doesn't match with
+ * the one that the information class itself expects. This is the case with classes
+ * ICIF_SET_SIZE_VARIABLE is not set, which means that the class requires a fixed
+ * length size.
+ *
+ * STATUS_ACCESS_VIOLATION -- Indicates the buffer is not within the user mode probe
+ * address range. The function will raise an exception.
+ *
+ * STATUS_DATATYPE_MISALIGNMENT -- Indicates the address of the buffer in memory is
+ * not aligned to the required alignment set.
+ */
static
__inline
NTSTATUS
-DefaultSetInfoBufferCheck(ULONG Class,
- const INFORMATION_CLASS_INFO *ClassList,
- ULONG ClassListEntries,
- PVOID Buffer,
- ULONG BufferLength,
- KPROCESSOR_MODE PreviousMode)
+DefaultSetInfoBufferCheck(
+ _In_ ULONG Class,
+ _In_ const INFORMATION_CLASS_INFO *ClassList,
+ _In_ ULONG ClassListEntries,
+ _In_ PVOID Buffer,
+ _In_ ULONG BufferLength,
+ _In_ KPROCESSOR_MODE PreviousMode)
{
NTSTATUS Status = STATUS_SUCCESS;
return Status;
}
+/**
+ * @brief
+ * Probe helper that validates the provided parameters whenever
+ * a NtQuery*** system call is invoked from user or kernel mode.
+ *
+ * @param[in] Class
+ * The specific class information that the caller explicitly
+ * requested information to be queried from an object.
+ *
+ * @param[in] ClassList
+ * An internal INFORMATION_CLASS_INFO consisting of a list array
+ * of information classes checked against the requested information
+ * classes given in Class parameter.
+ *
+ * @param[in] ClassListEntries
+ * Specifies the number of class entries in an array, provided by
+ * the ClassList parameter.
+ *
+ * @param[in] Flags
+ * Specifies a bit mask flag that influences how the query probe
+ * validation must be performed against Buffer and ReturnLength
+ * parameters. For further information in regard of this parameter,
+ * see remarks.
+ *
+ * @param[in] Buffer
+ * A pointer to an arbitrary data content in memory to be validated.
+ * Such parameter must be an initialized variable where the queried
+ * information is going to be received into this pointer. If the calling
+ * processor mode is UM (aka user mode) this parameter is validated.
+ * This parameter can be NULL (see remarks for more details).
+ *
+ * @param[in] BufferLength
+ * The length of the buffer pointed by the Buffer parameter, whose size
+ * is in bytes. If the Buffer parameter is NULL, this parameter can be 0.
+ *
+ * @param[in] ReturnLength
+ * The returned length of the buffer whose size is in bytes. If Buffer is
+ * NULL as well as BufferLength is 0, this parameter receives the actual
+ * return length needed to store the buffer in memory space. If the
+ * processor level calling mode is UM, this parameter is validated.
+ * If ICIF_FORCE_RETURN_LENGTH_PROBE is specified in Flags parameter,
+ * ReturnLength mustn't be NULL (see remarks). Otherwise it can be NULL.
+ *
+ * @param[in] ReturnLengthPtr
+ * This parameter is of the same nature as the ReturnLength one, with the
+ * difference being that the type parameter can be a ULONG on x86 systems
+ * or a ULONGLONG on AMD64 systems. If the processor level calling mode is
+ * UM, this parameter is validated. This parameter is currently unused.
+ *
+ * @param[in] PreviousMode
+ * The processor calling level mode. This level mode determines the procedure
+ * of probing validation in action. If the level calling mode is KM (aka kernel mode)
+ * this function will only validate the properties of the information class itself
+ * such as the required information length size. If the calling mode is UM, the
+ * pointer buffer provided by Buffer parameter is also validated as well as
+ * the return length parameter.
+ *
+ * @return
+ * The outcome of the probe validation is based upon the returned NTSTATUS code.
+ * STATUS_SUCCESS is returned if the validation succeeded. Otherwise, one of the
+ * following failure status codes is returned:
+ *
+ * STATUS_INVALID_INFO_CLASS -- Indicates the given information class is not a valid
+ * QUERY class (ICIF_QUERY flag is not set to the corresponding information class)
+ * or the actual class is not present in the class list array.
+ *
+ * STATUS_INFO_LENGTH_MISMATCH -- Indicates the information length doesn't match with the
+ * one that the information class itself expects. This is the case with classes where
+ * ICIF_QUERY_SIZE_VARIABLE is not set, which means that the class requires a fixed length size.
+ *
+ * STATUS_ACCESS_VIOLATION -- Indicates the buffer is not within the user mode probe address range
+ * or the buffer variable is not writable (see remarks). The function will raise an exception.
+ *
+ * STATUS_DATATYPE_MISALIGNMENT -- Indicates the address of the buffer in memory is not
+ * aligned to the required alignment set.
+ *
+ * @remarks
+ * The probing of Buffer and ReturnLength are influenced based on the probe flags
+ * pointed by Flags parameter. The following flags are:
+ *
+ * ICIF_PROBE_READ_WRITE -- This flag explicitly tells the function to do a read and
+ * write probe against Buffer parameter. ProbeForWrite is invoked in this case.
+ * This is the default mechanism.
+ *
+ * ICIF_PROBE_READ -- This flag explicitly tells the function to do a read probe against
+ * Buffer parameter only, that is, the function does not probe if the parameter is actually
+ * writable. ProbeForRead is invoked in this case.
+ *
+ * ICIF_FORCE_RETURN_LENGTH_PROBE -- If this flag is set, the function will force probe
+ * the ReturnLength parameter. In this scenario if ReturnLength is NULL a STATUS_ACCESS_VIOLATION
+ * exception is raised. NtQueryInformationToken is the only NT system call where ReturnLength
+ * has to be properly initialized and not NULL.
+ *
+ * Buffer parameter can be NULL if the caller does not want to actually query a certain information
+ * from an object. This is typically with query NT syscalls where a caller has to query the actual
+ * buffer length needed to store the queried information before doing a "real" query in the first place.
+ */
static
__inline
NTSTATUS
-DefaultQueryInfoBufferCheck(ULONG Class,
- const INFORMATION_CLASS_INFO *ClassList,
- ULONG ClassListEntries,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- PULONG_PTR ReturnLengthPtr,
- KPROCESSOR_MODE PreviousMode,
- BOOLEAN CompleteProbing)
+DefaultQueryInfoBufferCheck(
+ _In_ ULONG Class,
+ _In_ const INFORMATION_CLASS_INFO *ClassList,
+ _In_ ULONG ClassListEntries,
+ _In_ ULONG Flags,
+ _In_opt_ PVOID Buffer,
+ _In_ ULONG BufferLength,
+ _In_opt_ PULONG ReturnLength,
+ _In_opt_ PULONG_PTR ReturnLengthPtr,
+ _In_ KPROCESSOR_MODE PreviousMode)
{
NTSTATUS Status = STATUS_SUCCESS;
{
if (Buffer != NULL)
{
- if (!CompleteProbing)
+ if (Flags & ICIF_PROBE_READ)
{
ProbeForRead(Buffer,
BufferLength,
}
}
- if (ReturnLength != NULL)
+ if ((Flags & ICIF_FORCE_RETURN_LENGTH_PROBE) || (ReturnLength != NULL))
{
ProbeForWriteUlong(ReturnLength);
}
+
if (ReturnLengthPtr != NULL)
{
ProbeForWrite(ReturnLengthPtr, sizeof(ULONG_PTR), sizeof(ULONG_PTR));