The Handbook

    Theme
    • Guides
        • Check a system before installing FreeBSD
        • Orient a Linux administrator on FreeBSD
        • Supported FreeBSD releases
        • Choose a FreeBSD documentation and support channel
        • Move files safely without GNU mv -t
        • Update, upgrade, or update packages?
        • Upgrade 14.4 or 15.0 to FreeBSD 15.1
        • Choose packages, ports, or poudriere
        • Choose the quarterly or latest package branch
        • Choose a FreeBSD download or package mirror
        • Make a system setting persistent
        • Configure locale, keyboard, and time zone
        • Configure a serial console for recovery
        • Choose a custom kernel, module, or loader setting
        • Run a Linux binary with the compatibility layer
        • Check desktop and laptop hardware before installation
        • Choose and check a graphics driver
        • Choose Xorg or Wayland
        • Build a maintainable desktop baseline
        • Install and check a desktop browser
        • Check laptop Wi-Fi, power, and suspend
        • Check multimedia readiness
        • Choose and configure a printing stack
        • Run Windows applications with Wine
        • Snapshot and replicate a ZFS dataset
        • Choose a filesystem and storage layout
        • Operate ZFS without losing the recovery path
        • Restore files from a ZFS snapshot
        • Read ZFS pool health and run a scrub
        • Replace a failed device in a ZFS mirror
        • Replicate a ZFS dataset over SSH
        • Change PF safely on a remote host
        • Configure a narrow WireGuard tunnel
        • Plan a FreeBSD home server
        • Choose a mail server or an outgoing relay
        • Publish a network service safely
        • Choose a jail network model
        • Choose native jails or a jail manager
        • Choose a jail or a bhyve virtual machine
        • Establish a FreeBSD security baseline
        • Choose a MAC policy
        • Audit security-relevant activity
        • Start a DTrace performance investigation
    • Integrations
        • Create a first jail with Bastille
        • Compare jail managers and OCI tooling
        • Publish a Bastille service through PF
        • Mount a ZFS dataset in a Bastille jail
        • Update and upgrade Bastille jails
        • Back up and restore a Bastille jail
        • Prepare bhyve and vm-bhyve
        • Choose NFS or Samba for file sharing
        • Choose ZFS backup automation
        • Operate a signed poudriere repository
        • Manage FreeBSD configuration with Ansible or Salt
        • Run Motion with webcamd on FreeBSD
        • Design a reverse proxy, certificates, and monitoring
    • FAQ
    • Troubleshooting
        • Recover an interrupted freebsd-update run
        • Resolve a package repository or ABI mismatch
        • Diagnose the FreeBSD boot path
        • Recover with a ZFS boot environment
        • Diagnose DNS, routing, and firewall paths
        • Diagnose network mbuf exhaustion
        • Bind a service to a low port without running it as root
        • Diagnose audio output or input
        • Diagnose webcamd, cuse, and a webcam
        • Fix USB device permissions without opening every device
    • About this handbook
    • Synopsis
    • Start with the rule, not the module
    • Understand how MAC composes with DAC
    • Prefer a simpler boundary when it expresses the rule
    • Match the policy family to the requirement
    • Distinguish module, policy, labels, and persistence
    • Qualify a policy before production
    • Plan recovery before persistence
    • Avoid a universal hardening recipe
    • Primary references

    Choose a MAC policy

    Last reviewed
    13 August 2026
    Applies to
    15.1-RELEASE, 15.0-RELEASE, 14.4-RELEASE

    Synopsis #

    FreeBSD Mandatory Access Control (MAC) policies add kernel-enforced decisions to the ordinary discretionary access control (DAC) model. They are appropriate when a specific resource or information-flow rule cannot be expressed reliably with users, groups, modes, ACLs, jails, service privilege separation, or firewall policy alone.

    MAC is a framework, not one universal hardening mode. Its policy modules solve different problems, and several use labels whose design affects files, processes, login classes, and recovery. Loading every policy does not create a coherent security model. Begin with a written rule, choose the narrowest module that enforces it, and qualify both intended access and intended denial on a representative non-production system.

    Start with the rule, not the module #

    A MAC proposal should identify:

    • the subjects whose actions need control, such as service accounts or user classes;
    • the objects or resources being protected;
    • the access or information flow that must be allowed;
    • the access that must be denied even when ordinary ownership permits it;
    • who may administer the policy and through which recovery path;
    • how the decision will be tested after upgrades.

    “Enable MAC” is not a security requirement. “Only the account with UID 1001 may bind TCP port 80” is a testable rule. “Project A data must never be read by Project B” is also testable, but requires a substantially larger classification and labeling design.

    First establish the security baseline . An unsupported release, excess listener, weak account boundary, or missing recovery path should not be hidden behind a more complicated access-control layer.

    Understand how MAC composes with DAC #

    DAC uses ownership, groups, modes, and ACLs. Owners have discretion over much of that state. A MAC policy adds a system-administered check that subjects normally cannot relax at will.

    Access must pass the applicable checks. A MAC allow rule does not grant access that DAC denies, and a permissive file mode does not bypass a MAC denial. When several MAC policies are active, their restrictions compose; one policy does not cancel another policy’s denial.

    The root boundary depends on the policy. Some modules have explicit superuser exemptions, while labeled policies can constrain actions that would otherwise pass ordinary DAC checks. The system administrator can still control policy configuration in many designs, and the MAC framework does not cover every possible channel. It should not be relied on alone to contain a malicious privileged administrator.

    Prefer a simpler boundary when it expresses the rule #

    Use ordinary mechanisms when they provide the required invariant with less recovery risk:

    Requirement Usually consider first
    Separate one service from the host A jail, dedicated account, filesystem permissions, and a narrow network policy
    Prevent one account from modifying another account’s files Ownership, groups, modes, or POSIX ACLs
    Hide an administrative service from untrusted networks Service binding and firewall policy
    Drop application privilege after binding or initialization The application’s documented privilege-separation model
    Restrict CPU, memory, or process counts Jail and resource-control facilities
    Record security-relevant actions FreeBSD security event auditing rather than an access-control policy

    The jail decision guide distinguishes operating-system isolation from a virtual machine boundary. A jail and a MAC policy can be composed, but neither should be added without a separate purpose.

    Match the policy family to the requirement #

    The following map is a selection aid, not a ready-made configuration:

    Policy Narrow purpose Important design boundary
    mac_portacl(4) Permit named numeric identities to bind selected TCP or UDP ports Composes with the ordinary reserved-port restriction; rules replace the complete list
    mac_seeotheruids(4) Limit visibility of processes and sockets owned by other users Group exemptions and operational monitoring must be planned
    mac_bsdextended(4) Apply UID/GID-based rules to filesystem access Rule order, default behavior, and root handling require negative tests
    mac_ifoff(4) Prevent use of selected interface classes A wrong value can remove loopback or network recovery access
    mac_partition(4) Divide process visibility into numeric partitions It is process partitioning, not filesystem or network isolation
    mac_mls(4) Enforce confidentiality levels and compartments Requires a complete secrecy and labeling model
    mac_biba(4) Enforce integrity levels and compartments Information-flow rules may conflict with ordinary administration
    mac_lomac(4) Protect integrity through a low-watermark model Subjects may have their integrity level demoted after reading lower-integrity data

    Testing and stub modules such as mac_test(4), mac_stub(4), and mac_none(4) are not production security policies.

    For the narrow reserved-port case, use Bind a service to a low port without running it as root . That guide treats mac_portacl, the traditional reserved-port check, service identity, persistence, and rollback as one composed change.

    Distinguish module, policy, labels, and persistence #

    Four different states can be involved:

    1. The kernel contains the MAC framework. GENERIC includes it on supported FreeBSD releases covered here.
    2. A policy module is built into the kernel or loaded dynamically.
    3. The policy’s enforcement settings, rule set, or labels express the local security design.
    4. Boot and login configuration recreate that design after restart.

    Loading a module is not equivalent to completing the policy. Some non-labeling policies begin enforcing defaults as soon as they load. Labeled policies may require filesystem support, object labels, login-class labels, and interface labels before ordinary services work correctly.

    Do not compile policy modules into a custom kernel merely because a loader setting appears less permanent. A static policy is harder to remove during recovery. The kernel mechanism guide describes when static configuration is justified.

    Qualify a policy before production #

    Use a disposable or representative staging system with the same filesystem types, login paths, service accounts, jails, remote administration, and boot arrangement. A useful test matrix includes:

    Test Expected evidence
    Intended access The normal workload completes under the real service identity
    Intended denial A separate identity is denied by the MAC check being evaluated
    Root administration Documented maintenance actions behave according to the design
    Service startup Required labels, rules, and policy modules exist before the service starts
    Login and privilege transition Console, SSH, su, and other approved paths retain the correct identity and label
    Backup and restore Restored data preserves or deliberately recreates required labels and attributes
    Upgrade A release update or representative reboot preserves enforcement and service availability
    Recovery The policy can be bypassed or corrected from the available console path

    Test denials as deliberately as successful actions. A service that starts proves availability, not that the unwanted action is blocked. A denial message also does not prove the intended policy caused it; ordinary DAC, jail, or firewall controls may have rejected the operation first.

    Plan recovery before persistence #

    Capture the existing module list, policy sysctls, login-class configuration, filesystem options, and labels relevant to the proposed policy. Keep an out-of-band console available. A remote shell on the interface or account being restricted is not a recovery path.

    Introduce one policy at a time and avoid permanent boot configuration until runtime behavior has been qualified where the module permits such testing. Do not assume unloading a module reverses its work. A module may be busy, a service may retain state created before enforcement, and object labels can outlive the module load that created them.

    For a failed non-labeling policy test, restore the known rules and enforcement values before attempting a broader rule. For a failed labeling design, stop and use the documented single-user or console recovery procedure. Removing enforcement without reconciling /etc/login.conf, filesystem labels, or policy-specific configuration can leave identities and objects inconsistent.

    Every accepted deployment should retain:

    • the written rule and threat it addresses;
    • the policy module and every local setting;
    • the positive and negative test cases;
    • the authorized policy administrator;
    • console and boot recovery steps;
    • a review requirement after release upgrades or service changes.

    Avoid a universal hardening recipe #

    The strongest-looking policy is not necessarily the correct policy. MLS, Biba, and LOMAC require information-flow models that ordinary workstations and mixed-purpose servers may not possess. Enabling them without classification ownership can convert routine administration into unexplained denials and encourage unsafe exemptions.

    Prefer the least policy that makes the stated denial reliable. If the denial cannot be described and tested, the MAC configuration is not ready to implement.

    Primary references #

    • FreeBSD Handbook: Mandatory Access Control
    • mac(4)
    • mac_portacl(4)
    • mac_seeotheruids(4)
    • mac_bsdextended(4)
    • mac_ifoff(4)
    • mac_partition(4)
    • mac_mls(4)
    • mac_biba(4)
    • mac_lomac(4)

    Independent documentation. Not affiliated with or endorsed by the FreeBSD Project or the FreeBSD Foundation.

    Report a bug
    • Synopsis
    • Start with the rule, not the module
    • Understand how MAC composes with DAC
    • Prefer a simpler boundary when it expresses the rule
    • Match the policy family to the requirement
    • Distinguish module, policy, labels, and persistence
    • Qualify a policy before production
    • Plan recovery before persistence
    • Avoid a universal hardening recipe
    • Primary references