Level 2 · Chapter 6
Access checks & the Security Reference Monitor
The one kernel-mode algorithm underneath nearly every allow/deny decision Windows ever makes.
The previous four chapters described the pieces: tokens, descriptors and ACLs, integrity levels, and privileges. This chapter is where they come together, inside the Security Reference Monitor (SRM) — the kernel-mode component that actually performs an access check, every time, for nearly every kind of object in Windows.
The inputs to every access check
A single access check takes three things:
- A subject security context, derived from the caller's token — its user SID, group SIDs (with their attributes), privileges, and integrity level.
- A security descriptor, from the target object — owner, DACL, SACL, and integrity label.
- A desired access mask — the specific rights being requested (read, write, delete, and so on — object-type-specific).
The SRM's job is to compare the first two against the third and return a single answer: granted, or denied (and, along the way, to generate any SACL-driven audit events the descriptor calls for).
The algorithm, step by step
- Owner check. If the caller's SID matches the object's owner, certain baseline rights (like reading and modifying the security descriptor itself) are available regardless of the DACL — this is the structural privilege every owner has.
- Null DACL check. If the object has no DACL at all, access is granted outright — the "missing vs. empty" distinction from Security descriptors & ACLs is evaluated right here, first.
- Walk the DACL, in order. For each requested right still outstanding, the SRM scans ACEs top to bottom. A matching Deny ACE for any of the caller's SIDs immediately denies that right and stops evaluating it. A matching Allow ACE grants that right. Once every requested right has been resolved (all granted, or any one explicitly denied), evaluation for this check is done — later ACEs that were never reached simply don't matter for this particular request.
- Privilege checks, where relevant. For operations that can be satisfied through a privilege instead of (or in addition to) the DACL —
SeBackupPrivilegeoverriding an otherwise-denying file DACL, for instance — the SRM (viaSePrivilegeCheck) checks whether the caller's token holds and has enabled the relevant privilege. - Integrity check, independently of the above. Mandatory Integrity Control compares the caller's integrity level against the object's integrity label and can deny write access on that basis alone, regardless of what steps 1–4 concluded.
Only a request that clears every applicable one of these is actually granted.
Two entry points, one algorithm
Kernel-mode code (drivers, the Executive's own managers) calls SeAccessCheck directly. User-mode code that needs to replicate the same decision logic outside the kernel — a management tool asking "would this user be allowed to do X" without actually performing X — uses AuthzAccessCheck, a user-mode API deliberately built to mirror the same core algorithm rather than reimplementing an approximation of it. This matters because it means tooling built on AuthzAccessCheck gives genuinely accurate answers, not a best-effort guess at what the kernel would decide.
A worked example: "I'm an admin, why was I denied?"
Put the algorithm to work on a familiar complaint. An administrator gets access denied on a specific file, despite being confident they should have rights. Possible, entirely consistent explanations, in the same order the SRM would encounter them: an explicit Deny ACE for a group they belong to, reached before any Allow ACE further down the list (step 3); a required privilege (say, SeTakeOwnershipPrivilege) that's present in their token but wasn't enabled before the attempt (step 4); or a Low-or-Medium-integrity process (a sandboxed app, a script running in a restricted context) trying to write to a higher-integrity object regardless of what the DACL itself allows (step 5). None of these require "the permissions are broken" as an explanation — they're the algorithm working exactly as designed.
A common mistake
Treating "administrator" as a magic bypass for the entire algorithm above ignores that Deny ACEs, unenabled privileges, and integrity restrictions all still apply to administrative tokens. Administrators get access to more things by default — a larger set of privileges, typically fewer restrictive ACEs written against their groups — but they still go through exactly the same five-step evaluation as any other caller; nothing in the SRM special-cases "is this token an admin" as an unconditional yes.
Where this connects
- AppContainers & capabilities adds a further, even stricter layer of checks on top of everything described here, specifically for sandboxed app isolation.
- Object Manager is where security descriptors live as part of the general kernel object model this check operates against.