|
NOTE: CentOS Enterprise Linux is built from the Red Hat Enterprise Linux source code. Other than logo and name changes CentOS Enterprise Linux is compatible with the equivalent Red Hat version. This document applies equally to both Red Hat and CentOS Enterprise Linux.
Macros are used throughout programming, as they provide reusable
pieces of code that you can call one time and have explode into
many meaningful lines. SELinux uses the m4
macro language for writing reusable policy rules. This makes policy
writing and management easier. In using macros, policy writers gain
flexibility, modularity, shared quality control, and central
management for complex pieces of policy.
Macros do not exist in the policy.conf
file, as that file represents the exploded macro policy code. It is
possible to work backward in finding where a particular policy.conf entry exists. If a daemon has a rule
that you cannot find in the associated TE file at $SELINUX_SRC/domains/program/<foo>.te, then it is likely to be
found in the macros. This section first explains the syntax and
usage of a macro, then discusses the analysis method in more
detail.
You can find more resources about m4
from the manual page man m4, installed
documentation at /usr/share/doc/m4-<version>, and through the resources
listed in Chapter 9
References. Some of the specific macros used in the
targeted policy are explained in Section 3.4 Common Macros in the
Targeted Policy.
This usage example shows the first few lines from the Apache
HTTP macro file, $SELINUX_SRC/macros/program/apache_macros.te:
The define(`apache_domain',`
is the beginning of the macro definition. Inside the definition,
the $1 represents the parameter
passed to the macro. Look in $SELINUX_SRC/domains/program/apache.te, which has
the following invocation:
This single line then generates a large set of types and rules,
substituting the passed parameter sys for every $1:
type httpd_$1_htaccess_t, file_type, sysadmfile; -> \
type httpd_sys_htaccess_t, file_type, sysadmfile;
type httpd_$1_script_exec_t, file_type, sysadmfile -> \
type httpd_sys_script_exec_t, file_type, sysadmfile
role system_r types httpd_$1_script_t; -> \
role system_r types httpd_sys_script_t;
...
|
To find how a rule is derived from a macro, follow this
approach. Take a rule you are curious about:
The allow rule says, httpd_t
is permitted to start a child process that transitions to
httpd_suexec_t. The
type_transition rule defines
two things: the circumstances, that is, when the domain
httpd_t is executing a file of
the type httpd_suexec_exec_t
(/usr/sbin/suexec); and the child domain
transitioned to, httpd_suexec_t. The allow rule then permits the defined
transition.
These rules are present only in $SELINUX_SRC/policy.conf, so they must be derived
from a macro.
In those rules, the variable elements are the parent domain
(httpd_t), the child domain
(httpd_suexec_t), and the
program type (httpd_suexec_exec_t). These are represented
in the macro as $1,
$2, and so forth. Fortunately,
the search is made easier because the object class (process) and permission (transition) are never variables in an
SELinux macro. It is safe to search using the class and permission
as a query:
grep -R ":process transition" macros/*
macros/core_macros.te:allow $1 $3:process transition; # match
macros/global_macros.te:allow $1 self:process transition;
|
The return from core_macros.te fits
the right format. Here it is in the macro file, showing it to be
part of the domain_trans()
macro:
# domain_trans(parent_domain, program_type, child_domain)
#
# Permissions for transitioning to a new domain.
#
define(`domain_trans',`
#
# Allow the process to transition to the new domain.
#
allow $1 $3:process transition;
|
In the macro call, the variables are domain_trans($1, $2, $3), with $1 the parent domain, $2 the program type, and $3 the child domain.
However, a search through $SELINUX_SRC/domains/program/apache.te and
$SELINUX_SRC/macros/programs/apache_macros.te does
not find a line such as domain_trans(httpd_t, httpd_suexec_t,
httpd_suexec_exec_t). This means that domain_trans() is not called directly by
the Apache HTTP policy, so another macro must be involved.
Looking back at the rules you are curious about, the common name
roots that make up those rules are httpd_t and httpd_suexec. Focusing your search on those
as variables turns up a macro call:
grep httpd_suexec domains/program/apache.te | grep httpd_t
daemon_sub_domain(httpd_t, httpd_suexec)
|
The parameter httpd_suexec
does not have either of the suffixes, _t or _exec_t, because it obtains those from the
macro. The macro daemon_sub_domain() is found in $SELINUX_SRC/macros/global_macros.te. Notice the
_exec_t and _t that are attached to the variable inputs
$1 and $2:
# define a sub-domain, $1_t is the parent domain, $2 is the name
# of the sub-domain.
#
define(`daemon_sub_domain', `
...
domain_auto_trans($1, $2_exec_t, $2_t)
|
Recall that the variables fed into daemon_sub_domain() were httpd_t ($1) and httpd_suexec ($2). When m4 runs,
it inputs the parameters in the order received, so $1 becomes httpd_t, $2_exec_t becomes httpd_suexec_exec_t, and $2_t is httpd_suexec_t. Notice that the macro
daemon_sub_domain actually
calls domain_auto_trans(),
which is found in core_macros.te and
looks like this:
define(`domain_auto_trans',`
domain_trans($1,$2,$3)
type_transition $1 $2:process $3;
')
...
define(`domain_trans',`
allow $1 $3:process transition;
...
|
There you see the completion of the chain, as domain_trans() is called, and the
parameters are fed in to create the rules you are looking for:
$1 = httpd_t (base input of httpd_t)
$2 = httpd_suexec_exec_t (base input of httpd_suexec)
$3 = httpd_suexec_t (base input of httpd_suexec)
apache.te # feeds 2 variables into
daemon_sub_domain(httpd_t, httpd_suexec)# which calls
domain_auto_trans($1, $2_exec_t, $2_t) # that associates new vars
#### $1 = $1, $2_exec_t = $2, $2_t = $3) # and feeds the vars into
domain_trans($1,$2,$3) # which has
type_transition $1 $2:process $3; # that expands into
type_transition httpd_t httpd_suexec_exec_t:process httpd_suexec_t
# and
# expands domain_trans()
allow $1 $3:process transition; # which expands into
allow httpd_t httpd_suexec_t:process transition;
# Here is a final association of variables to sources
allow $1 $3 :process transition;
allow httpd_t httpd_suexec_t:process transition;
type_transition $1 $2 :process $3;
type_transition httpd_t httpd_suexec_exec_t:process httpd_suexec_t;
|
|
|