Access Control Lists (ACLs)

Once the hardware has verified you are in Ring 3 (User Mode), the OS Kernel must decide: Are you allowed to open this file?

This is the job of the Access Control subsystem.

1. Discretionary Access Control (DAC)

Linux and Unix systems primarily use DAC.

  • “Discretionary”: The owner of the file has the discretion to set permissions.
  • The Problem: If a user runs a malicious script (Trojan), that script runs with the user’s full permissions and can change permissions on all the user’s files.

The Inode & Permission Bits

Every file in a Unix filesystem is represented by an Inode. The inode stores metadata, including a 9-bit permission mask.

  • User (u): The owner.
  • Group (g): Users in the file’s group.
  • Others (o): Everyone else.

Each scope has 3 bits: Read (4), Write (2), Execute (1).


2. Interactive: Permission Bitmask Calculator

Visualize how the kernel translates binary flags into the octal notation used by chmod.

USER (Owner)
GROUP
OTHERS
Command to Run
chmod 655 file
Symbolic
-rw-r-xr-x

3. Mandatory Access Control (MAC)

Because DAC has flaws (root can do anything, users can accidentally expose files), high-security systems use MAC (e.g., SELinux, AppArmor).

  • “Mandatory”: The system defines the policy, not the user. Even root cannot override it easily.
  • Labels: Files and processes have security labels.
  • Policy: “The Apache process (Label: httpd_t) can ONLY read files with Label httpd_content_t.”
  • If Apache tries to read /etc/shadow (Label: shadow_t), the kernel blocks it, even if permissions are 777.

4. Code Example: Manipulating Permissions

System calls to change permissions.

Go
Java
package main

import (
	"fmt"
	"os"
)

func main() {
	fileName := "secret.txt"

	// Create a file
	file, err := os.Create(fileName)
	if err != nil {
		panic(err)
	}
	file.Close()

	// 1. Change permissions to 0600 (rw-------)
	// Only the owner can read/write.
	if err := os.Chmod(fileName, 0600); err != nil {
		panic(err)
	}

	info, _ := os.Stat(fileName)
	fmt.Printf("Permissions: %s\n", info.Mode())
    // Output: -rw-------
}
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;

public class PermExample {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("secret.txt");
        if (!Files.exists(path)) Files.createFile(path);

        // 1. Define permissions set using POSIX enum
        Set<PosixFilePermission> perms = new HashSet<>();
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        // No GROUP or OTHERS permissions added

        // 2. Apply permissions
        try {
            Files.setPosixFilePermissions(path, perms);
            System.out.println("Permissions set to rw-------");
        } catch (UnsupportedOperationException e) {
            System.out.println("POSIX permissions not supported on this OS (Windows?)");
        }
    }
}