Linux Security / Basic: identity, resources, and evidence / Lesson 3
Reason about permissions, ACLs, and creation masks
Use bounded mode-bit calculations while recognizing the other layers a real access decision needs.
On this page
Lesson goals
- Select owner, group, or other mode class without unioning them.
- Explain how a creation mask differs from changing existing permissions.
Ask which operation and object are being checked
Reading file content, traversing a directory, creating an entry, and removing a name are different operations. Directory execute means search/traversal, while directory read concerns listing entries. Removing a name commonly depends on the parent directory and additional rules, not simply on the target file’s write bit. Sticky bits, ACLs, capabilities, mount behavior, mandatory controls, and path traversal can matter. This lesson’s calculations intentionally model only ordinary mode classes under declared assumptions. No chmod, chown, setfacl, account lookup, file creation, or permission inspection is performed on this host.
Choose the applicable class rather than combining classes
For ordinary mode checks, matching the owner selects the owner class; it does not fall through to a more generous group or other class. The first program demonstrates this often-missed distinction. It assumes trusted numeric identities, no ACL, no capability bypass, and already satisfied path prerequisites. It is not a complete Linux permission evaluator. A real access check also depends on the relevant filesystem credentials and policy context. Keep the simplified rule and its exclusions beside the example so the arithmetic is not mistaken for proof that a real file is accessible.
def selected_bits(uid, groups, owner, group, mode):
if uid == owner:
return (mode >> 6) & 7
if group in groups:
return (mode >> 3) & 7
return mode & 7
assert selected_bits(1200, {1300}, 1200, 1300, 0o046) == 0
assert selected_bits(1201, {1300}, 1200, 1300, 0o046) == 4
assert selected_bits(1202, set(), 1200, 1300, 0o046) == 6
print("owner, group, and other are selected separately")
owner, group, and other are selected separately
The complete program performs bit operations on invented ids and modes. It reads no inode and changes no permission. The owner receives zero in this fixture despite more generous other bits; no fallback or ACL behavior is modeled.
Treat umask as removal from requested creation bits
Without a parent default ACL, a creation mask removes selected permission bits from the mode requested by the application. It does not add execute permission and does not rewrite existing files. The second program calculates common illustrative cases using bitwise operations, not subtraction. The maximum requested modes and chosen mask are classroom inputs, not a universal recommendation. A default ACL changes the creation rules, so the simple formula is intentionally conditional. Actual application-requested mode, inherited ACLs, service settings, and later changes must be reviewed before describing a real file’s final permissions.
def created_mode(requested, mask):
return requested & (~mask & 0o777)
assert created_mode(0o666, 0o027) == 0o640
assert created_mode(0o777, 0o027) == 0o750
assert created_mode(0o666, 0o111) == 0o666
print("file=0640 directory=0750; mask adds no execute bits")
file=0640 directory=0750; mask adds no execute bits
The complete program does integer arithmetic only. It does not set the process umask or create a file. The results assume no inherited default ACL and say nothing about current host permissions or a service’s actual creation requests.
Read ACLs and directory rules in their own context
POSIX ACLs add named user/group entries and a mask that can limit the effective rights of relevant entries. A familiar mode display may not expose every intended relationship. Default ACLs govern inheritance, while access ACLs govern the object’s discretionary access. These are different questions. Do not repair a refusal by making a whole tree broadly writable; identify the exact operation, path component, selected identity, and effective ACL entry first. The course describes these rules without reading or altering real ACLs, and later mandatory policy can still deny an otherwise permitted discretionary operation.
Verify the intended access matrix at the right layer
Define which synthetic subject may read, write, traverse, create, or remove which resource, and include legitimate positives and denials. State excluded layers explicitly. In an approved disposable environment, actual enforcement would need checks of path prerequisites, effective credentials, ACLs, mandatory controls, and creation behavior. Those operations are not run here. A correct local formula is useful evidence about that formula, while a real permission diagnosis needs observed context. Preserve the distinction so a mode number is not presented as a complete Linux security posture or a universal hardening setting.
Common errors and fixes
Owner falls back to generous other permissions
- Why it happens
- Mode classes are unioned rather than selected.
- How to fix it
- Apply the relevant ordinary class under the declared assumptions.
- Prevent it next time
- Include owner-denied/group-allowed fixtures.
Umask is subtracted or applied to existing files
- Why it happens
- Bit removal and creation scope are misunderstood.
- How to fix it
- Use conditional bit masking and distinguish later permission changes.
- Prevent it next time
- Record requested mode and default-ACL assumptions.
A refusal is fixed with broad recursive write access
- Why it happens
- The actual operation and denial layer are unknown.
- How to fix it
- Identify the narrow path, identity, ACL, and policy cause.
- Prevent it next time
- Review access matrices and effective outcomes.
Check your understanding
1. The owner bits are zero and other bits allow read/write. Does the owner inherit other access in the model?
Show worked solution
No. Owner matching selects the owner class, so the fixture yields zero. A real decision still needs the excluded ACL, capability, path, and mandatory-policy context. Do not test the rule by changing host permissions; the in-memory fixture is sufficient for this stated claim.
2. A newly created file differs from requested & ~mask. What assumption should be examined?
Show worked solution
Check whether a parent default ACL governs creation, what mode the application actually requested, and whether the service or later code changed it. The simple formula is not universal. This exercise inspects none of those host facts and should report them as unverified rather than guessing a fix.
Key takeaways
- Mode classes are selected, not automatically combined.
- Creation masks remove requested bits under stated ACL assumptions.
- Real access decisions involve more than one mode number.