How does the NTFS permission model differ from Unix rwx mode bits, and what does a single access control entry (ACE) contain?
answer
- security descriptor, not three bits
- owner SID, DACL, SACL
- one ACE: SID, mask, type, flags
- allow and deny, both expressible
- inheritance is copied into the child
basics
~20 sNTFS attaches a security descriptor with an ordered list of ACEs to every file, so any number of users and groups can each be allowed or denied specific rights. Unix mode bits offer only three fixed slots of read/write/execute.
solid answer
~50 sOn Unix a file carries an owner, a group, and nine permission bits — three rwx triples for owner, group and other. NTFS instead stores a **security descriptor** on every file and directory: an owner SID, a **DACL** (the discretionary ACL that decides access), and a **SACL** (auditing plus the integrity label). The DACL is an ordered list of ACEs, and each ACE holds a trustee SID, an access mask of specific rights, an ACE type (allow or deny), and inheritance flags. So NTFS can express "these five groups get different rights, and this one account is explicitly denied" without inventing extra groups. Rights are granular too — reading data, writing data, appending, deleting, reading attributes and changing the ACL are separate bits, not folded into one `w`. Access is evaluated when the handle is opened, and the granted mask is stamped into that handle.
go deeper
Be able to say that every NTFS file carries a list of entries naming users or groups with specific rights, and that both Allow and Deny exist — unlike Unix, which has only three fixed rwx slots.
Explain the security descriptor's parts and what one ACE holds: trustee SID, access mask, allow/deny type, inheritance flags. Point out granular rights such as append-without-write and delete as their own bit.
Show you have debugged this: inherited entries are physically copied into children, so disabling inheritance freezes a divergent copy, and access is checked at handle-open so a DACL edit does not stop a running process.
Own the policy angle — decide whether access is granted through group SIDs and inheritance from a small number of roots, or scattered as explicit per-file ACEs, and be able to argue why the second becomes unauditable at scale.
## The two models side by side A Unix file's permissions are nine bits plus an owner UID and a group GID. The kernel picks exactly one triple to apply: if you are the owner it uses the owner triple, otherwise if you are in the file's group it uses the group triple, otherwise it uses other. That is the whole model, and it is beautifully small — but it can only express three distinct opinions about a file. Anything richer forces you to create groups. NTFS takes the opposite trade. Every file and directory carries a *security descriptor*, a variable-length structure with four interesting parts: - the **owner SID** — the security identifier of the principal that owns the object; - a **group SID** — a vestigial field kept for POSIX compatibility, effectively unused by Windows itself; - the **DACL** (discretionary access control list) — the ordered list of ACEs that decides who may do what; - the **SACL** (system access control list) — which access attempts get audited, and the object's mandatory integrity label. A SID is not a small integer like a UID; it is a variable-length identifier such as `S-1-5-21-<domain>-<rid>` for a domain or local account, or a well-known constant such as `S-1-5-18` for LocalSystem. That matters practically: SIDs are unique across machines and domains, so an ACL copied to another machine still names the same principal, whereas a UID means whatever the target machine's passwd database says it means. ## Inside one ACE An access control entry is four things: 1. **Type** — ACCESS_ALLOWED or ACCESS_DENIED (there are audit ACE types too, but those live in the SACL). 2. **Trustee SID** — the user, group, or well-known principal the entry is about. 3. **Access mask** — a 32-bit set of rights. For files these include object-specific bits such as `FILE_READ_DATA`, `FILE_WRITE_DATA`, `FILE_APPEND_DATA`, `FILE_EXECUTE`, `FILE_READ_ATTRIBUTES` and `FILE_DELETE_CHILD`, plus standard rights that every securable object has: `DELETE`, `READ_CONTROL` (read the security descriptor), `WRITE_DAC` (change the DACL) and `WRITE_OWNER`. 4. **Flags** — including the inheritance flags `OBJECT_INHERIT_ACE`, `CONTAINER_INHERIT_ACE`, `INHERIT_ONLY_ACE` and `NO_PROPAGATE_INHERIT_ACE`, and the `INHERITED_ACE` flag marking an entry that came from a parent. The familiar names in the GUI — Full control, Modify, Read & execute — are just conventional bundles of those bits. `icacls` prints them as `(F)`, `(M)`, `(RX)`, with inheritance shown as `(OI)` object inherit, `(CI)` container inherit, `(IO)` inherit only, and a leading `(I)` for an inherited entry. ## Granularity that Unix folds together Several distinctions have no `rwx` equivalent: - **Write versus append.** `FILE_WRITE_DATA` and `FILE_APPEND_DATA` are separate bits, so you can grant a log writer append-only access. - **Delete.** On Unix, removing a name needs write permission on the *directory*; the file's own bits are irrelevant. On NTFS a caller needs `DELETE` on the file itself, or `FILE_DELETE_CHILD` on the parent — two independent paths to the same outcome. - **Reading the ACL versus reading the data.** `READ_CONTROL` and `FILE_READ_DATA` are different rights. - **Deny.** Unix has no way to say "everyone in Engineering except Bob"; an NTFS DACL says it with one deny ACE. ## Inheritance is a copy, not a lookup This is the piece people get wrong. When a file is created inside a directory, the inheritable ACEs from the parent are *copied into the new file's own DACL* and tagged `INHERITED_ACE`. The kernel does not walk up the tree at access time. Changing a parent folder therefore triggers a re-propagation pass down the tree; and a child whose inheritance has been disabled keeps whatever converted copies it had at that moment, permanently diverging from its parent. ``` C:\data\report.txt BUILTIN\Administrators:(I)(F) CONTOSO\alice:(F) ``` Here the `(I)` entry came from `C:\data`; the `alice` entry was set explicitly on the file. ## When the check happens Windows performs the access check once, when a handle is opened, against the *desired access* mask the caller requested. The granted mask is recorded in the handle. Tightening a DACL afterwards does not revoke access through handles that are already open — the process keeps reading until it closes the handle. That surprises people who expect permission changes to bite immediately. ## What interviewers are testing Not the flag letters. They want to hear that you know NTFS security is a list, not a triple; that entries name SIDs and carry both allow and deny; that inheritance is materialised into the child; and that the richness is exactly why Windows permissions are easier to get subtly wrong than `chmod 640`.
- On Unix, deleting a file depends on write permission on the directory. What governs deletion on NTFS?Either right works: the `DELETE` standard right on the file itself, or `FILE_DELETE_CHILD` on the parent directory. That is why a user can sometimes delete a file they cannot open for writing, and why removing `DELETE` from a file is not enough if the parent grants delete-child.
- If you tighten a file's DACL while a process already has the file open, does that process immediately lose access?No. Windows evaluates the DACL once, when the handle is opened, and stamps the granted access into the handle. The running process keeps that access until it closes the handle and tries to reopen. To cut someone off now, you have to terminate the process or break the session, not just edit the ACL.
- What does the SACL do, and why is it usually empty?The SACL holds audit ACEs — which principals and which access attempts generate security-log events — plus the object's mandatory integrity label. It is usually empty because auditing every file access is expensive and noisy; teams enable it selectively on sensitive directories, typically through audit policy rather than per-file edits.
saying these in an interview costs you the question
- Calls NTFS permissions just rwx bits with longer names
- Thinks the descriptor's group SID works like a Unix primary group
- Assumes tightening a DACL cuts off already-open handles
- Cannot say what a single ACE actually contains
- Believes inheritance is resolved by walking up at access time