107 lines
4.1 KiB
C
107 lines
4.1 KiB
C
// Kernel security contexts. Contexts are immutable authority sets carried by processes and delegated only by attenuation.
|
|
|
|
#include <string.h>
|
|
#include <kernel/se_security.h>
|
|
#include <kernel/ke_id.h>
|
|
#include <kernel/ke_process.h>
|
|
#include <kernel/ob_object.h>
|
|
|
|
static KE_ID_ALLOCATOR gSecurityIds = KE_ID_ALLOCATOR_INIT(1u);
|
|
static SECURITY_CONTEXT* gRootSecurityContext;
|
|
|
|
// Destroys one non-root security context after its last object reference disappears.
|
|
static void KiSecurityContextDestroy(OBJECT* object) {
|
|
(void)object;
|
|
}
|
|
|
|
// Allocates and initializes one immutable security context object.
|
|
static KSTATUS KiCreateSecurityContext(SYS_PRIVILEGES effectivePrivileges,
|
|
SYS_PRIVILEGES delegablePrivileges,
|
|
SECURITY_CONTEXT** contextOut) {
|
|
if (!contextOut)
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
*contextOut = (SECURITY_CONTEXT*)0;
|
|
|
|
if ((effectivePrivileges & ~SYS_PRIV_ALL) != 0 ||
|
|
(delegablePrivileges & ~SYS_PRIV_ALL) != 0)
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
if ((delegablePrivileges & ~effectivePrivileges) != 0)
|
|
return NTLSTATUS_ACCESS_DENIED;
|
|
|
|
SECURITY_CONTEXT* context = (SECURITY_CONTEXT*)ObAllocateObject(ObjectTypeSecurityContext,
|
|
sizeof(SECURITY_CONTEXT));
|
|
if (!context)
|
|
return NTLSTATUS_NO_MEMORY;
|
|
context->Header.Destroy = KiSecurityContextDestroy;
|
|
|
|
KSTATUS status = KeAllocateId32(&gSecurityIds, &context->SecurityId);
|
|
if (!KSUCCESS(status)) {
|
|
ObDereferenceObject(&context->Header);
|
|
return status;
|
|
}
|
|
|
|
context->EffectivePrivileges = effectivePrivileges;
|
|
context->DelegablePrivileges = delegablePrivileges;
|
|
context->Flags = SYS_SECURITY_CONTEXT_FLAG_NONE;
|
|
*contextOut = context;
|
|
return NTLSTATUS_SUCCESS;
|
|
}
|
|
|
|
// Initializes the root context exactly once before any process is created.
|
|
KSTATUS SeInitializeSecurity(void) {
|
|
if (gRootSecurityContext)
|
|
return NTLSTATUS_SUCCESS;
|
|
|
|
SECURITY_CONTEXT* context = (SECURITY_CONTEXT*)0;
|
|
KSTATUS status = KiCreateSecurityContext(SYS_PRIV_ALL,
|
|
SYS_PRIV_ALL,
|
|
&context);
|
|
if (!KSUCCESS(status))
|
|
return status;
|
|
|
|
gRootSecurityContext = context;
|
|
return NTLSTATUS_SUCCESS;
|
|
}
|
|
|
|
// Returns the permanently referenced bootstrap root context.
|
|
SECURITY_CONTEXT* SeGetRootSecurityContext(void) {
|
|
return gRootSecurityContext;
|
|
}
|
|
|
|
// Derives one child context whose effective and delegable authority are subsets of the source delegable sets.
|
|
KSTATUS SeDeriveSecurityContext(SECURITY_CONTEXT* source,
|
|
SYS_PRIVILEGES effectivePrivileges,
|
|
SYS_PRIVILEGES delegablePrivileges,
|
|
SECURITY_CONTEXT** contextOut) {
|
|
if (!source || !contextOut)
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
|
|
if ((effectivePrivileges & ~source->DelegablePrivileges) != 0 ||
|
|
(delegablePrivileges & ~source->DelegablePrivileges) != 0)
|
|
return NTLSTATUS_ACCESS_DENIED;
|
|
|
|
return KiCreateSecurityContext(effectivePrivileges,
|
|
delegablePrivileges,
|
|
contextOut);
|
|
}
|
|
|
|
// Tests one process's immutable effective privilege mask.
|
|
bool SeProcessHasPrivilege(const struct PROCESS* process, SYS_PRIVILEGES privileges) {
|
|
if (!process || !process->SecurityContext)
|
|
return false;
|
|
return (process->SecurityContext->EffectivePrivileges & privileges) == privileges;
|
|
}
|
|
|
|
// Exports immutable context metadata to one public structure.
|
|
void SeQuerySecurityContext(const SECURITY_CONTEXT* context, SYS_SECURITY_CONTEXT_INFO* infoOut) {
|
|
if (!context || !infoOut)
|
|
return;
|
|
|
|
memset(infoOut, 0, sizeof(*infoOut));
|
|
infoOut->Size = sizeof(*infoOut);
|
|
infoOut->SecurityId = context->SecurityId;
|
|
infoOut->EffectivePrivileges = context->EffectivePrivileges;
|
|
infoOut->DelegablePrivileges = context->DelegablePrivileges;
|
|
infoOut->Flags = context->Flags;
|
|
}
|