The railroad diagram in Figure 6-9 represents an overview of the syntax of an SELinux policy.
As the figure shows, an SELinux policy consists of 11 elements, several of which are optional:
te_rbac
Defines type enforcement and role-based access control configuration.
users
constraints
Defines constraints that the security policy must observe (optional).
initial_sid_contexts
Defines the security contexts of important security objects.
fs_use
genfs_contexts
Defines security contexts for filesystems lacking persistent labels (optional).
net_contexts
The policy elements must appear in the order indicated by the
railroad diagram. However, you generally don’t have
to concern yourself with the order of policy statements, because each
type of statement resides in a designated file or directory. As
explained in Chapter 4, the SELinux policy
Makefile assembles these files into a single
file before compiling the policy source statements. The
Makefile ensures that policy statements are
presented to the policy compiler in the proper order. Table 6-1 shows the correspondence between the
policy elements and files in the
src/policy
SELinux source tree.
Table 6-1. Policy elements and associated files
Table 6-1 shows files and directories used in the Fedora Core 2 SELinux implementation. The files may have different contents or locations under other implementations of SELinux.
One of the most important policy elements,
te_rbac
, contains type enforcement and role-based
access control declarations. Along with the file context
configuration, the TE and RBAC configuration is the part of an
SELinux policy that is most often modified. Syntactically, the
te_rbac
element consists of a series
that freely intermingles two
subelements—te_decl
and
rbac_decl
—as shown
in Figure 6-10.
Before presenting the syntax of the SELinux user
and role-based access control declarations, let’s
look at a few subelements that appear in a variety of SELinux policy
elements and at a few principles that govern their use. Figure 6-11 shows the syntax of a subelement known as
identifier_list
.
As its name suggests, the subelement represents a list of
identifiers. An example of such a list appears in the following
declaration from the
ping.te
file:
allow ping_t self:rawip_socket { create ioctl read write bind getopt setopt };
The curly braces enclose an identifier list specifying the
permissions related to a raw IP socket: create
,
ioctl
, read
,
write
, bind
,
getopt
, and setopt
.
Notice that the identifiers are separated from one another by white
space. Another subelement,
id_comma_list
,
specifies a comma-separated list of identifiers. A railroad diagram
for this subelement appears as Figure 6-12.
Another statement of the ping.te
file provides
an example of this subelement:
type ping_exec_t, file_type, sysadmfile, exec_type;
In this statement, the identifiers ping_exec_t
,
file_type
, sysadmfile
, and
exec_type
appear as an
id_comma_list
.
Let’s now consider some fine points of railroad diagrams. Literals do not need railroad diagrams to explain them, because they are labeled with the values they match. Though literals sometimes appear in railroad diagrams in uppercase form, the strings they represent can appear in the SELinux policy in either uppercase or lowercase. So, with reference to Figure 6-11, you can anticipate that most identifiers will appear in lowercase rather than uppercase. That is, you should expect the following:
create, ioctl, read, write, bind, getopt, setopt
rather than:
CREATE, IOCTL, READ, WRITE, BIND, GETOPT, SETOPT
However, it’s entirely permissible to specify
uppercase identifiers. It’s just that SELinux policy
developers generally prefer not to do so. What matters is
consistency. The identifiers create
and
CREATE
are both legal but also entirely distinct,
because one uses lowercase letters whereas the other uses uppercase
letters.
Let’s consider one more common policy subelement,
known as names
, which appears in Figure 6-13. This element can represent such strings as:
A single identifier
A list of identifiers separated from one another by white space, enclosed within curly braces
An asterisk (*)
An identifier preceded by a tilde (~)
A list of identifiers separated from one another by white space and enclosed within curly braces, and preceded by a tilde (~)
Two identifiers separated by a hyphen (-)
Some rather bizarre extensions are also permissible. For instance,
the following is a valid
nested_id_set
subelement:
{ x -y { a b c } }
You may be curious about the meaning or use of this subelement. But,
for the moment, please focus merely on the syntax, not the meaning.
The meaning of the subelement emerges from the context in which it is
used. So rather than continue to examine subelements—a process
that could be continued indefinitely—let’s
start looking at concrete examples by considering the
users
element, which is used to describe user
declarations.