Chapter 15: How do I manage policy namespace?
15.1. About policy namespace
The documentation so far has only shown domains that begin with "<kernel>". A new feature introduced in TOMOYO 1.8.2 introduces the concept of namespaces. Domains that start with "<kernel>" belong to the "<kernel>" namespace, but different namespaces can now be used with domains that start with "<$namespace>", where $namespace can be any arbitrary name.
Each policy namespace has its own set of domain policy, exception policy and profiles, which are all independent of other namespaces. This independency allows you (and those who want to develop and distribute policy for specific applications) to develop policy files without worrying interference among namespaces, except that directives for jumping to different namespaces need to be added to other namespaces.
15.2. How to specify namespaces?
The notation "<$namespace>" will be used hereafter, in which $namespace can be a any word (e.g. "/usr/sbin/sshd", "/usr/bin/httpd", "Apache") in TOMOYO's string representation rule. The "<kernel>" namespace is the built-in namespace. As long as you use only "<kernel>" namespace, policy files remain compatible with TOMOYO 1.8.1.
A domain name starts with "<$namespace>". For example, "<kernel>" domain and "<kernel> /sbin/init" domain belong to "<kernel>" namespace whereas "</usr/sbin/sshd>" domain and "</usr/sbin/sshd> /bin/bash" domain belong to "</usr/sbin/sshd>" namespace.


Although each namespace has its own set of domain policy, exception policy and profiles, the policy for all namespaces are still contained within the same files within /proc/ccs/ and /etc/ccs/policy/ for simplicity and compatibility reasons. In other words, the policy for each namespace is not split into separate files.
To specify namespace in /proc/ccs/exception_policy and /proc/ccs/profile , add "<$namespace>" prefix to each line. An example of /proc/ccs/profile containing "<kernel>" and "</usr/sbin/httpd>" namespace looks like below:
<kernel> PROFILE_VERSION=20100903 <kernel> 0-COMMENT=-----Disabled Mode----- <kernel> 0-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } <kernel> 0-CONFIG={ mode=disabled grant_log=no reject_log=yes } <kernel> 1-COMMENT=-----Learning Mode----- <kernel> 1-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } <kernel> 1-CONFIG={ mode=learning grant_log=no reject_log=yes } <kernel> 2-COMMENT=-----Permissive Mode----- <kernel> 2-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } <kernel> 2-CONFIG={ mode=permissive grant_log=no reject_log=yes } <kernel> 3-COMMENT=-----Enforcing Mode----- <kernel> 3-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } <kernel> 3-CONFIG={ mode=enforcing grant_log=no reject_log=yes } </usr/sbin/httpd> PROFILE_VERSION=20100903 </usr/sbin/httpd> 0-COMMENT=-----Disabled Mode----- </usr/sbin/httpd> 0-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } </usr/sbin/httpd> 0-CONFIG={ mode=disabled grant_log=no reject_log=yes } </usr/sbin/httpd> 1-COMMENT=-----Learning Mode----- </usr/sbin/httpd> 1-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } </usr/sbin/httpd> 1-CONFIG={ mode=learning grant_log=no reject_log=yes } </usr/sbin/httpd> 2-COMMENT=-----Permissive Mode----- </usr/sbin/httpd> 2-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } </usr/sbin/httpd> 2-CONFIG={ mode=permissive grant_log=no reject_log=yes } </usr/sbin/httpd> 3-COMMENT=-----Enforcing Mode----- </usr/sbin/httpd> 3-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 enforcing_penalty=0 } </usr/sbin/httpd> 3-CONFIG={ mode=enforcing grant_log=no reject_log=yes }
For compatibility, "<kernel>" prefix can be omitted when specifying "<kernel>" namespace.
To specify namespace in /proc/ccs/domain_policy , no special care needs to be taken. This is because domain policy consists with blocks where a block starts with a domainname declaration line and the domain name contains namespace which the domain belongs to. An example of /proc/ccs/domain_policy containing "<kernel>" and "</usr/sbin/httpd>" namespace looks like this:
<kernel> use_profile 0 use_group 0 <kernel> /sbin/init use_profile 0 use_group 0 </usr/sbin/httpd> use_profile 1 use_group 0 </usr/sbin/httpd> /var/www/cgi-bin/counter.cgi use_profile 1 use_group 0
15.3. How to specify domain transition across namespaces?
As explained above, directives for jumping to different namespaces needs to be added to other namespaces. Two more directives are added.
The "reset_domain" directive causes programs to run in the namespace specified by this program. The syntax is same with initialize_domain directive. Below example causes all executions of /usr/sbin/sshd to be transit to "</usr/sbin/sshd>" domain:
reset_domain /usr/sbin/sshd from any
The "no_reset_domain" directive cancels the effect of "reset_domain" directive. The syntax is same with no_initialize_domain directive.
Also, "auto_domain_transition=" part in the conditional ACL allows transition to arbitrary namespaces upon permitted by policy (but use with caution because there is no guarantee that the access request that was permitted by policy never fails after the domain transition).
file pivot_root /usr/lxc/lxc1/ /usr/lxc/lxc1/oldroot/ auto_domain_transition="<lxc1>" file pivot_root /usr/lxc/lxc2/ /usr/lxc/lxc2/oldroot/ auto_domain_transition="<lxc2>"
While "reset_domain" directive allows only transition to the domain where the name of the namespace is equals to the name of the program, "auto_domain_transition=" part in the conditional ACL allows transition to the domain where the name of the namespace is an arbitrary word. In other words, the former can transit to domains like "</usr/sbin/httpd>" whereas the latter can transit to domains like "</usr/sbin/httpd>" and "<Apache>".
Regarding "task auto_domain_transition" directive and "task manual_domain_transition" directive, there is no change because these directives receive a domainname which already contains the name of the namespace. Thus, you can specify like below:
task manual_domain_transition <Apache> /www.tomoyo00.com task manual_domain_transition <Apache> /www.tomoyo01.com task manual_domain_transition <Apache> /www.tomoyo02.com task manual_domain_transition <Apache> /www.tomoyo03.com
While "reset_domain" directive and "auto_domain_transition=" part in the conditional ACL allow only transition to the domain where the name of the domain is equal to the name of the domain's namespace, "task auto_domain_transition" directive and "task manual_domain_transition" directive allow transition to arbitrary domains. In other words, the former can transit to domains like "</usr/sbin/httpd>" whereas the latter can transit to domains like "</usr/sbin/httpd>" and "</usr/sbin/httpd> /var/www/cgi-bin/counter.cgi".
15.4. How to use namespace from policy editor?
ccs-editpolicy
supports new command line option <$namespace> which sets the initial namespace to edit to <$namespace> namespace. The default namespace is "<kernel>". Be careful not to typo the namespace. Entries will not be shown as you expect if you typo, for ccs-editpolicy
filters entries based on the namespace currently editing.
Regarding <<< Exception Policy Editor >>> screen and <<< Profile Editor >>> screen, the name of namespace currently editing is shown on the third line of the screen as with the name of domainname currently selected is shown on the third line of the <<< Domain Transition Editor >>> screen. You can jump to <<< Namespace Selector >>> screen by pressing "n" key after pressing "w" key in order to select namespace to edit.
Although it is possible to create a new namespace and create profiles for the new namespace and add entries using ccs-editpolicy
, it is recommended to use ccs-loadpolicy
for your convenience. For example, to clone profile for "<kernel>" namespace in order to use for "</usr/sbin/httpd>" namespace, you can use an awk
script like below:
# awk ' { print "</usr/sbin/httpd> " $0 } ' /etc/ccs/profile.conf | ccs-loadpolicy -p
If /etc/ccs/profile.conf already contains the "<kernel>" prefix, the script will look like below:
# grep '^<kernel> ' /etc/ccs/profile.conf | awk ' { $1 = "</usr/sbin/httpd> "; print $0 } ' | ccs-loadpolicy -p
Note that the purpose of namespace is to allow having independent set of domain policy, exception policy and profile. You don't have to clone from existing files.
15.5. Pitfalls when using namespaces
Namespace is convenient, but there are a few pitfalls that you need to take care.
- Program execution request that causes domain transition by "reset_domain" directive will be denied (with error messages like below printed on the console) regardless of profile configurations if either "the domain to transit to is not defined" or "the profile for the domain to transit to is not defined" is true. This is because "reset_domain" directive is considered as a clear sign for applying different set of policy files and therefore should not automatically inherit configuration from current namespace. You have to explicitly load domain policy, exception policy and profile for the namespace by the moment a process attempts to transit to that namespace.
ERROR: Domain '</usr/sbin/httpd>' not ready.
- Although you can develop policy for specific applications independently, the process will not transit to different namespaces unless explictly specified. When using namespaces, exception policy without "reset_domain" directive will not be useful unless one of "auto_domain_transition=" part in the conditional ACL, "task auto_domain_transition" directive or "task manual_domain_transition" directive is specified.
- Memory allocated for creating namespaces cannot be released just like memory allocated for creating profiles cannot be released. This should not matter for normal usage, for the memory quota can be controlled via /proc/ccs/stat interface.