Course outline

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.

About 5 min readContent reviewed
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.

python Check three declared mode-class decisions
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")
Expected output
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.

python Calculate conditional creation modes without calling umask
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")
Expected output
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.

Official references