This article discusses security contexts for subjects (typically, processes) and how they are assigned. To view the list of processes on your system, along with their hierarchy, use the
pstree
command:[root@vbg-work ~]# pstree init-+-NetworkManager-+-dhclient | `-{NetworkManager} |-abrtd |-acpid |-atd |-auditd-+-audispd-+-sedispatch | | `-{audispd} | `-{auditd} |-avahi-daemon---avahi-daemon |-bonobo-activati---{bonobo-activat} |-cimserver---3*[{cimserver}] |-clock-applet |-console-kit-dae---63*[{console-kit-da}] |-crond |-cupsd |-2*[dbus-daemon---{dbus-daemon}] |-2*[dbus-launch] |-devkit-disks-da---devkit-disks-da |-devkit-power-da |-evolution---7*[{evolution}] |-evolution-alarm---{evolution-alar} |-evolution-data----2*[{evolution-data}] |-gconf-im-settin |-gconfd-2 |-gdm-binary---gdm-simple-slav-+-Xorg | `-gdm-session-wor---gnome-session-+-abrt-applet | |-bluetooth-apple | |-gdu-notificatio | |-gnome-panel---{gnome-panel} | |-gnome-power-man | |-gnome-volume-co | |-gpk-update-icon---{gpk-update-ico} | |-metacity---{metacity} | |-nautilus---{nautilus} | |-nm-applet | |-polkit-gnome-au
The above output shows the process tree on my system (starting with the
init
process). init
is the first one to be executed by the kernel after the basic system has been set up. All processes are children ofinit
. When the system is shut down, init
is the last process to terminate before the kernel executes its own shutdown.
To view the security contexts allotted to all system processes, execute the
pstree
command with the -Z
option:[root@vbg-work ~]# pstree -Z init(`system_u:system_r:init_t:s0') |-NetworkManager(`system_u:system_r:NetworkManager_t:s0') | |-dhclient(`system_u:system_r:dhcpc_t:s0') | `-{NetworkManager}(`system_u:system_r:NetworkManager_t:s0') |-abrtd(`system_u:system_r:abrt_t:s0-s0:c0.c1023') |-acpid(`system_u:system_r:apmd_t:s0') |-atd(`system_u:system_r:crond_t:s0-s0:c0.c1023') |-auditd(`system_u:system_r:auditd_t:s0') | |-audispd(`system_u:system_r:audisp_t:s0') | | |-sedispatch(`system_u:system_r:audisp_t:s0') | | `-{audispd}(`system_u:system_r:audisp_t:s0') | `-{auditd}(`system_u:system_r:auditd_t:s0') |-avahi-daemon(`system_u:system_r:avahi_t:s0') | `-avahi-daemon(`system_u:system_r:avahi_t:s0') |-bonobo-activati(`unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023') | `-{bonobo-activat}(`unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023') |-cimserver(`system_u:system_r:initrc_t:s0') | |-{cimserver}(`system_u:system_r:initrc_t:s0') | |-{cimserver}(`system_u:system_r:initrc_t:s0') | `-{cimserver}(`system_u:system_r:initrc_t:s0') |-clock-applet(`unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023') |-console-kit-dae(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023') | |-{console-kit-da}(`system_u:system_r:consolekit_t:s0-s0:c0.c1023')
Now, we can see the security contexts associated with all the processes. How did
init
get a type ofinit_t
? Why are the security contexts of some child processes different from those of the parent (else all processes in the system should have had the type init_t
)? How are these different security types assigned?
Consider another scenario: The
httpd
process on a Fedora/RHEL server is started with the commandservice httpd start
or /etc/init.d/httpd start
. Start the Web server process, if it’s not already running, with the following command:[root@vbg-work ~]# /etc/init.d/httpd start
Check the security context associated with the
httpd
process:[root@vbg-work ~]# ps axZ | grep httpd unconfined_u:system_r:httpd_t:s0 3099 ? Ss 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3102 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3103 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3104 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3105 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3106 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3107 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3108 ? S 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 3109 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3113 pts/0 S+ 0:00 grep httpd
As you can see, the
httpd
process gets a security context type of httpd_t
.
Stop the Web server with the following command:
[root@vbg-work ~]# service httpd stop Stopping httpd: [ OK ]
Restart the Web server. But this time, not from the
service
start-up script, but by executing the binary command, which is as follows:[root@vbg-work ~]# /usr/sbin/httpd
…and now, check the SELinux security context for the Web server process:
[root@vbg-work ~]# ps axZ | grep httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3207 ? Ss 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3209 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3210 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3211 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3212 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3213 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3214 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3215 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3216 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3218 pts/0 S+ 0:00 grep httpd [root@vbg-work ~]#
This time, the type of the Web server process is
unconfined_t
. Why is it so?
If we use the
service
command, the same Web server process gets a security context type of httpd_t
, but executing the Web server directly gives the Web server process a security context type ofunconfined_t
.
As you would have probably guessed by now, this is due to Type Transitioning. Like objects (files), Type Transitioning is also applied to subjects (processes).
The basic rules to set the security context of services are the same as those for files: Whenever a new service (process) is created in the memory, Type Transition rules in the policy are checked. If a Type Transition rule exists and matches the conditions, the resulting process is given the new security context. When there are no such rules, the new process inherits the security context of its parents.
To check all Type Transitions rules that apply to processes (classes of type process), issue the following commands:
[root@vbg-work ~]# sesearch -T -c process type_transition user_wine_t fusermount_exec_t : process mount_t; type_transition staff_execmem_t nsplugin_config_exec_t : process nsplugin_config_t; type_transition insmod_t fusermount_exec_t : process mount_t; type_transition xend_t fusermount_exec_t : process mount_t; type_transition sysadm_java_t fusermount_exec_t : process mount_t; type_transition ricci_modservice_t fail2ban_initrc_exec_t : process initrc_t; type_transition init_t afs_bosserver_exec_t : process afs_bosserver_t; type_transition hotplug_t dictd_initrc_exec_t : process initrc_t; type_transition ricci_modservice_t sssd_initrc_exec_t : process initrc_t; type_transition init_t apmd_exec_t : process apmd_t; type_transition qmail_local_t qmail_queue_exec_t : process qmail_queue_t; type_transition staff_execmem_t gpg_agent_exec_t : process gpg_agent_t; ...
Based on the above rules, the syntax of Type Transition rules that apply to processes can be understood as:
type_transtion [Parent Process Type] [Type of File being executed to create a process] : process [Type of The New Process created]
To check the above rules, let us look at the example of the Web server process discussed earlier. When executing the executable
/usr/sbin/httpd
directly to create the httpd
process:- The parent process is the shell (because we are executing the command
/usr/sbin/httpd
under the Bash shell). - The type of the parent process is
unconfined_t
. (Execute the following command to check.)[root@vbg-work ~]# ps axZ | grep bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2460 pts/0 Ss 0:00 bash
- The type of the file being executed is
httpd_exec_t
. (Execute the following command to check.)[root@vbg-work ~]# ls -lZ /usr/sbin/httpd -rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd
Let us check in our policy if such a rule exists:
[root@vbg-work ~]# sesearch -T -c process | grep httpd_exec_t | grep unconfined_t [root@vbg-work ~]#
This shows that we do not have a Type Transition rule to set the security context of new processes created by executing files of type
httpd_exec_t
under a parent process of type unconfined_t
. In such a scenario, i.e., in the absence of any Type Transition rule, the new process takes the type of the parent; therefore, the httpd
process inherits its security context from Bash (which is unconfined_t
).
Let us now analyse the other case. When starting the
httpd
service through initialisation scripts:- The parent process is the shell (because we are executing the script
/etc/init.d/httpd
under Bash). - The type of the parent process is
unconfined_t
. (Execute the following command to check.)[root@vbg-work ~]# ps axZ | grep bash unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2460 pts/0 Ss 0:00 bash
- The type of the file being executed is
httpd_initrc_exec_t
. (Execute the following command to check.)[root@vbg-work ~]# ls -lZ /etc/init.d/httpd -rwxr-xr-x. root root system_u:object_r:httpd_initrc_exec_t:s0 /etc/init.d/httpd
Let us check in our policy if such a rule exists:
[root@vbg-work ~]# sesearch -T -c process | grep httpd_initrc_exec_t | grep unconfined_t type_transition unconfined_t httpd_initrc_exec_t : process initrc_t; [root@vbg-work ~]#
Finally, we have found a match. This rule states that if a file of type
httpd_initrc_exec_t
is executed under a parent process of type unconfined_t
, the resulting process should get a type of initrc_t
.
This is good, but we had observed that the Web server process had a type of
httpd_t
and this rule states that the type of the resulting process is initrc_t
. Is there an error? Is there something missing?
There is, indeed, something missing. It is important to note that the Web server process is created on executing the binary file (
/use/bin/httpd
). Therefore, the init
script actually executes this file.
But what happens is that the shell script process created by executing the initialisation script (
/etc/init.d/httpd
) is now running with a process security context bearing the type initrc_t
(as per the rule above). When this process further executes the Web server binary (/usr/sbin/httpd
), a new context is created. Therefore, there is another scenario that comes into play here, which is:- The parent process is the shell script process created by executing the script
/etc/init.d/httpd
. - The type of the parent process is
initrc_t
(because this is the type of process created by executing theinit
script from under Bash, as per the Type Transition rule above). - The type of the file being executed is
httpd_exec_t
(as the shell script further executes the binary/usr/sbin/httpd
). Execute the following command to check:[root@vbg-work ~]# ls -lZ /usr/sbin/httpd -rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd
Let us see if we have a Type Transition rule in the policy for the above:
[root@vbg-work ~]# sesearch -T -c process | grep httpd_exec_t | grep initrc_t type_transition initrc_t httpd_exec_t : process httpd_t; [root@vbg-work ~]#
Voila! There it is, stating that if a file of type
httpd_exec_t
is executed under a parent process of typeinitrc_t
, the resulting process created will have a security context type of httpd_t
.
As an exercise, let us ensure that the
httpd
process, if executed directly under the shell, should also be created with a security context type of httpd.
To do this, we will need to create a new module and insert it into our policy. We will need to create a new type enforcement file as discussed in earlier articles. An example of the file is given below:vbg@vbg-work test-selinux]$ cat http.te policy_module(http-lfy,1.1.0) ######################################## # # Declarations # require { type httpd_t; type unconfined_t; type httpd_exec_t; role unconfined_r; class process transition; } ######################################## # # http local policy # type_transition unconfined_t httpd_exec_t : process httpd_t; role unconfined_r types httpd_t; allow unconfined_t httpd_t:process transition; [vbg@vbg-work test-selinux]$
Compile and load this module:
[vbg@vbg-work test-selinux]$ make http.pp [vbg@vbg-work test-selinux]$ su - [root@vbg-work ~]# semodule -i /home/vbg/test-selinux/http.pp
Now execute the command
/usr/sbin/httpd
and note the security context type of the httpd
process:root@vbg-work ~]# /usr/sbin/httpd [root@vbg-work ~]# [root@vbg-work ~]# ps axZ | grep http unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4343 ? Ss 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4345 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4346 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4347 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4348 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4349 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4350 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4351 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:httpd_t:s0-s0:c0.c1023 4352 ? S 0:00 /usr/sbin/httpd unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 4354 pts/0 S+ 0:00 grep http [root@vbg-work ~]#
But how is the type of the first process (init) set? Does it inherit its type from the kernel? What exactly happens?
The following lines are taken verbatim from Dan Walsh’s blog: “When the SELinux kernel boots up, it is hard coded to run as
Let us check if such a rule really exists in the policy, which applies when
kernel_t
. Since at this point there is no policy running, this is the only context. So since this is the only context, all applications that are run will stay in kernel_t
. When the kernel executes/sbin/init
it originally is running as kernel_t
, then it reads in the policy file and loads it into the kernel. At this point init re-execs itself. When /sbin/init
was installed it is labelled init_exec_t
and now there is a rule in the kernel that says when kernel_t
execs an application labelled init_exec_t
, it should transition to init_t
. So now the init
process is running as init_t
.”Let us check if such a rule really exists in the policy, which applies when
init
re-executes itself:- The parent process is the kernel.
- The parent process type is
kernel_t
. - The file being executed is
/sbin/init
. - The security context type of the file being executed is
init_exec_t
:[root@vbg-work ~]# ls -lZ /sbin/init -rwxr-xr-x. root root system_u:object_r:init_exec_t:s0 /sbin/init
Search the SELinux policy for a Type Transition rule:
root@vbg-work ~]# sesearch -T -c process | grep init_exec_t | grep kernel_t type_transition kernel_t init_exec_t : process init_t;
There we are! When
/sbin/init
is executed under kernel_t
, the init
process being created has a type of init_t
. This can be checked by the following command:[root@vbg-work ~]# pstree -pZ | head -n 1 init(1,`system_u:system_r:init_t:s0’) [root@vbg-work ~]#
Now we can understand how subjects or processes created in memory get their security contexts. Applying SELinux policy rules under type enforcement is simply allowing access only to desired objects by the designated subjects, and once we know how to set the security context types of objects and subjects, and how to create allow rules, we can easily achieve the best out of SELinux.
In the next article in this series, we will explore macros and dive deep into them.
0 comments
Post a Comment