mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 21:11:54 +00:00
[NTOSKRNL]: Implement SeCheckPrivilegedObject and call it in the two cases where it's needed (when changing process priority) instead of spamming the debug log that we're not doing the check.
[NTOSKRNL]: Implement ProcessUserModeIOPL info level (and implement Ke386SetIopl) instead of spamming we can't do this. [NTOSKRNL]: Implement ProcessExecuteOptions info level (and implement MmSetExecuteOptions) instead of spamming we can't do this. [NDK]: Add NoExecute Flags based on ProcessHacker. No longer spammed to death for every process all the time. svn path=/trunk/; revision=55688
This commit is contained in:
parent
656f87b67c
commit
28f0bba7b4
8 changed files with 236 additions and 10 deletions
|
@ -63,8 +63,18 @@ Author:
|
||||||
#define MAP_PROCESS 1
|
#define MAP_PROCESS 1
|
||||||
#define MAP_SYSTEM 2
|
#define MAP_SYSTEM 2
|
||||||
|
|
||||||
#ifndef NTOS_MODE_USER
|
//
|
||||||
|
// Flags for ProcessExecutionOptions
|
||||||
|
//
|
||||||
|
#define MEM_EXECUTE_OPTION_DISABLE 0x1
|
||||||
|
#define MEM_EXECUTE_OPTION_ENABLE 0x2
|
||||||
|
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x4
|
||||||
|
#define MEM_EXECUTE_OPTION_PERMANENT 0x8
|
||||||
|
#define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE 0x10
|
||||||
|
#define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE 0x20
|
||||||
|
#define MEM_EXECUTE_OPTION_VALID_FLAGS 0x3F
|
||||||
|
|
||||||
|
#ifndef NTOS_MODE_USER
|
||||||
//
|
//
|
||||||
// Virtual Memory Flags
|
// Virtual Memory Flags
|
||||||
//
|
//
|
||||||
|
|
|
@ -727,6 +727,10 @@ KeContextToTrapFrame(
|
||||||
KPROCESSOR_MODE PreviousMode
|
KPROCESSOR_MODE PreviousMode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ke386SetIOPL(VOID);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KiCheckForKernelApcDelivery(VOID);
|
KiCheckForKernelApcDelivery(VOID);
|
||||||
|
|
|
@ -1503,6 +1503,10 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmReleaseMmInfo(struct _EPROCESS *Process);
|
MmReleaseMmInfo(struct _EPROCESS *Process);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmSetExecuteOptions(IN ULONG ExecuteOptions);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
|
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
|
||||||
|
|
|
@ -226,6 +226,15 @@ SepPrivilegeCheck(
|
||||||
KPROCESSOR_MODE PreviousMode
|
KPROCESSOR_MODE PreviousMode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
SeCheckPrivilegedObject(
|
||||||
|
IN LUID PrivilegeValue,
|
||||||
|
IN HANDLE ObjectHandle,
|
||||||
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
SepDuplicateToken(
|
SepDuplicateToken(
|
||||||
|
|
|
@ -563,6 +563,34 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
|
||||||
/* Exit to V86 mode */
|
/* Exit to V86 mode */
|
||||||
KiEoiHelper(TrapFrame);
|
KiEoiHelper(TrapFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ke386SetIOPL(VOID)
|
||||||
|
{
|
||||||
|
|
||||||
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
PKPROCESS Process = Thread->ApcState.Process;
|
||||||
|
PKTRAP_FRAME TrapFrame;
|
||||||
|
CONTEXT Context;
|
||||||
|
|
||||||
|
/* IOPL was enabled for this process/thread */
|
||||||
|
Process->Iopl = TRUE;
|
||||||
|
Thread->Iopl = TRUE;
|
||||||
|
|
||||||
|
/* Get the trap frame on exit */
|
||||||
|
TrapFrame = KeGetTrapFrame(Thread);
|
||||||
|
|
||||||
|
/* Convert to a context */
|
||||||
|
Context.ContextFlags = CONTEXT_CONTROL;
|
||||||
|
KeTrapFrameToContext(TrapFrame, NULL, &Context);
|
||||||
|
|
||||||
|
/* Set the IOPL flag */
|
||||||
|
Context.EFlags |= EFLAGS_IOPL;
|
||||||
|
|
||||||
|
/* Convert back to a trap frame */
|
||||||
|
KeContextToTrapFrame(&Context, NULL, TrapFrame, CONTEXT_CONTROL, UserMode);
|
||||||
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
|
|
@ -1094,4 +1094,73 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmSetExecuteOptions(IN ULONG ExecuteOptions)
|
||||||
|
{
|
||||||
|
|
||||||
|
PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
|
||||||
|
KLOCK_QUEUE_HANDLE ProcessLock;
|
||||||
|
NTSTATUS Status = STATUS_ACCESS_DENIED;
|
||||||
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
|
|
||||||
|
/* Only accept valid flags */
|
||||||
|
if (ExecuteOptions & ~MEM_EXECUTE_OPTION_VALID_FLAGS)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Invalid no-execute options\n");
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change the NX state in the process lock */
|
||||||
|
KiAcquireProcessLock(CurrentProcess, &ProcessLock);
|
||||||
|
|
||||||
|
/* Don't change anything if the permanent flag was set */
|
||||||
|
if (!CurrentProcess->Flags.Permanent)
|
||||||
|
{
|
||||||
|
/* Start by assuming it's not disabled */
|
||||||
|
CurrentProcess->Flags.ExecuteDisable = FALSE;
|
||||||
|
|
||||||
|
/* Now process each flag and turn the equivalent bit on */
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.ExecuteDisable = TRUE;
|
||||||
|
}
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_ENABLE)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.ExecuteEnable = TRUE;
|
||||||
|
}
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.DisableThunkEmulation = TRUE;
|
||||||
|
}
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_PERMANENT)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.Permanent = TRUE;
|
||||||
|
}
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
|
||||||
|
}
|
||||||
|
if (ExecuteOptions & MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.ImageDispatchEnable = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These are turned on by default if no-execution is also eanbled */
|
||||||
|
if (CurrentProcess->Flags.ExecuteEnable)
|
||||||
|
{
|
||||||
|
CurrentProcess->Flags.ExecuteDispatchEnable = TRUE;
|
||||||
|
CurrentProcess->Flags.ImageDispatchEnable = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All good */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the lock and return status */
|
||||||
|
KiReleaseProcessLock(&ProcessLock);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -928,6 +928,8 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
KAFFINITY ValidAffinity, Affinity = 0;
|
KAFFINITY ValidAffinity, Affinity = 0;
|
||||||
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
|
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
|
||||||
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
|
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
|
||||||
|
ULONG NoExecute = 0;
|
||||||
|
BOOLEAN HasPrivilege;
|
||||||
PLIST_ENTRY Next;
|
PLIST_ENTRY Next;
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -1189,8 +1191,17 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
|
if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
|
||||||
(PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
|
(PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
|
||||||
{
|
{
|
||||||
/* TODO: Check privileges */
|
/* Check the privilege */
|
||||||
DPRINT1("Should check privilege\n");
|
HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
|
||||||
|
ProcessHandle,
|
||||||
|
PROCESS_SET_INFORMATION,
|
||||||
|
PreviousMode);
|
||||||
|
if (!HasPrivilege)
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
DPRINT1("Privilege to change priority to realtime lacking\n");
|
||||||
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a job */
|
/* Check if we have a job */
|
||||||
|
@ -1284,7 +1295,16 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
/* Check if the new base is higher */
|
/* Check if the new base is higher */
|
||||||
if (BasePriority > Process->Pcb.BasePriority)
|
if (BasePriority > Process->Pcb.BasePriority)
|
||||||
{
|
{
|
||||||
DPRINT1("Should check privilege\n");
|
HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
|
||||||
|
ProcessHandle,
|
||||||
|
PROCESS_SET_INFORMATION,
|
||||||
|
PreviousMode);
|
||||||
|
if (!HasPrivilege)
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority);
|
||||||
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call Ke */
|
/* Call Ke */
|
||||||
|
@ -1595,12 +1615,61 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
|
KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ProcessUserModeIOPL:
|
||||||
|
|
||||||
|
/* Only TCB can do this */
|
||||||
|
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Need TCB to set IOPL\n");
|
||||||
|
Status = STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only supported on x86 */
|
||||||
|
#if defined (_X86_)
|
||||||
|
Ke386SetIOPL();
|
||||||
|
#endif
|
||||||
|
/* Done */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ProcessExecuteFlags:
|
||||||
|
|
||||||
|
/* Check buffer length */
|
||||||
|
if (ProcessInformationLength != sizeof(ULONG))
|
||||||
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProcessHandle != NtCurrentProcess())
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter SEH for direct buffer read */
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
NoExecute = *(PULONG)ProcessInformation;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
/* Get exception code */
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
_SEH2_YIELD(break);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
/* Call Mm for the update */
|
||||||
|
Status = MmSetExecuteOptions(NoExecute);
|
||||||
|
break;
|
||||||
|
|
||||||
/* We currently don't implement any of these */
|
/* We currently don't implement any of these */
|
||||||
case ProcessLdtInformation:
|
case ProcessLdtInformation:
|
||||||
case ProcessLdtSize:
|
case ProcessLdtSize:
|
||||||
case ProcessIoPortHandlers:
|
case ProcessIoPortHandlers:
|
||||||
case ProcessUserModeIOPL:
|
|
||||||
case ProcessWx86Information:
|
case ProcessWx86Information:
|
||||||
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
|
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
@ -1626,11 +1695,6 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessExecuteFlags:
|
|
||||||
DPRINT1("No execute support not implemented\n");
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Anything else is invalid */
|
/* Anything else is invalid */
|
||||||
default:
|
default:
|
||||||
DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
|
DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
|
||||||
|
|
|
@ -426,6 +426,44 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
SeCheckPrivilegedObject(IN LUID PrivilegeValue,
|
||||||
|
IN HANDLE ObjectHandle,
|
||||||
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode)
|
||||||
|
{
|
||||||
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
||||||
|
PRIVILEGE_SET Priv;
|
||||||
|
BOOLEAN Result;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
SeCaptureSubjectContext(&SubjectContext);
|
||||||
|
|
||||||
|
Priv.PrivilegeCount = 1;
|
||||||
|
Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||||||
|
Priv.Privilege[0].Luid = PrivilegeValue;
|
||||||
|
Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode);
|
||||||
|
if (PreviousMode != KernelMode)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
SePrivilegeObjectAuditAlarm(ObjectHandle,
|
||||||
|
&SubjectContext,
|
||||||
|
DesiredAccess,
|
||||||
|
&PrivilegeValue,
|
||||||
|
Result,
|
||||||
|
PreviousMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SeReleaseSubjectContext(&SubjectContext);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/* SYSTEM CALLS ***************************************************************/
|
/* SYSTEM CALLS ***************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue