> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-30-security-auditing/di-30.4-jie-qiang-zhi-fang-wen-kong-zhi-kuang-jia-mac-kuang-jia.md).

# 30.4 Mandatory Access Control Framework (MAC Framework)

## Overview

FreeBSD's Mandatory Access Control (MAC) framework allows fine-grained control over system security through loadable security policy modules. MAC can load access control modules to enforce security policies. Some modules provide protection for narrow subsets of the system, hardening specific services, while others provide comprehensive labeled security across all subjects and objects. The term "mandatory" means that control is exercised by the administrator and the operating system, in contrast to the default Discretionary Access Control (DAC), where users make their own access decisions.

MAC policies **cannot override** traditional Unix security mechanisms (file permissions and superuser checks); they only impose additional restrictions on top of DAC. In other words, even if MAC is configured to allow access, if DAC denies it, the operation will still fail. MAC policies can restrict `root` privileges, which is one of the key distinctions from DAC.

The MAC framework was first introduced in FreeBSD 5.0 as part of the TrustedBSD project, designed by Robert Watson and implemented by the Network Associates Laboratories (NAI Labs) security research division, under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), part of the DARPA CHATS research program.

The MAC framework design references IEEE POSIX.1e Draft 17 (formerly known as POSIX.1e), which aimed to define security extensions for operating systems, including access control lists (ACLs), auditing, and mandatory access control. POSIX.1e was never finalized as an official standard, and FreeBSD's MAC implementation is the result of independent evolution by the TrustedBSD project based on practical requirements, not fully equivalent to any approved international or industry standard.

Improper MAC configuration may result in inability to access the system, disruption of normal user operations, or inability to start Xorg. Furthermore, MAC alone should not be relied upon to protect the system. The MAC framework only enhances existing security policies; without sound security practices and regular security audits, the system remains vulnerable.

The examples in this chapter are for demonstration purposes only and **should not** be implemented on production systems. Any security policy implementation requires thorough understanding, proper design, and comprehensive testing.

While this section covers a wide range of MAC framework security issues, it does not address the development of new MAC security policy modules. Many of the policy modules in the MAC framework have specific characteristics and can also be used for testing purposes.

## Standards Compliance

FreeBSD's MAC implementation is related to the following standards and drafts:

* **IEEE POSIX.1e Draft 17**: The mac(3) userspace API and the maclabel(7) label format are based on this draft. The API has only weak similarity to the POSIX draft because the POSIX API cannot express certain concepts required for flexible and extensible access control.
* **File System Access Control Lists**: The ACL mechanism defined in the POSIX.1e draft is independently implemented by FreeBSD through the getfacl(1)/setfacl(1) commands and is not part of the MAC framework.
* **Label Semantics**: The semantics of the three labeling policies (Biba, MLS, LOMAC) respectively follow their own security model theories, which originate from classical military security policy and commercial integrity policy research.

## Key Terminology

The following key terms are used when discussing the MAC framework:

* **Compartment**: A group of programs and data that need to be partitioned or isolated; users must be explicitly authorized to access specific system components. Compartments represent groupings such as workgroups, departments, projects, or topics, enabling need-to-know security policies.
* **Integrity**: The level of trust that can be assigned to data. Higher data integrity means greater trust in it.
* **Level**: An increasing or decreasing setting of a security attribute. A higher level means greater security.
* **Label**: A security attribute that can be applied to system objects such as files and directories, comparable to a confidentiality stamp. When a label is applied to a file, it describes its security attributes, allowing access only to files, users, and resources with similar security settings. The meaning and interpretation of label values depend on policy configuration: some policies treat labels as representations of object integrity or confidentiality, while others use labels to hold access rules.
* **Multilabel**: This attribute is a file system option that can be set with tunefs(8) in single-user mode, via fstab(5) during the boot process, or when creating a new file system. This option allows administrators to apply different MAC labels to different objects, and is only applicable to security policy modules that support labeling.
* **Single label**: A policy where the entire file system enforces access control using one label for data flow. When `multilabel` is not set, all files follow the same label setting.
* **Object**: An entity through which information flows under the direction of a **subject**, including directories, files, fields, screens, keyboards, memory, magnetic storage, printers, and other data storage or transmission devices. An object is a data container or system resource; accessing an object means accessing its data.
* **Subject**: An active entity that causes information to flow between **objects**, such as a user, user process, or system process. In FreeBSD, a subject is almost always a thread executing operations on behalf of a user within a process.
* **Policy**: A set of rules defining how objectives are achieved, typically documenting how a certain class of objects is handled. In this chapter, a policy is viewed as a set of rules that control data and information flow and define access permissions.
* **High-watermark**: A policy that allows raising the security level to access higher-level information, with most processes reverting to their original level upon completion. Currently, the FreeBSD MAC framework does not include such a policy.
* **Low-watermark**: A policy that allows lowering the security level to access lower-security information, with most processes reverting to the user's original level upon completion. In FreeBSD, only mac\_lomac(4) uses this policy.
* **Sensitivity**: Most commonly used in Multilevel Security (MLS) discussions. A sensitivity level describes the importance or confidentiality of data; the higher the level, the more important the data's confidentiality or secrecy.

## Understanding MAC Labels

MAC labels are security attributes that can be applied to subjects and objects in the system. When setting labels, administrators need to understand their implications to prevent unexpected or unintended system behavior. The available attributes for objects depend on the loaded policy modules, and each module interprets attributes differently.

The security label on an object is used by policies as part of access control decisions. In some policies, the label contains all the information for the decision; in others, the label may be processed as part of a larger rule set.

Label policies are divided into single-label and multilabel categories. The system uses single-label by default. Administrators should understand the advantages and disadvantages of each to implement a policy that matches the system's security model.

A single-label policy enforces one set of access permissions across the system, with lower management overhead but reduced flexibility for labeling policies, allowing only one label per subject or object. However, in many environments, a single label is sufficient.

A single-label policy is somewhat similar to DAC in that `root` configures the policy to place users in appropriate categories and access levels. The significant difference is that many policy modules can also restrict `root`. Basic control of objects is delegated to groups, but `root` can revoke or modify settings at any time.

When appropriate, `multilabel` can be passed to tunefs(8) to set a multilabel policy for UFS file systems. A multilabel policy allows each subject or object to have its own independent MAC label. The decision between single-label or multilabel is only necessary for policies that implement labeling functionality, such as `biba`, `lomac`, and `mls`. Some policies (such as `seeotheruids`, `portacl`, `partition`) do not use labels at all. The `multilabel` feature is natively supported on UFS2 file systems and must be enabled by running `tunefs -l enable` in single-user mode. MAC label support for ZFS file systems may differ due to implementation differences.

Because everything in a file system has a label — including directories, files, and even device nodes — using a multilabel policy on a partition and establishing a multilabel security model may increase management overhead.

The following command will set multilabel `multilabel` on the specified UFS file system. This command should be executed in single-user mode and is not required for swap file systems:

```sh
# Must be executed in single-user mode
# tunefs -l enable /
tunefs: multilabel remains unchanged as enabled
```

> **Note**
>
> If the above command is not executed in single-user mode, it will always display the error message "tunefs: / is not clean - run fsck."

Some users have encountered issues when setting the `multilabel` flag on the root partition (such as label configuration not taking effect, or the system failing to boot properly). For specific troubleshooting steps, see the "MAC Framework Troubleshooting" section at the end of this chapter.

Since multilabel policies are set per file system, a multilabel policy may not be needed if the file system layout is well-organized. Consider a FreeBSD web server MAC security model design: by default, everything on this computer's file system uses the single label `biba/high`. If the web server needs to run at `biba/low` to prevent upward writes, it can be installed on a separate UFS file system **/usr/local** set to `biba/low`.

### Configuring Labels

Almost all configuration for label policy modules can be accomplished using base system tools. These commands configure objects or subjects, or provide a simple interface for configuration control and verification.

All configuration can be done using `setfmac` (set MAC labels for system objects) and `setpmac` (set labels for system subjects). For example, to set the MAC label `biba` of test to `high`:

```sh
# setfmac biba/high test
```

Upon successful execution, the command returns to the prompt with no error message.

The common error `Permission denied` typically occurs when attempting to set or modify a label on a restricted object. Other situations may result in different failures: the file may not belong to the user attempting to relabel the object, the object may not exist, or the object may be read-only. The enforced policy may prohibit a process from relabeling a file for reasons related to the file's attributes, the process's attributes, or the new label value's attributes. For example, a low-integrity user attempting to change a high-integrity file's label, or a low-integrity user attempting to change a low-integrity file's label to high-integrity, will both fail.

System administrators can use `setpmac` to assign a different label to an invoked process, overriding the policy module settings:

```sh
# setfmac biba/high test
Permission denied
# setpmac biba/low setfmac biba/high test
# getfmac test
test: biba/high
```

For currently running processes (such as sshd), `getpmac` is typically used to obtain their label. This command takes a process ID (PID) instead of a command name. If a user attempts to access a file outside their permissions, an `Operation not permitted` error will be displayed due to the restrictions of the loaded policy module.

### Predefined Labels

Some FreeBSD policy modules that support labeling provide three predefined labels: `low`, `equal`, and `high`:

| Label   | Description                                                                                                                        |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `low`   | The lowest label setting an object or subject can have. Setting this label prevents access to objects or subjects labeled as high. |
| `equal` | Disables or exempts the subject or object from the policy; should only be placed on objects that are exempt from the policy.       |
| `high`  | Grants the highest setting available to an object or subject in the Biba and MLS policy modules.                                   |

Such policy modules include mac\_biba(4), mac\_mls(4), and mac\_lomac(4). Each predefined label establishes different information flow directives; refer to the module manual pages for general label configuration characteristics.

### Numeric Labels

The Biba and MLS policy modules support numeric labels, which can be set to indicate precise levels of hierarchical control. This numeric value is used to divide information into different classification groups, allowing access only to that group or higher levels. For example:

```
biba/10:2+3+6(5:2+3-20:2+3+4+5+6)
```

This can be interpreted as "Biba policy label/grade 10: compartments 2, 3, and 6: (grade 5 …)."

In this example, the first grade is the effective grade with effective compartments, the second is the low grade, and the last is the high grade. Most configurations do not require this level of granularity, as it constitutes advanced configuration.

System objects have only a current grade and compartment. System subjects reflect the range of available permissions in the system and the network interfaces used for access control.

The grades and compartments in subject-object pairs are used to construct a **dominance** relationship: the subject dominates the object, the object dominates the subject, neither dominates the other, or they dominate each other. "Mutual dominance" occurs when two labels are equal. Due to Biba information flow characteristics, a user possesses a set of permissions that may correspond to project compartment permissions, and objects also possess a set of compartments. A user may need to use `su` or `setpmac` to reduce permissions to access objects in unrestricted compartments.

### User Labels

Users need to configure labels in **/etc/login.conf** using login classes to ensure their files and processes interact correctly with the system security policy. Each policy module that uses labels implements user class settings.

To set default labels for the user class enforced by MAC, add a `label` entry. An example `label` entry containing each policy module is shown below. Note that in actual configuration, administrators would not enable all policy modules. It is recommended to read this entire section before implementation.

```ini
default:
	:welcome=/etc/motd:
	:setenv=MAIL=/var/mail/$,BLOCKSIZE=K:
	:path=~/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:
	:manpath=/usr/share/man /usr/local/man:
	:nologin=/usr/sbin/nologin:
	:cputime=1h30m:
	:datasize=8M:
	:vmemoryuse=100M:
	:stacksize=2M:
	:memorylocked=4M:
	:memoryuse=8M:
	:filesize=8M:
	:coredumpsize=8M:
	:openfiles=24:
	:maxproc=32:
	:priority=0:
	:requirehome:
	:passwordtime=91d:
	:umask=022:
	:ignoretime@:
	:label=partition/13,mls/5,biba/10(5-15),lomac/10[2]:
```

Users cannot modify the default values, but after logging in they can change labels within the policy constraints. The above example tells the Biba policy that a process has a minimum integrity of 5, a maximum of 15, and a default effective label of 10. The process runs at 10 until it chooses to change (possibly because the user uses `setpmac`), constrained by the Biba-configured range.

After modifying the **/etc/login.conf** file, the login class capability database must be rebuilt using `cap_mkdb`.

Many sites have numerous users and need to divide them into different user classes with in-depth planning, which can make management complex.

### Network Interface Labels

Labels can be set on network interfaces to help control data flow across the network. Network interface labels function the same way as object labels in each policy. For example, in Biba, a user at a high setting is not allowed to access a network interface labeled `low`.

When setting MAC labels on network interfaces, the `maclabel` parameter can be used with `ifconfig`:

```sh
# ifconfig bge0 maclabel biba/equal
```

This example sets a MAC label of `biba/equal` on the `bge0` interface. When using settings like `biba/high(low-high)`, the entire label should be quoted to prevent errors.

Each policy module that supports labeling has tunable parameters that can be used to disable MAC labels on network interfaces. Setting the label to `equal` has a similar effect. For details on tunable parameters, see the `sysctl` output, policy manual pages, and subsequent sections of this chapter.

## Planning Security Configuration

Before implementing any MAC policy, planning is recommended. The planning phase should consider implementation requirements and objectives, such as:

* How to classify information and resources on the target system.
* Which information or resources to restrict access to, and what access restrictions to impose.
* Which MAC modules are needed to achieve these objectives.

Before implementing MAC on a production system, a trial run should be conducted on a trusted system with its configuration. Different environments have different requirements, and establishing a complete security configuration can reduce post-deployment modifications.

Consider how the MAC framework enhances overall system security. The various security policy modules provided by the MAC framework can be used to protect networks and file systems, or to prevent users from accessing specific ports and sockets. Perhaps the best use of policy modules is to load multiple modules simultaneously to provide an MLS environment, an approach distinct from policies that only target specific purposes and harden isolated system elements. The downside of MLS is increased management overhead.

However, this overhead is acceptable compared to the long-term benefits of the framework's flexible policy selection with low performance overhead. Reducing support for unnecessary policies can improve overall system performance while providing selection flexibility. A good implementation should consider overall security requirements and effectively deploy the various security policy modules provided by the framework.

MAC ensures that users cannot arbitrarily change system security attributes. All user utilities, programs, and scripts must operate within the access rules of the selected security policy modules, and MAC access rule control rests with the system administrator.

It is the system administrator's responsibility to carefully select the correct security policy modules. For environments requiring network access control restrictions, mac\_portacl(4), mac\_ifoff(4), and mac\_biba(4) are good starting points. For environments requiring strict confidentiality of file system objects, mac\_bsdextended(4) and mac\_mls(4) may be considered.

Policy decisions can be based on network configuration. If only specific users should be allowed to access ssh(1), mac\_portacl(4) is an appropriate choice. On the file system side, access to objects may be confidential for some users but not for others. For example, a large development team might be split into smaller project groups: developers in project A must not access objects written by developers in project B, but both groups may need to access objects created by developers in project C. Using the different security policy modules provided by the MAC framework, users can be divided into groups and granted appropriate access permissions.

Each security policy module has a unique approach to handling system security. Module selection should be based on a well-considered security policy, which may need revision and reimplementation. Understanding the different security policy modules provided by the MAC framework helps administrators choose the best solution.

Implementing MAC is similar to implementing a firewall; care must be taken to prevent the administrator from being completely locked out. The ability to revert to a previous configuration should be considered, and extra caution should be exercised when implementing MAC through remote connections.

## Available MAC Policies

The default FreeBSD kernel includes `options MAC`. The source code path is **sys/security**.

After testing a module, add the module name to **/boot/loader.conf** for loading at boot time. Each module also provides a kernel option for administrators who choose to compile a custom kernel.

### Module Loading Timing Restrictions

| Module               | Description                                   | Label Support | Loading Timing |
| -------------------- | --------------------------------------------- | ------------- | -------------- |
| mac\_biba(4)         | Biba integrity policy                         | Yes           | Boot only      |
| mac\_bsdextended(4)  | File system firewall                          | No            | Any time       |
| mac\_ddb(4)          | Kernel debugger interface restriction         | No            | Any time       |
| mac\_do(4)           | Non-privileged user credential changes        | No            | Any time       |
| mac\_ifoff(4)        | Interface silencing                           | No            | Any time       |
| mac\_ipacl(4)        | IP address access control                     | No            | Any time       |
| mac\_lomac(4)        | Low-Watermark integrity policy                | Yes           | Boot only      |
| mac\_mls(4)          | Multilevel security confidentiality policy    | Yes           | Boot only      |
| mac\_none(4)         | Null policy module (no access control effect) | No            | Any time       |
| mac\_ntpd(4)         | NTP unprivileged operation                    | No            | Any time       |
| mac\_partition(4)    | Process partition policy                      | Yes           | Any time       |
| mac\_portacl(4)      | Port binding access control                   | No            | Any time       |
| mac\_priority(4)     | Scheduling priority policy                    | No            | Any time       |
| mac\_seeotheruids(4) | Cross-user visibility policy                  | No            | Any time       |

The following sections describe each of these policies individually. The last three labeling policies (Biba, MLS, LOMAC) support using integer values instead of the three default labels.

### MAC See Other UIDs Policy

Module name: mac\_seeotheruids.ko

Kernel configuration line: `options MAC_SEEOTHERUIDS`

Boot option: `mac_seeotheruids_load="YES"`

The mac\_seeotheruids(4) module provides an independent sysctl tunable tree `security.mac.seeotheruids.*`, whose functionality is similar to `security.bsd.see_other_uids` and `security.bsd.see_other_gids`. This option does not require prior label setup and can transparently interoperate with other modules.

After loading the module, the following `sysctl` tunable parameters are available to control functionality:

* `security.mac.seeotheruids.enabled` enables the module and enforces the default setting, denying users the ability to view processes and sockets owned by other users.
* `security.mac.seeotheruids.suser_privileged` when set to a non-zero value, allows the superuser (`root`) to view processes and sockets of all users.
* `security.mac.seeotheruids.specificgid_enabled` allows specifying a group to be exempt from this policy. Set using the `security.mac.seeotheruids.specificgid=XXX` tunable, replacing *XXX* with the numeric group ID.
* `security.mac.seeotheruids.primarygroup_enabled` is used to exempt specific primary groups. Users in the exempted group can view each other's processes and sockets.

### MAC BSD Extended Policy

Module name: mac\_bsdextended.ko

Kernel configuration line: `options MAC_BSDEXTENDED`

Boot option: `mac_bsdextended_load="YES"`

The mac\_bsdextended(4) module implements a file system firewall, providing an extension to the standard file system permission model that allows administrators to create firewall-like rule sets to protect files, utilities, and directories within the file system hierarchy. When a file system object is accessed, the rule list is traversed until a matching rule is found or the end is reached. This behavior can be changed with `security.mac.bsdextended.firstmatch_enabled`. Similar to other FreeBSD firewall modules, a file containing access control rules can be created and read by the system at boot time using rc.conf(5) variables.

The rule list can be entered using ugidfw(8), with syntax similar to ipfw(8). Additional tools can be written using libugidfw(3) library functions.

After loading the mac\_bsdextended(4) module, the current rule configuration can be viewed with the following command:

```sh
# ugidfw list
0 slots, 0 rules
```

By default, no rules are defined and all content is fully accessible. Create a rule to block all users but not affect `root`:

> **Warning**
>
> This rule will prevent all non-root users from doing anything, potentially rendering the system completely unusable. This is shown only as a negative example and must never be used in production environments.

```sh
# ugidfw add subject not uid root new object not uid root mode n
```

While simple, this rule is an extremely poor practice: it prevents all users from executing any command. A more practical example is blocking all access by `user1` to `user2`'s home directory (including directory listings):

```sh
# ugidfw set 2 subject uid user1 object uid user2 mode n
# ugidfw set 3 subject uid user1 object gid user2 mode n
```

`not uid user2` can be used instead of `user1` to enforce the same access restrictions for all users. However, `root` is not affected by this rule.

This module should be used with extra caution, as improper use may block access to portions of the file system.

### MAC DDB Policy

Module name: mac\_ddb.ko

Kernel configuration line: `options MAC_DDB`

Boot option: `mac_ddb_load="YES"`

The mac\_ddb(4) policy module restricts the subset of commands available at the kernel debugger ddb(4) command prompt. Allowed commands are limited to those that do not involve arbitrary memory read or write operations, preventing the extraction of system secrets while retaining sufficient debugging functionality to diagnose kernel panics. For example, `trace` or `show registers` are allowed, but `show buffer addr` is not.

All debugger commands declared with the `DB_CMD_MEMSAFE` flag are permitted. The policy also provides a validation function that conditionally allows certain additional commands based on user parameters.

Once loaded, mac\_ddb also ensures that only the ddb(4) debugger backend can be executed, not gdb(4).

This policy does not use labels.

### MAC DO Policy

Module name: mac\_do.ko

Kernel configuration line: `options MAC_DO`

Boot option: `mac_do_load="YES"`

The mac\_do(4) policy module allows non-privileged users to change process credentials (user ID and group ID) according to administrator-configured rules, supporting per-jail independent configuration.

This policy takes effect through the **/usr/bin/mdo** executable; for details, refer to mdo(1). Rules are specified as strings in `from>to` format, where each rule contains a `from` part (matching current credentials) and a `to` part (target credentials), with multiple rules separated by semicolons `;`.

The following sysctl tunable parameters are available:

* `security.mac.do.enabled` enables or disables the mac\_do policy (default: 1).
* `security.mac.do.rules` credential rule list, configured independently per jail.

mac\_do supports per-jail rule configuration. Each jail must have mdo(1) installed at the **/usr/bin/mdo** path. Jail parameters include `mac.do` (`enable`/`disable`/`inherit`) and `mac.do.rules`.

Unlike the traditional setuid approach, mac\_do does not rely on setuid programs to determine whether a credential change is acceptable; instead, the kernel makes the decision based on administrator-configured rules, thereby avoiding the security risks of setuid program vulnerabilities.

### MAC Interface Silencing Policy

Module name: mac\_ifoff.ko

Kernel configuration line: `options MAC_IFOFF`

Boot option: `mac_ifoff_load="YES"`

The mac\_ifoff(4) module is used to dynamically disable network interfaces, preventing them from coming up during system boot. It does not use labels and does not depend on any other MAC modules.

This module is primarily controlled through the following `sysctl` tunable parameters:

* `security.mac.ifoff.lo_enabled` enables or disables all traffic on the loopback interface lo(4).
* `security.mac.ifoff.bpfrecv_enabled` enables or disables all traffic on the Berkeley Packet Filter interface bpf(4).
* `security.mac.ifoff.other_enabled` enables or disables traffic on all other interfaces.

One of the most common uses of mac\_ifoff(4) is network monitoring in environments where network traffic must be blocked during boot. Another use is writing scripts that automatically block network traffic when applications such as security/aide discover new or changed files in protected directories.

### MAC IP Address Access Control List Policy

Module name: mac\_ipacl.ko

Kernel configuration line: `options MAC_IPACL`

Boot option: `mac_ipacl_load="YES"`

The mac\_ipacl(4) policy allows a host to restrict the ability of VNET(9) jails to set IPv4 and IPv6 addresses using the sysctl(8) interface. When the default policy is enforced, all IP addresses for jails are denied.

The following sysctl tunable parameters are available:

* `security.mac.ipacl.ipv4` enforces mac\_ipacl for IPv4 addresses (default: 1).
* `security.mac.ipacl.ipv6` enforces mac\_ipacl for IPv6 addresses (default: 1).
* `security.mac.ipacl.rules` IP address access control list, format is `jid,allow,interface,addr_family,IP_addr/prefix[@jid,...]`. Where `allow` is 1 for allow, 0 for deny; `interface` left empty matches all interfaces; `addr_family` is `AF_INET` or `AF_INET6`; `prefix` of -1 means a single IP, non-negative value means a subnet.

When multiple rules apply to the same IP address, the rule defined later in the list determines the final result.

### MAC Port Access Control List Policy

Module name: mac\_portacl.ko

Kernel configuration line: `options MAC_PORTACL`

Boot option: `mac_portacl_load="YES"`

The mac\_portacl(4) module is used to restrict local TCP and UDP port binding, allowing non-`root` users to bind to specified privileged ports below 1024.

Once loaded, this module enables the MAC policy on all sockets. The following tunable parameters are provided:

* `security.mac.portacl.enabled` fully enables or disables this policy.
* `security.mac.portacl.port_high` sets the highest port number protected by mac\_portacl(4).
* `security.mac.portacl.suser_exempt` when set to a non-zero value, exempts `root` from this policy.
* `security.mac.portacl.autoport_exempt` when set to a non-zero value (default), allows applications to use port 0 for automatic allocation, bypassing rule checking.
* `security.mac.portacl.rules` specifies the policy as a text string, format `rule[,rule,…]`, containing as many rules as needed, each in the format `idtype:id:protocol:port`. `idtype` should be `uid` or `gid`; `protocol` can be `tcp` or `udp`; `port` is the port number allowed for the specified user or group to bind. User ID, group ID, and port parameters use numeric values only.

By default, ports below 1024 can only be used by privileged processes running as `root`. To allow mac\_portacl(4) to permit non-privileged processes to bind to ports below 1024, configure as follows:

```sh
# sysctl security.mac.portacl.port_high=1023
# sysctl net.inet.ip.portrange.reservedlow=0
# sysctl net.inet.ip.portrange.reservedhigh=0
```

> **Warning**
>
> Setting both `net.inet.ip.portrange.reservedlow` and `net.inet.ip.portrange.reservedhigh` to `0` completely removes the kernel-level privileged port protection mechanism, meaning ports 1-1023, which were originally only bindable by `root`, are no longer subject to any kernel restrictions. The implication of this configuration is: **replacing traditional UNIX privileged port protection entirely with mac\_portacl's rule-level protection**.
>
> If the mac\_portacl module is not loaded for any reason, is disabled (`security.mac.portacl.enabled=0`), or the rule configuration is incorrect, the system will revert to a state where **all users can bind to any port** — this includes critical service ports such as SSH (22), HTTP (80), and HTTPS (443), which may lead to service hijacking or privilege escalation attacks. Ensure that `mac_portacl` is always reliably loaded and that rules are complete.

To prevent `root` from being affected by this policy, set `security.mac.portacl.suser_exempt` to a non-zero value:

```sh
# sysctl security.mac.portacl.suser_exempt=1
```

Allow the `www` user with UID 80 to bind to port 80 without `root` privileges:

```sh
# sysctl security.mac.portacl.rules=uid:80:tcp:80
```

The following example allows the user with UID 1001 to bind to TCP ports 110 (POP3) and 995 (POP3s):

```sh
# sysctl security.mac.portacl.rules=uid:1001:tcp:110,uid:1001:tcp:995
```

### MAC NTPD Policy

Module name: mac\_ntpd.ko

Kernel configuration line: `options MAC_NTPD`

Boot option: `mac_ntpd_load="YES"`

The mac\_ntpd(4) policy module allows ntpd(8) to run as a non-`root` user, granting the following privileges to processes running under UID 123 (the `ntpd` user):

| Privilege                   | Description           |
| --------------------------- | --------------------- |
| `PRIV_ADJTIME`              | Adjust system time    |
| `PRIV_CLOCK_SETTIME`        | Set system clock      |
| `PRIV_NTP_ADJTIME`          | NTP time adjustment   |
| `PRIV_NETINET_RESERVEDPORT` | Bind privileged ports |
| `PRIV_NETINET_REUSEPORT`    | Reuse ports           |

When ntpd(8) is started with `-u <user>[:group]`, it first initializes with root privileges and then drops privileges to the specified user. This policy ensures that ntpd can still perform the privileged operations required for time synchronization after dropping privileges.

The following sysctl tunable parameters are available:

* `security.mac.ntpd.enabled` enables the mac\_ntpd policy (default: 1).
* `security.mac.ntpd.uid` numeric UID of the ntpd user (default: 123).

### MAC Partition Policy

Module name: mac\_partition.ko

Kernel configuration line: `options MAC_PARTITION`

Boot option: `mac_partition_load="YES"`

The mac\_partition(4) policy places processes into specific "partitions" based on their MAC labels. Most configuration for this policy is done using setpmac(8). `sysctl` tunable parameter:

* `security.mac.partition.enabled` enables MAC process partition enforcement.

When this policy is enabled, users can only view their own processes and other processes within their partition, and cannot use utilities outside their partition scope. For example, users in the `insecure` class cannot access `top` and many commands that require spawning processes.

This example adds `top` to the label set for the `insecure` class of users. All processes of the `insecure` class remain within the `partition/13` label:

```sh
# setpmac partition/13 top
```

Display partition labels and process list:

```sh
# ps Zax
```

Display partition labels for another user's processes and that user's currently running processes:

```sh
# ps -ZU trhodes
```

Unless mac\_seeotheruids(4) is loaded, users can see processes in the `root` label.

### MAC Priority Policy

Module name: mac\_priority.ko

Kernel configuration line: `options MAC_PRIORITY`

Boot option: `mac_priority_load="YES"`

The mac\_priority(4) policy module grants scheduling priority privileges based on group(5) group membership. Users or processes in the `realtime` group (GID 47) are allowed to run threads and processes at real-time scheduling priority; users or processes in the `idletime` group (GID 48) are allowed to run at idle scheduling priority.

The realtime policy grants the following kernel privileges:

* `PRIV_SCHED_RTPRIO` — Real-time priority
* `PRIV_SCHED_SETPOLICY` — Set scheduling policy

The idletime policy grants the following kernel privilege:

* `PRIV_SCHED_IDPRIO` — Idle priority

With realtime enabled, privileged users can use rtprio(1) to start processes at real-time priority; with idletime enabled, idprio(1) can be used to start processes at idle priority. Applications can adjust priority through the rtprio(2) system call.

The following sysctl tunable parameters are available:

* `security.mac.priority.realtime` enables the realtime policy (default: 1).
* `security.mac.priority.realtime_gid` numeric GID of the realtime group (default: 47).
* `security.mac.priority.idletime` enables the idletime policy (default: 1).
* `security.mac.priority.idletime_gid` numeric GID of the idletime group (default: 48).

### MAC Multilevel Security Module

Module name: mac\_mls.ko

Kernel configuration line: `options MAC_MLS`

Boot option: `mac_mls_load="YES"`

The mac\_mls(4) policy enforces strict information flow control, managing access between subjects and objects in the system.

In an MLS environment, each subject or object's label contains a "clearance" level and compartments. The clearance level can reach thousands, making it extremely labor-intensive to configure each subject or object individually. To reduce management burden, this policy includes three built-in labels: `mls/low`, `mls/equal`, and `mls/high`:

* The `mls/low` label represents a low clearance level, cannot access higher-level information, and prevents higher-level objects from writing or passing information to lower levels.
* The `mls/equal` label applies to objects that need to be exempt from the policy.
* `mls/high` is the highest clearance level. Objects assigned this label dominate all other objects in the system, but information cannot be leaked to lower-level objects.

MLS provides:

* Hierarchical security levels, accompanied by a set of non-hierarchical categories;
* The fixed rule "no read up, no write down" — subjects can read objects at the same or lower level, but cannot read higher-level objects; similarly, subjects can write to objects at the same or higher level, but cannot write to lower-level objects;
* Confidentiality (prevention of improper data disclosure);
* A design foundation that supports processing data at multiple sensitivity levels concurrently in the same system without leaking information between confidential and classified levels.

The following `sysctl` tunable parameters are available:

* `security.mac.mls.enabled` enables or disables the MLS policy.
* `security.mac.mls.ptys_equal` marks all pty(4) devices as `mls/equal` upon creation.
* `security.mac.mls.revocation_enabled` revokes access to objects after a label changes to a lower grade.
* `security.mac.mls.max_compartments` sets the maximum number of compartment levels allowed in the system.

MLS labels are managed using setfmac(8). To assign a label to an object:

```sh
# setfmac mls/5 test
```

Get the MLS label of the file test:

```sh
# getfmac test
```

A master policy file can also be created in the **/etc/** path, specifying MLS policy information for processing by `setfmac`.

When using the MLS policy module, administrators need to plan the flow of sensitive information. The default `block read up block write down` sets all objects to a low level: everything is accessible, and administrators gradually increase information confidentiality.

Beyond the three basic labels, administrators can group users and groups as needed to block information flow. Using descriptive terms (such as `Confidential`, `Secret`, and `Top Secret`) to view clearance level information may be more intuitive. Some administrators establish different groupings by project level. Regardless of the classification method, careful planning is required before implementing a restrictive policy.

Typical application scenarios for the MLS policy module include e-commerce web servers, file servers storing critical corporate information, and financial institution environments.

### MAC Biba Module

Module name: mac\_biba.ko

Kernel configuration line: `options MAC_BIBA`

Boot option: `mac_biba_load="YES"`

The mac\_biba(4) module loads the MAC Biba policy. This policy is similar to the MLS policy, but the information flow rules are exactly reversed: Biba prevents sensitive information from flowing downward, while MLS prevents sensitive information from flowing upward.

In a Biba environment, each subject or object is assigned an "integrity" label. The label consists of a hierarchical grade and non-hierarchical components. Higher grades indicate higher integrity.

The supported labels are `biba/low`, `biba/equal`, and `biba/high`:

* `biba/low` is the lowest integrity an object or subject can have. Setting this label on an object or subject prevents it from writing to objects or subjects labeled `biba/high`, but read access is unrestricted.
* `biba/equal` is only used for objects that need to be exempt from the policy.
* `biba/high` allows writing to objects with lower labels, but prevents reading from objects with lower labels. It is recommended to assign this label to objects that affect the overall integrity of the system.

Biba provides:

* Hierarchical integrity levels, accompanied by a set of non-hierarchical integrity categories;
* The fixed rule "no write up, no read down", the opposite of MLS — subjects can write to objects at the same or lower level, but cannot write to higher-level objects; similarly, subjects can read objects at the same or higher level, but cannot read lower-level objects;
* Integrity assurance (prevention of improper data tampering);
* Based on integrity levels rather than MLS sensitivity levels.

The following tunable parameters control the Biba policy:

* `security.mac.biba.enabled` enables or disables Biba policy enforcement.
* `security.mac.biba.ptys_equal` disables the Biba policy on pty(4) devices.
* `security.mac.biba.revocation_enabled` revokes access to objects after a label changes to one that dominates the subject.

Access to Biba policy settings on system objects uses `setfmac` and `getfmac`:

```sh
# setfmac biba/low test
# getfmac test
test: biba/low
```

Integrity (as distinct from sensitivity) is used to ensure that information is not controlled by untrusted parties, including information transmitted between subjects and objects. It ensures that users can only modify or access information they are explicitly authorized to access. The mac\_biba(4) security policy module allows administrators to configure which files and programs users can view and invoke, while ensuring that these programs and files are trusted for that user.

During the initial planning phase, administrators need to divide users into grades, levels, and compartments. When this policy module is enabled, the system defaults to a high label, and administrators configure different grades and levels for different users. A good planning approach is to organize by topic rather than clearance level. For example, only allow developers to have modification privileges for the source code repository, source code compilation programs, and other development utilities; other users (such as testers, designers, or end users) are only allowed read access.

Lower-integrity subjects cannot write to higher-integrity subjects; higher-integrity subjects cannot list or read lower-integrity objects. Setting labels to the lowest possible grade may make objects inaccessible to subjects. Suitable environments for this security policy module include restricted web servers, development and testing machines, and source code repositories; less suitable scenarios include personal workstations, routers, or network firewalls.

### MAC Low-watermark Module

Module name: mac\_lomac.ko

Kernel configuration line: `options MAC_LOMAC`

Boot option: `mac_lomac_load="YES"`

Unlike the MAC Biba policy, mac\_lomac(4) allows access to lower-integrity objects, provided that integrity rules are not violated and the subject's integrity level is lowered first.

The Low-watermark integrity policy works essentially the same as Biba, with the difference being the use of floating labels: subject demotion is supported through an auxiliary grade compartment. The auxiliary compartment format is `[auxgrade]`. The syntax for assigning a policy with an auxiliary grade is `lomac/10[2]`, where `2` is the auxiliary grade.

This policy relies on universally labeling all system objects with integrity labels, allowing subjects to read from low-integrity objects and then lower the subject's label, using `[auxgrade]` to prevent subsequent writes to high-integrity objects. Compared to Biba, this policy offers greater compatibility and requires less initial configuration.

As with Biba and MLS policies, use `setfmac` and `setpmac` to place labels on system objects:

```sh
# setfmac lomac/high[low] /usr/home/trhodes
# getfmac /usr/home/trhodes
```

The auxiliary grade `low` is a feature unique to the LOMAC policy.

## User Lockdown

This example envisions a small storage system with fewer than fifty users. Users can log in, store data, and access resources.

In this scenario, the mac\_bsdextended(4) and mac\_seeotheruids(4) policy modules can coexist, both hiding user processes and blocking access to system objects.

First, add the following to **/boot/loader.conf**:

```ini
mac_seeotheruids_load="YES"
```

Add the following lines to **/etc/rc.conf** to activate the mac\_bsdextended(4) security policy module:

```ini
ugidfw_enable="YES"
```

During system initialization, the default rules from **/etc/rc.bsdextended** will be loaded. The default entries may need modification. This computer is only used for user services; all entries except the last two can be left commented out to enforce default loading of user-owned system objects.

Add the required users to this computer and reboot. For testing, log in as different users on two separate consoles. Run `ps aux` to check if other users' processes are visible. Verify that running ls(1) on other users' home directories fails.

Do not test as `root` unless specific `sysctl` settings have been modified to prevent superuser access.

When adding new users, their mac\_bsdextended(4) rules will not appear in the rule set list. To quickly update the rule set, first unload the security policy module, then reload it using kldunload(8) and kldload(8).

## Troubleshooting

This section discusses common configuration errors and their solutions.

### The `multilabel` Flag Fails to Remain Enabled on the Root (**/**) Partition

If the `multilabel` flag fails to remain enabled on the root (**/**) partition, the following steps can resolve this temporary error:

1. Edit **/etc/fstab** and set the root partition to `ro` (read-only).
2. Reboot into single-user mode.
3. Run the command `tunefs -l enable` on **/**.
4. Immediately run `mount -urw /`, and change `ro` back to `rw` in **/etc/fstab**.
5. Reboot the system to normal mode.
6. Carefully check the `mount` output to confirm that the root file system has the `multilabel` flag properly set.

### Unable to Start Xorg

After establishing a secure environment with MAC, Xorg cannot start. The cause may be the MAC `partition` policy or incorrect label settings in a MAC label policy. Debugging steps are as follows:

1. Check the error messages. If the user is in the `insecure` class, the `partition` policy may be the issue. Try restoring the user class to the `default` class and rebuild the database using `cap_mkdb`.
2. Carefully check the label policy settings for the user, Xorg, and **/dev** entries.
3. If neither resolves the issue, the error messages and environment description can be sent to the [FreeBSD general questions mailing list](https://lists.freebsd.org/subscription/freebsd-questions).

### Error When Switching Users

When a user switches from `root` to another user in the system, an error message `_secure_path: unable to stat .login_conf` may appear. This message typically occurs when the user's label is higher than the target user being switched to. For example, if `joe`'s default label is `biba/low` and `root`'s label is `biba/high`, `root` cannot view `joe`'s home directory because the Biba integrity model does not allow `root` to view objects at a lower integrity level — this occurs regardless of whether `root` uses `su` to switch to `joe`.

### Root User Not Recognized

The system no longer recognizes `root`. In this case, `whoami` returns `0`, and `su` returns `who are you?`.

This situation may be caused by the label policy being disabled via sysctl(8) or the policy module being unloaded. If the policy has been disabled, the login capability database needs to be reconfigured: carefully check **/etc/login.conf** to ensure all `label` options have been removed, then rebuild the database using `cap_mkdb`.

This can also occur when the policy restricts access to **/etc/master.passwd**. This is typically because the administrator changed the file under a label that does not conform to the system's general policy. In this case, the system reads user information, but access is blocked because the file inherited the new label. Recovery should be possible after disabling the policy using sysctl(8).

## Exercises

1. The FreeBSD MAC framework uses a modular design, with the kernel implementing different mandatory access control policies through `mac_*.ko` policy modules. List at least 4 FreeBSD built-in MAC policy modules and briefly describe their application scenarios.
2. What is the fundamental difference between the MAC framework and traditional Discretionary Access Control (DAC)?
3. When enabling a MAC policy module (such as `mac_portacl`) in FreeBSD, it is typically necessary to modify **/boot/loader.conf** and reboot the system. Write a complete configuration example and explain how to verify currently loaded MAC policy modules without rebooting.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-30-security-auditing/di-30.4-jie-qiang-zhi-fang-wen-kong-zhi-kuang-jia-mac-kuang-jia.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
