RedHat/CentOS: a quick introduction to SeLinux policy (a short howto) 

UNIX access control mechanism is build around file permissions. The
access permissions define which subject can iteract with the file and
how. Due to the simple design this concept provides only the very basic

# ls -l
total 84
-rw------- 1 root root 1085 Mar 6 23:42 anaconda-ks.cfg
-rw-r--r-- 1 root root 17150 Mar 6 23:42 install.log
-rw-r--r-- 1 root root 2566 Mar 6 23:42 install.log.syslog

The main purpose of SeLinux is to avoid users or services to go beyond
their pre-defined scope of actions. SeLinux defines another level of
access control mechanism and implements a new layer of independent
system policy.

SeLinux extension allows you to restrict access actions at MUCH HIGHER
GRANULARITY than the common UNIX permissons - it goes far beyond the
simple UNIX file access control.

System defaults, the policy basics

The POLICY definition is a set of rules which specify how "secure" the
system will be, better - which actions will be allowed in the system as
the policy rule defines only what is allowed. All the actions not
allowed within the policy rules are disabled. It is the same concept as
with building firewall - all traffic is disabled and only specific data
flows are allowed.

There are some RedHat pre-defined (bundled) policies and they can be in
various "states". To determine the current SeLinux setup:

# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 21
Policy from config file: targeted

I would use the configuration file to explain what the options "enabled
enforcing targeted" mean. Main SeLinux configuration file is
/etc/selinux/config. In this file we define which policy will be loaded
on system boot.

If you set this file wrong, make a typo, the system will not boot and
panic. If it happens you can edit the Grub commandline and add the
"selinux=0" statement. All the options in the config are ignored then.
Here is the config file itself:

# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.

The SELINUXTYPE is an actual set of allow rules - simply, it is the name
of compiled policy which inherits allow rules. After the system boots
you can't change the SELINUXTYPE, but you are only allowed to modify how
the kernel will follow the policy instructions.

If the kernel is in enforcing mode, then the loaded policy is in use
without exceptions. If the SeLinux is in permissive mode, the kernel
will allow all the actions and will print warning AVC messages only
(good for debugging) instead of dropping the action. You can choose
which SELINUXTYPE policy you will load at system boot. To check policies
you have available on your system type:

# rpm -qa | grep selinux-policy

Or you can check the policies (compiled rule files) by simple listing
content of /etc/selinux directory.

# ls -la
total 56
drwxr-xr-x 4 root root 4096 Mar 27 03:00 .
drwxr-xr-x 77 root root 4096 Mar 27 02:59 ..
-rw-r--r-- 1 root root 512 Mar 27 02:58 config
-rw------- 1 root root 195 May 24 2008 restorecond.conf
-rw-r--r-- 1 root root 1752 Mar 14 2007 semanage.conf
drwxr-xr-x 5 root root 4096 Mar 27 02:58 targeted

As you can see I have only the targeted policy rules installed by now.
The targeted policy is focused on specific system components/services
and all the other content is allowed to run by default - as is labeled
with unconfirmed type. It means that if you do use this policy then the
majority of the software will run and you will still keep the SeLinux
protection for well-known services shipped with distro as samba, http,
postfix, ftp... If you plan to use services which are not bundled by
RedHat then you have to use targeted policy rules or write your own
modules for them.

I will install the strict policy as well. As the strict policy is really
hard-restrictive it is more alike the original NSA SeLinux concept. You
can have problems if your non-selinux-labeled application decides try to
bind some of the tcp sockets for example because unlabeled context is
considered unknow, dangerous and therefore can't interact with the
system. There is now allow rule for unlabeled content. Usually, the
system with strict policy is not able to boot at all (until RedHat 5).
As you need to allow your application to work on the system you have to
prepare special security module for the application.

# yum list | grep selinux-policy | grep -v devel
selinux-policy.noarch 2.4.6-137.el5
selinux-policy-targeted.noarch 2.4.6-137.el5
selinux-policy-mls.noarch 2.4.6-137.1.el5 updates
selinux-policy-strict.noarch 2.4.6-137.1.el5 updates

# yum install selinux-policy-strict

Some basic tweaking on predefined policy

RedHat shipped policies includes so called "booleans" or let's say
"constraints" defined. Using those booleans you can partially change the
SeLinux behavior without creating a whole new policy or policy module.
To list all the booleans related to the apache:

# getsebool -a | grep httpd
allow_httpd_anon_write --> off
allow_httpd_bugzilla_script_anon_write --> off
allow_httpd_mod_auth_pam --> off
allow_httpd_nagios_script_anon_write --> off
allow_httpd_squid_script_anon_write --> off
allow_httpd_sys_script_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_network_connect --> off
httpd_can_network_connect_db --> off
httpd_can_network_relay --> off
httpd_disable_trans --> off
httpd_enable_cgi --> off
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> on
httpd_rotatelogs_disable_trans --> off
httpd_ssi_exec --> off
httpd_suexec_disable_trans --> off
httpd_tty_comm --> on
httpd_unified --> on

The apache config could be configured to allow executing cgi for
example, but the current SeLinux policy is set the way it disallow such
interaction of the Apache daemon. To enable the interaction between the
daemon and the cgis I have to set the trigger:

# setsebool -P httpd_enable_cgi on

Some of the booleans mentioned above can control "SeLinux command
behavior" itself. By default it is possible for root to change how the
system will INTERPRET policy - you can switch from enforcing to
permissive mode forth and back as you wish on the fly using setenforce

# setenforce 0

Even in restricted or targetted policy the root is still the master over
the Linux system, the SeLinux idea is not to limit the root but to allow
the service security will be tuned specifically. Of course, you can
write your own policy which will deny the root to write to /etc
directory if you like.

But even in shipped policy you can limit root user actions a bit. For
example - you can disable the setenforce command.

# getsebool -a | grep secure_mode_policyload
secure_mode_policyload --> off

# setsebool -P secure_mode_policyload on

# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 21
Policy from config file: targeted

# setenforce 0
setenforce: setenforce() failed

What the policy module is

The policy module is a set of compiled rules which expands the main
policy configuration. The modular policy is used on the RedHat5.0(?) and
later. Each module is specific to application as you can see:

# semodule -l
amavis 1.1.0
ccs 1.0.0
clamav 1.1.0
dcc 1.1.0
evolution 1.1.0
iscsid 1.0.0
mozilla 1.1.0
mplayer 1.1.0
nagios 1.1.0
oddjob 1.0.1
pcscd 1.0.0
pyzor 1.1.0
razor 1.1.0
ricci 1.0.0
smartmon 1.1.0

Modules are permanently allowed or denied to load while system boot
using semodule -r (remove) and semodule -i (install) command. The
modular policy of RedHat5.2/CentOS5.2 and above also allows you to load
the necessary policy definitions module on the fly. It is good to know
that such behaviour could be enabled or disabled via boolean named
secure_mode_insmod (in || off).

Into the deep, the filesystem

And now some technical talk. Where to start to look for SeLinux. Lets
begin with the filesystem extended attribute information. We can call it
the LABEL and sits on the filesystem if the FS supports it (ext3 does).
The SeLinux labels are saved as metadata. Let's check them out.

# getfattr -n security.selinux /root/anaconda-ks.cfg
getfattr: Removing leading '/' from absolute path names
# file: root/anaconda-ks.cfg

Get the attributes with 'ls -Z':

# ls -Z
-rw------- root root system_u:object_r:user_home_t anaconda-ks.cfg
-rw-r--r-- root root root:object_r:user_home_t install.log
-rw-r--r-- root root root:object_r:user_home_t

You can see the selinux content on the processes as well with 'ps -efZ'.
The magic is the 'Z' option. On the example we can see
"root:object_r:user_home_t". This gibrish is called access control
vector . The vector is the most and only important data for the access
control mechanism.

The architecture

- The SeLinux consists of SeLinux supporting filesystem, the Access
Vector Cache and the Security Server.

- Each filesystem object has it's own vector.

- If some operation should be performed the SeLinux search the allow
rules if the vector of object is allowed to interact with the subject's
vector .

- If SeLinux finds at least one allow rule then the operation is

- The SeLinux is the last resort access control mechanism in the system.

The system has a AVC (the vector cache) to speed up searches. If there
is no record about the result within the cache then the Security Server
is queried.

A set of filters could be placed between the SS and AVC
(security_compute_av()). The filters (constraints) then could drop some
allow messages. It could be useful when changing system behaviour
without the policy compilation and loading.

The SeLinux rules could be more complicated. Instead of simple allow
rule to certain interactions between object and subject they can define
the interacting (originator) object can change it's own "vector
definition" into another "vector". This type of behaviour is called

SeLinux context

# ls -lZ /etc/selinux/semanage.conf
-rw-r--r-- root root system_u:object_r:selinux_config_t

system_u -> user, it could not be identical with /etc/passwd user
object_r -> role, like the group, but SeLinux type
selinux_config_t -> type, the domain, most important

Extended attributes as clasification and sensitivity could be specified,
but we don't need them yet.

Selinux users

Selinux uses it's own users but you don't need to map the passwd user to
SeLinux user if the username is the same.

Creating your own policy

1) compile the module

$ checkmodule -M -m -o local.mod local.te

2) create the package

$ semodule_package -o local.pp -m local.mod

3) load the module into the kernel

$ semodule -i local.pp

The following example was created using audit2allow which generates
policy allow rules from logs of denied operations.

cat /var/log/audit/audit.log | audit2allow -M mynagios

module mynagios 1.0;

require {
type security_t;
type usr_t;
type ping_t;
type httpd_sys_script_t;
type load_policy_t;
class security load_policy;
class file { read write };
class fifo_file getattr;

#============= httpd_sys_script_t ==============
allow httpd_sys_script_t usr_t:fifo_file getattr;

[ add comment ] ( 5 views )   |  [ 0 trackbacks ]   |  permalink

<<First <Back | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Next> Last>>