[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:
Alex Ionescu 2012-02-18 23:59:31 +00:00
parent 656f87b67c
commit 28f0bba7b4
8 changed files with 236 additions and 10 deletions

View file

@ -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
//

View file

@ -727,6 +727,10 @@ KeContextToTrapFrame(
KPROCESSOR_MODE PreviousMode
);
VOID
NTAPI
Ke386SetIOPL(VOID);
VOID
NTAPI
KiCheckForKernelApcDelivery(VOID);

View file

@ -1503,6 +1503,10 @@ NTSTATUS
NTAPI
MmReleaseMmInfo(struct _EPROCESS *Process);
NTSTATUS
NTAPI
MmSetExecuteOptions(IN ULONG ExecuteOptions);
VOID
NTAPI
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);

View file

@ -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(

View file

@ -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 ***********************************************************/

View file

@ -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 */

View file

@ -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);

View file

@ -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