tomoyotitle.png

Chapter 4: How does TOMOYO Linux work?

4.1. Understanding domains

In TOMOYO Linux, the technique used to enforce MAC makes use of something called "domains". This is an important concept. Every process in a system belongs to a domain, which is determined by its execution history. Broadly speaking, every time a process is executed, a new domain is created. Any particular domain is represented by a concatenation of all previously executed pathanames. This creation of a new domain can also be called a "domain transition". Have a look at this diagram:

domain_transition.png

The kernel is always the first domain and is represented in TOMOYO Linux by <kernel>. In this example, the kernel then executes /sbin/init. Because a process has been executed, a new domain is created which in this case is the domain <kernel> /sbin/init. The bootup scripts are then executed, which result in further domains being created.

The process execution history is important. Consider the following domains:

<kernel> /sbin/init /etc/rc.d/rc
<kernel> /sbin/init /etc/rc.d/rc.sysinit /etc/rc.d/rc

In both cases, the script "/etc/rc.d/rc" is the process causing a new domain to be created. However, because the process execution history is different, they are considered to be two separate domains. This allows you to control what can be executed by any particular domain, and allows policy to be more flexible as you can apply different levels of restriction to a process depending on how it was executed. There is also the possibility to manage domain transition very precisely and for example apply the same restriction to a process without regard to how it was executed. This topic will be discussed later.

4.2. View domains with the policy editor

Let's have a look at the policy editor to get a better understanding of domains. This is the main tool used with TOMOYO Linux and it is important to become comfortable using it. The instructions on this page can be supplemented with this page describing How to use the Policy Editor.

Once the system has been rebooted into the TOMOYO Linux kernel, run the policy editor with the "/etc/tomoyo/" option to edit policy files within the "/etc/tomoyo/" directory:

# /usr/sbin/tomoyo-editpolicy /etc/tomoyo/

The policy editor provides a number of "screens" that each serve a different role. The default screen that greets the user is the "Domain Transition Editor". The picture below describes the domain tree that should be visible after running the above command. As of now, only the "<kernel>" domain is defined:

editpolicy-domain-list1.png

Since this is a newly initialized policy, the policy files in "/etc/tomoyo/" are empty. There are two sets of policy involved in TOMOYO Linux: policy loaded in the kernel, and policy saved to "/etc/tomoyo/". Many sets of policies can be saved to "/etc/tomoyo/" and can be loaded into the kernel at boot or on demand. Saving policy to disk will be discussed in later. Press the "q" key to quit the policy editor.

Now run the policy editor again without the "/etc/tomoyo/" option in order to view the policy that is loaded in the kernel:

# /usr/sbin/tomoyo-editpolicy

As the system runs, TOMOYO Linux will record the creation of new domains and add them to the tree. After running the above command, the domain tree should appear populated with all domains created since startup:

editpolicy-domain-list2.png

The first line shows what screen you are on and how many domains are listed.
The second line is the message area.
The third line shows the domain name currently selected by the cursor.
The fourth line and downwards are the domains currently defined.

Try executing some commands and see where new domains are created. You can do this while you still have the policy editor running.

You can scroll using the arrow keys and/or the Home/End/PageUp/PageDown keys.
Press the "r" key to refresh the contents of the screen.
Press the "f" key to find an entry.
Press the "?" key to view the available commands. Press the "?" again to go back to the previous screen.

Note that a new domain is only created if it is unique, so executing the same command over and over again will not result in the creation of many domains.

4.3. Understanding profiles

Each domain can be restricted using TOMOYO Linux by assigning a "profile". These profiles can be assigned to any domain independently of others, which allows you to slowly build up the security in your system one domain at a time. This also allows you to create custom profiles for specific domains, but this is a more advanced topic for later on.

In the policy editor, look at the numbers in the second column of each line:

editpolicy-domain-profile-number.png

This number is called the "profile number". A profile number is an integer value which takes between 0 and 255. The default profile number is "0", also known as "Disabled Mode", in which the domain is completely unrestricted.

Press the "w" key to list the different "screens" that can be viewed using the policy editor:

editpolicy-window-list.png

Press the "p" key to select the "Profile Editor", and you will see the list of profiles:

editpolicy-profile-list.png

Each profile contains 3 fields:

Name

Control

COMMENT

Description of the profile.

CONFIG

Configuration of operation mode.

PREFERENCE

Configuration of various options.

The "mode" parameter of the CONFIG line can contain one of the following values:

Value

Meaning

disabled

Works as if a regular kernel.

learning

Do not reject an access request if the request violates policy. Append the request to policy.

permissive

Do not reject an access request if the request violates policy. Do not append the request to policy.

enforcing

Reject an access request if the request violates policy. Do not append the request to policy.

The PREFERENCE line holds the following options:

Name

Function

max_audit_log

Sets the maximum number of audit logs that the kernel will hold

max_learning_entry

Sets the maximum number of domain policy entries appended by "Learning Mode"

Thus, there are four default profiles that each play a different role:

default_profiles-en.png

Each of these profiles can be assigned to a domain:

kernel_namespace.png

The "Learning Mode" profile is the feature of TOMOYO Linux that makes developing policy very easy. This mode will automatically generate policy for any domain that has this profile selected. This can then be developed and refined into a solid policy. The other profiles, "Permissive Mode" and "Enforcing Mode", are for later on when a domain is ready to be restricted.

For further information on management of profiles, read Chapter 9: Advanced profile management.

4.4. Understanding domain policy

The restrictions of each domain can be viewed using the "Domain Policy Editor" screen, which can be accessed by selecting a domain in the "Domain Transition Editor" screen, and then pressing the "Enter" key. Since no policy has been developed yet, the screen is empty. This is an example of domain policy for Apache:

(Click to view complete screen.)
editpolicy-httpd-acl1.png

The permissions in domain policy are represented here with directives such as "file read" and "file write". Once the domain is placed in "Enforcing Mode", only the permissions defined in domain policy will be allowed, as well as the permissions defined in exception policy (see 4.5: Understanding exception policy). In order to develop a policy of least privilege that still allows normal usage, the "Learning Mode" and "Permissive Mode" can be used. For in depth details on the directives that can be used in domain policy, see Domain policy syntax located in Appendix B: Policy specification.

4.5. Understanding exception policy

Press the "w" key, then press the "e" key, and you will see the "Exception Policy Editor" screen:

(Click to view complete screen.)
editpolicy-exception-list1.png

You can scroll this window using the arrow keys and/or the Home/End/PageUp/PageDown keys.

The permissions here are similar to those in the domain policy, but apply to all domains. Permissions defined here will not be displayed in domain policy, and access requests from any domain that match a permission in exception policy will be automatically accepted. The exception policy can also be used to shorten and simplify domain policy for each domain by using the group directives.

For in depth details on the directives that can used in exception policy, see Exception policy syntax located in Appendix B: Policy specification.

4.6. Saving audit logs (optional)

When a domain tries to perform an action that has been permitted in domain/exception policy, this action is granted. If the action has not been permitted in policy, then the action is rejected, assuming the domain is in "Enforcing Mode".

When developing policy, it may be useful to save a log entry every time a domain makes a request that is undefined in domain/exception policy. While this is crucial for system administration once policy has been fully developed and enforced, it can also be used alongside "Learning Mode" to help develop policy.

TOMOYO Linux can record "access granted logs" (access requests that were granted by either domain policy or exception policy) and "access rejected logs" (access requests that were not granted by neither domain policy nor exception policy). These logs are in the form of domain policy. This is useful in the case that the user wishes to permit a domain to perform actions that are not currently permitted in policy. The "access rejected log" could then be used to append permissions to domain policy. The "Learning Mode" described in the next chapter mostly automates the process of appending "access rejected logs" into domain policy for domains set to that mode.

The following values can be given for the "grant_log" parameter of the CONFIG line:

Value

Meaning

no

Don't record "access granted logs".

yes

Record "access granted logs".

The following values can be given for the "reject_log" parameter of the CONFIG line:

Value

Meaning

no

Don't record "access rejected logs".

yes

Record "access rejected logs".

tomoyo-auditd is a daemon program that reads from the /sys/kernel/security/tomoyo/audit interface and writes to specified log files. To make use of this daemon, it can for example be run by adding "/usr/sbin/tomoyo-auditd" to "/etc/rc.local".

The configuration of this daemon is done in the "/etc/tomoyo/tools/auditd.conf" file. Text read from the /sys/kernel/security/tomoyo/audit can be sorted and sent to different files. Some useful defaults exist, but an advanced user can make use of extensive sorting rules to make administration easier. The default configuration file looks like this:

# This file contains sorting rules used by tomoyo-auditd command.

# An audit log consists with three lines. You can refer the first line
# using 'header' keyword, the second line using 'domain' keyword, and the
# third line using 'acl' keyword.
#
# Words in each line are separated by a space character. Therefore, you can
# use 'header[index]', 'domain[index]', 'acl[index]' for referring index'th
# word of the line. The index starts from 1, and 0 refers the whole line
# (i.e. 'header[0]' = 'header', 'domain[0]' = 'domain', 'acl[0]' = 'acl').
#
# Three operators are provided for conditional sorting.
# '.contains' is for 'fgrep keyword' match.
# '.equals' is for 'grep ^keyword$' match.
# '.starts' is for 'grep ^keyword' match.
#
# Sorting rules are defined using multi-lined chunks. A chunk is terminated
# by a 'destination' line which specifies the pathname to write the audit
# log. A 'destination' line is processed only when all preceding 'header',
# 'domain' and 'acl' lines in that chunk have matched.
# Evaluation stops at the first processed 'destination' line.
# Therefore, no audit logs are written more than once.
#
# More specific matches should be placed before less specific matches.
# For example:
#
# header.contains profile=3
# domain.contains /usr/sbin/httpd
# destination     /var/log/tomoyo/reject_003_httpd.log
#
# This chunk should be placed before the chunk that matches logs with
# profile=3. If placed after, the audit logs for /usr/sbin/httpd will be
# sent to /var/log/tomoyo/reject_003.log .

# Please use TOMOYO Linux's escape rule (e.g. '\040' rather than '\ ' for
# representing a ' ' in a word).

# Discard all granted logs.
header.contains granted=yes
destination     /dev/null

# Save rejected logs with profile=0 to /var/log/tomoyo/reject_000.log
header.contains profile=0
destination     /var/log/tomoyo/reject_000.log

# Save rejected logs with profile=1 to /var/log/tomoyo/reject_001.log
header.contains profile=1
destination     /var/log/tomoyo/reject_001.log

# Save rejected logs with profile=2 to /var/log/tomoyo/reject_002.log
header.contains profile=2
destination     /var/log/tomoyo/reject_002.log

# Save rejected logs with profile=3 to /var/log/tomoyo/reject_003.log
header.contains profile=3
destination     /var/log/tomoyo/reject_003.log

It is important to be careful with disk space if "access granted logs" are saved, as this file can grow extremely quickly. Do not do this unless you know what you are doing.

To manage logs with logrotate, create "/etc/logrotate.d/tomoyo" with the following content (give "nocreate" option or logs after the first rotation will not be saved):

/var/log/tomoyo/*.log {
  weekly
  rotate 9
  missingok
  notifempty
  nocreate
}

If audit logs are not required, tomoyo-auditd need not be run. In this case, give PREFERENCE={ max_audit_log=0 } for profiles to save memory and improve performance. While the use of audit logs can be delayed until a domain has been switched to "Enforcing Mode", it is recommended to store "access rejected logs" at this point for the development of fine-grained policy.

Distributers may wish to create daemon or service to be included with the package. It is very simple to do so, as such a daemon would only need to run a single command: /usr/sbin/tomoyo-auditd. If you are using systemd, create "/lib/systemd/system/tomoyo-auditd.service" with the following contents:

[Unit]
Description=TOMOYO Linux Auditing Daemon

[Service]
Type=forking
ExecStart=/usr/sbin/tomoyo-auditd
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target