mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +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_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
|
||||
//
|
||||
|
|
|
@ -727,6 +727,10 @@ KeContextToTrapFrame(
|
|||
KPROCESSOR_MODE PreviousMode
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
Ke386SetIOPL(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiCheckForKernelApcDelivery(VOID);
|
||||
|
|
|
@ -1503,6 +1503,10 @@ NTSTATUS
|
|||
NTAPI
|
||||
MmReleaseMmInfo(struct _EPROCESS *Process);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmSetExecuteOptions(IN ULONG ExecuteOptions);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
|
||||
|
|
|
@ -226,6 +226,15 @@ SepPrivilegeCheck(
|
|||
KPROCESSOR_MODE PreviousMode
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
SeCheckPrivilegedObject(
|
||||
IN LUID PrivilegeValue,
|
||||
IN HANDLE ObjectHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN KPROCESSOR_MODE PreviousMode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SepDuplicateToken(
|
||||
|
|
|
@ -563,6 +563,34 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
|
|||
/* Exit to V86 mode */
|
||||
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 ***********************************************************/
|
||||
|
||||
|
|
|
@ -1094,4 +1094,73 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
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 */
|
||||
|
|
|
@ -928,6 +928,8 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
KAFFINITY ValidAffinity, Affinity = 0;
|
||||
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
|
||||
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
|
||||
ULONG NoExecute = 0;
|
||||
BOOLEAN HasPrivilege;
|
||||
PLIST_ENTRY Next;
|
||||
PETHREAD Thread;
|
||||
PAGED_CODE();
|
||||
|
@ -1189,8 +1191,17 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
|
||||
(PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
|
||||
{
|
||||
/* TODO: Check privileges */
|
||||
DPRINT1("Should check privilege\n");
|
||||
/* Check the privilege */
|
||||
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 */
|
||||
|
@ -1284,7 +1295,16 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
/* Check if the new base is higher */
|
||||
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 */
|
||||
|
@ -1595,12 +1615,61 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
|
||||
Status = STATUS_SUCCESS;
|
||||
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 */
|
||||
case ProcessLdtInformation:
|
||||
case ProcessLdtSize:
|
||||
case ProcessIoPortHandlers:
|
||||
case ProcessUserModeIOPL:
|
||||
case ProcessWx86Information:
|
||||
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
|
@ -1626,11 +1695,6 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
|||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
case ProcessExecuteFlags:
|
||||
DPRINT1("No execute support not implemented\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
/* Anything else is invalid */
|
||||
default:
|
||||
DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
|
||||
|
|
|
@ -426,6 +426,44 @@ SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
|
|||
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 ***************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
|
Loading…
Reference in a new issue