Family Inheritance
Knowing how NTFS passes down file access attributes would have helped one systems administrator avoid exile to the basement. It could do the same for you.
- By Bill Boswell
- February 01, 2002
I try to avoid taking long looks at myself in the mirror, but when I
do, I see features that have branded members of both sides of my family
for generations. Big ears, bad eyes, thin hair. Inheritance is a blessing
or a curse, depending on what characteristics you get and from whom you
get them.
I started thinking about inheritance the other day after overhearing
someone moan about a calamity on a big Windows NT 4.0 file server. It
seems that a recently trained administrator had gotten a work request
from an irate manager who wanted contractors blocked from accessing server-based
files. “They can store their stuff on their own hard drives,” the manager
wrote in her work request. “Just keep them away from everyone else’s files,
especially mine.”
This junior administrator, eager to exercise his newly acquired system
privileges, promptly set to work. Using Windows Explorer, he opened the
Properties window for the root of the data drive on the server. He selected
the Security tab and clicked Add. He found a group named Contractors and
added it to the access list along with the Administrators group, the only
other entry. He then selected No Access from the permissions drop-down
list, checked the box labeled “Replace Permissions on Subdirectories”
and clicked OK.
It wasn’t long before the phones started ringing at the help desk as
users from all over the company—contractors and regular employees alike—called
to complain that they’d lost access to their files. The administrator
who made the change was thoroughly perplexed. “Why would non-contractors
lose access?” he asked in bewilderment as the CIO had him hauled down
to the basement to do maintenance inventories for the next six months.
To give this administrator a complete answer to his question requires
a close look at the operation of the NTFS file system, especially the
role of an innocent-looking data structure called the security descriptor.
While we’re at it, we’ll see how the outcome would have been different
on Windows 2000, where permission inheritance can help avoid these kinds
of problems.
NTFS and Access Permissions
I’m sure you know the NTFS file system is a database contained in a file
called the Master File Table (MFT). This database consists of a series
of one-kilobyte records, each of which contains a brief header followed
by a set of attributes that describes the contents of a file or folder.
When the junior administrator opened the Properties window at the root
of the volume and selected the Security tab, he saw the contents of an
attribute called $Security_Descriptor. This attribute defines who owns
the associated MFT record, who can access the contents of the record,
what they’re permitted to do, and who can audit their actions.
Users, groups and computers with access permissions to a file or folder
are listed within the security descriptor in a table called the Discretionary
Access Control List (DACL). The term “discretionary” differentiates the
ACL from the “security” ACL, which controls auditing permissions.
The DACL is the business end of the stick used to control access permissions.
It contains a set of Access Control Entries, or ACEs, each of which consists
of a Security ID (SID) and a 32-bit number called an access mask. Bits
in the access mask define specific permissions. For example, bit No. 1
sets Read permission, bit 10 sets Write permission, and bit 100 sets Append
permission.
When a user touches a file or folder, the file system extracts the DACL
from the security descriptor and hands it over to the Security Reference
Monitor (SRM) in the Windows Executive. The SRM compares the contents
of the security descriptor with the user’s access token. This token contains
the user’s SID along with the SIDs of any groups to which the user belongs
and other assorted security information.
The SRM does its evaluation by plucking the first ACE from the DACL then
scanning the access token looking for a match to the SID in the ACE. If
it finds one, it compares the permissions requested by the user process
to the permissions listed in the access mask. For example, if the process
opened a file for Read/Write access, the SRM looks for the Read and Write
bits set in the access mask.
The SRM has its eye on the clock and doesn’t want to do any extra work.
It goes through the ACEs and, once it finds a match for a particular permission,
it stops looking for other ACEs lower down that might have access masks
that control the same permission. This is called canonical evaluation,
based on the root word canon, which means a body of information arranged
in the order it’s encountered. A canon of music, for instance, might start
with Mesopotamian lute strumming and continue through Mozart cantatas
to end up with Eminem rap music.
The SRM takes no responsibility for sorting the ACEs. It’s solely up
to the application, such as Explorer, that modified the contents of the
security descriptor to arrange the ACEs in the DACL in a way that makes
sense during canonical evaluation. Generally, this means that Deny entries
come before Allow entries, although some applications such as Exchange
2000 play games with this sorting.
If the SRM doesn’t find a match between the SIDs in the access token
and the ACE entries in the DACL, including a match for every permission
requested by the user process, it denies access completely. “If you aren’t
on the A list, buddy,” says the SRM, “you don’t get in.”
Which brings us to the event that occurred to our hapless junior administrator.
When he added the Contractors group to the access list at the root folder
of the volume, he modified the contents of the DACL in the $Security_Descriptor
attribute of the “\” (root) record. His decision to apply this change
to subfolders and files was what ruined his afternoon, because the file
system obligingly went on to overwrite the $Security_Descriptor attribute
in every file and folder record in the MFT database. This wiped out any
existing permissions lower in the tree, which is why users other than
members of the Contractors group lost access.
Windows 2000 and Permission Inheritance
The root cause of the administrator’s mistake wasn’t so much a lack of
training as a flaw in the operating system whereby a single mouse click
could wreak that kind of havoc. Fortunately, in the versions of NTFS that
ship with Win2K and XP, Microsoft completely re-engineered the mechanism
for handling security descriptors. (The internal version number of NTFS
in NT 4.0 is version 1.2. NTFS version 3.0 ships with Win2K and version
3.1 ships with XP.)
In NTFS 3.x, files and folders don’t have discrete security descriptors.
All security descriptors are stored in a database under a new MFT metadata
record called $Secure. The security descriptors in the $Secure database
are assigned index numbers that link them to the MFT records of files
and folders in the volume.
When a user accesses a file, the file system obtains the security descriptor
index number from the $Standard_ Information attribute in the file record,
goes to the $Secure database, looks up the security descriptor that corresponds
to the index number, and delivers the DACL inside that security descriptor
to the Security Reference Monitor for processing. (This happens a lot
more quickly than it takes to describe.)
This central repository of security descriptors in the $Secure database
makes it possible to implement inheritance for file and folder permissions.
The mechanism for this inheritance isn’t quite as intuitive as you might
think, though.
When you create the first folder at the root of a new NTFS 3.x volume,
the file system creates a new security descriptor entry in the $Secure
database. Any new folders and subfolders you create in that volume will
reference the index number of that security descriptor in their $Standard_Information
attribute, at least as long as you don’t change the default permissions.
In this way, folders and subfolders appear to inherit their permissions
when—in actuality—they share the same security descriptor.
A slight complication to this mechanism is necessary to conserve the
number of security descriptors and speed up processing. From the outside,
it looks as if the system should just find the security descriptor index
number in the parent folder and give the same index number to the subfolder.
In actuality, the system selects a security descriptor in the same way
that I locate a pair of socks in the morning, by finding one sock then
rummaging around looking for a match.
The file system first calculates the contents of the security descriptor
needed by the file or folder. It then scans the $Secure database looking
for a security descriptor that has the same contents. To avoid a slow,
byte-by-byte comparison of all the security descriptors during the scan,
the $Secure database has a lookup table called $SDH that stores the index
number of each security descriptor and a 128-bit hash of the security
descriptor’s contents. To do the scan, the file system hashes the calculated
security descriptor then compares the result with the hashes in the lookup
table. If it finds a match, it does a byte-by-byte comparison of the actual
security descriptor for verification, then uses its index number as the
link to the new MFT record. The database also stores a cross-reference
between hashes and index numbers in the $SII index to speed up access
to security descriptors.
Permission Inheritance Mechanisms
We’re just about ready to see how Win2K permission inheritance might have
kept our junior administrator in the good graces of the CIO, but first
we need to wiggle past a complexity in the permission process itself.
To accommodate permission inheritance, each ACE in an NTFS 3.x DACL must
be flagged to determine its inheritance setting. By default, when you
put a new user or group on the access list for a folder, the new ACE is
set to be inherited by all files in that folder and all subfolders and
files below the folder. But as we’ve seen, this inheritance isn’t calculated
dynamically. The security descriptor in the $Security database is a fixed
entity. This means the system needs a way to differentiate between ACEs,
depending on their source, so it can create new security descriptors for
the subfolders and their files.
If you add a user or group to an access list, the result is a Direct
Apply ACE. This contrasts with an Inherited ACE placed there by the system.
The ACL Editor in the Security tab of the Property window in Explorer
has an Advanced view that lists each ACE in the security descriptor and
whether it was inherited or directly applied. The ACL Editor in XP, shown
in Figure 1, shows the source folder of each inherited ACE.
|
Figure 1. The ACL Editor (viewed from the Windows
XP GUI), tells you from where the file got its permission settings.
(Click image to view larger version.) |
So, let’s say you add a group to the access list of a folder that already
has a couple of inherited ACEs. The file system creates a new security
descriptor in the $Secure database for that folder and constructs a DACL
that lists the new group as a Direct Apply ACE along with the original
Inherited ACEs. It then creates still another security descriptor for
the subfolders under the folder where you made the change. This security
descriptor has the same set of ACEs in the DACL, but the ACE for the new
group is flagged as Inherited. The system then proceeds to update the
$Standard_Information attributes of the subfolders to point at this new
security descriptor.
How Windows 2000 is Different—and Better
Let’s see how this new-fangled NTFS permission machinery would have kept
our junior administrator out of trouble. When he placed the Contractors
group on the access list for the root of the volume, the file system would
have created a new security descriptor containing the old ACE for the
Administrators group, plus a new ACE for the Contractors group. Both of
these entries would be Direct Apply ACEs because they’re applied to the
root of the volume, the highest point in the directory tree.
The system would then construct a security descriptor having a DACL with
the same ACE list, but with each ACE flagged as Inherited. It would then
visit each MFT record and update the index number in the $Standard_Information
attribute to point to the new security descriptor.
If this sounds like what happened in NT, here’s the difference. When
the system encounters a folder with a pointer to a different security
descriptor, it creates a new security descriptor that retains the original
ACEs, plus the new ACE for the Contractors group. As a result, the Deny
ACE for the contractors is added to folders and files throughout the volume
without disrupting access by any other users. And because only a limited
number of security descriptors were involved, the operation occurs much
more quickly than with NT.
If you’re rolling out Win2K servers and desktops, or planning on doing
so, it would be worth your time to play around with file maneuvers and
permission settings in the lab so you can prepare your users for any changes.
If you find other interesting or surprising convolutions caused by permission
inheritance, let me know.