Policy development can be a tricky process. It is generally best to perform policy development in permissive mode, if running in enforcement mode it is possible to render your system inoperable by making a policy development error.
All policy customization done for a specific machine should be added to the $SELINUX_SRC/domains/misc/local.te file to ensure that future policy updates do not alter or remove the changes. Changes to file contexts are similarly added to $SELINUX_SRC/file_contexts/misc/local.fc. If these files do not exist they should be created.
Policy for daemons are in individual .te files located in $SELINUX_SRC/domains/program/. Policy for daemons that are not installed on a given system can be moved out of this directory and into $SELINUX_SRC/domains/program/unused/, where they will not be added into the policy during compilation. This can save resources, but could cause problems if the daemon is ever installed without its corresponding policy file being re-compiled into the active policy.
The mysqld.te policy is a good example of SELinux daemon policy. A listing of this policy is provided in Appendix B and should be referred to during this section.
An understanding of m4 macros is extremely helpful in reading and understanding SELinux policy. A link to m4 documentation can be found in Appendix A. SELinux makes extensice use of macros in policy development, the core_macros.te and global_macros.te files located in $SELINUX_SRC/macros/ contain many of these macros. Familiarity with these macros is a key to successful policy development.
Because SELinux is still undergoing such rapid development, there currently exists no documentation of the complete list of macros other than the policy sources themselves. Reading policy sources and familiarizing yourself with the commonly used macros is a key to successful policy development.
The mysqld policy begins with a macro call to the daemon_domain macro. This macro sets up types and access common to most service daemons and is found in the global_macros.te file. Other macros included in the MySQL policy are etcdir_domain, log_domain, and tmp_domain which create subdomains of the mysqld_t domain for configuration files, logfiles, and temporary files respectively.
Also called by the MySQL policy is the can_network_server macro, which allows the domain to open a network port and service requests on it, and the can_ypbind macro, which allows the use of an NIS server for user authentication.
Several types are defined by the macros in the previous section, such as mysqld_exec_t, created by the daemon_domain macro and used as the type for the MySQL executable files. Also created by macros are mysqld_etc_t, mysqld_log_t, and mysqld_tmp_t, used for configuration files, logfiles and temporary files respectively.
Other types are explicitly defined in the mysqld.te policy file. For example, the line
type mysqld_db_t, file_type, sysadmfile
defines the mysqld_db_t file type used for the MySQL database files themselves and flags them with the sysadmfile attribute to allow the system administrator to manage them. The create_dir_file macro is then called with the appropriate parameters to allow the mysqld_t domain to create and use the mysqld_db_t files.
Ifdefs are used to control conditional compilation of policy based on whether other components are present in the policy. For example, the mysqld.te policy contains an ifdef so that if logrotate.te is present on the system, the logrotate_t domain is given access to certain mysqld_t subdomains.
The bulk of any policy file is composed of allow statements. An example is the line:
allow mysqld_t etc_t:dir search;
This allows the mysqld_t domain to perform a search operation on directories labeled with the etc_t type. Since policy is developed based on the logged denials when running the system in permissive mode, this indicates that mysql searches the /etc directory for its own files and therefore we have this rule in the policy to allow that to happen.
A policy boolean is defined at the end of the mysqld.te file. This demonstrates how to set certain rules to be conditional based on the runtime state of the boolean. In this example, the policy will allow processes running in a user domain to connect to MySQL, if and only if the allow_user_mysql_connect boolean is set to true. The line:
bool allow_user_mysql_connect false
defines the boolean and sets it to a default of false.