-
Work with a proper daemon under Red Hat Enterprise Linux. This
means it has an initscript in /etc/init.d/ and can be managed using chkconfig. For example, this procedure assumes you
are going to use the service command to
control starting and stopping the daemon.
For this procedure, you are writing policy for the fictional
foo package and it's associated
foo daemon. Use a real daemon name in this
place when developing your own policy.
-
Create a file at $SELINUX_SRC/domains/program/foo.te.
-
Put the daemon domain macro call in the file:
-
Create the file contexts file, $SELINUX_SRC/file_contexts/program/foo.fc.
-
Put the first list of file contexts in file.fc. You may need to add to this later,
depending on the needs of the foo
daemon.
/usr/bin/foo -- system_u:object_r:foo_exec_t
/var/run/foo.pid -- system_u:object_r:foo_var_run_t
/etc/foo.conf -- system_u:object_r:foo_conf_t
|
-
Load the new policy with make load.
-
Label the foo files:
restorecon /usr/bin/foo /var/run/foo.pid /etc/foo.conf
|
-
Start the daemon, service foo
start.
-
Examine your audit log for denial messages:
grep "avc: denied" /var/log/messages > /tmp/avc_denials
cat /tmp/avc_denials
|
Familiarize yourself with the errors the daemon is generating.
You are writing policy with the help of audit2allow, but you need to understand the nature
of the denials. You can also use seaudit
for viewing the log messages, as explained in Section 6.2 Using seaudit for Audit Log Analysis.
-
Use audit2allow to start the first
round of policy rules.
audit2allow -l -i /var/log/messages -o \
/etc/selinux/targeted/src/policy/domains/program/foo.te
|
When looking at the generated rules, if you see a rule that
gives the foo_t domain
read access to a file or
directory, change the permission to read { read gettatr }. The domain is likely to
need that permission if it already wants to read a file.
-
Look to see if the foo_t
domain tries to create a network socket, that is, udp_socket or tcp_socket as the object class in the AVC
denial:
avc: denied { create } for pid=7279 exe=/usr/bin/foo \
scontext=root:system_r:foo_t tcontext=root:system_r:foo_t\
tclass=udp_socket
|
If this is the case, then add the can_network() macro to foo.te:
-
Continue to iterate through the basic steps to generate all the
rules you need. Each set of rules added to the policy may reveal
additional permission needs from the foo_t domain.
-
Start the daemon.
-
Read the AVC messages.
-
Write policy from the AVC messages, using audit2allow and your own knowledge, looking for
chances to use macros.
-
Load new policy.
-
Go back to beginning, starting the daemon ...
-
If the domain tries to access port_t, which relates to tclass=tcp_socket or tclass=udp_socket in the AVC log message,
you need to determine what port number foo
needs to use. To diagnose, put these rules in foo.te:
allow foo_t port_t:tcp_socket name_bind;
auditallow foo_t port_t:tcp_socket name_bind;
|
The auditallow rule helps
you determine the nature of the port connection attempt.
-
Iterate through the remaining AVC denials. When they are
resolved with new policy, you can configure the unique port
requirements for the foo_t domain.
-
With the daemon started, determine which port foo is using. Look at the AVC allowed message and
see what port the daemon is connected to:
lsof | grep foo.*TCP
foo 2283 root 3u IPv6 3192 TCP *:4242 (LISTEN)
|
The foo daemon is listening on port
4242.
-
Remove the generic port_t
rule, replacing it with a specific rule for a new port type based
on the foo_t domain.
type foo_port_t, port_type;
allow foo_t foo_port_t:tcp_socket name_bind;
|
Add this line to $SELINUX_SRC/file_contexts. This reserves the port
4242 for the domain foo_t:
ifdef(`foo.te', `portcon tcp 4242 system_u:object_r:foo_port_t')
|