SELinux: cannot confine Firefox process to mozilla_t domain

fedorafirefoxmozillaselinux

My goal is to execute Firefox in the mozilla_t domain instead of unconfined_t. The machine runs Fedora 20 with SELinux in enforcing mode.

Unfortunately, I can't seem to get this right. No matter what I do, the process is always executed in the unconfined_t domain.

I know that there are three conditions to be met:

  1. the target file context (mozilla_exec_t) must be executable for the source domain (unconfined_t or bin_t)
  2. the target file context (mozilla_exec_t) must be marked as an entry point for the target domain (mozilla_t)
  3. the source domain (unconfined_t or bin_t) must be allowed to transition to the target domain (mozilla_t)

The target file is the firefox script at /usr/bin/firefox which calls /usr/lib64/firefox/run-mozilla.run, which again runs the binary /usr/lib64/firefox/firefox. This is the output of ls -Z on these files:

-rwxr-xr-x. root root system_u:object_r:bin_t:s0       /usr/bin/firefox
-rwxr-xr-x. root root system_u:object_r:bin_t:s0       /usr/lib64/firefox/run-mozilla.sh
-rwxr-xr-x. root root system_u:object_r:mozilla_exec_t:s0 /usr/lib64/firefox/firefox

The first condition is met, as unconfined_t is allowed to execute the target file context mozilla_exec_t.

$ sesearch -s unconfined_t -t mozilla_exec_t -c file -p execute -Ad
Found 1 semantic av rules:
   allow unconfined_t mozilla_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ; 

The second condition is met, as mozilla_exec_t is defined as the entry point to the mozilla_t domain.

$ sesearch -s mozilla_t -t mozilla_exec_t -c file -p entrypoint -Ad
Found 1 semantic av rules:
   allow mozilla_t mozilla_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ; 

Per default configuration in Fedora 20, the third condition is not met because unconfined_t cannot transition to mozilla_t.

$ sesearch -s unconfined_t -t mozilla_t -c process -p transition -Ad
(no output)

To fix this I have written a short policy module that grants unconfined_t process permission to transition to mozilla_t.

module rekado 1.0;

require {
  type unconfined_t;
  type mozilla_t;
  class process transition;
}

allow unconfined_t mozilla_t : process transition ; 

Now I should be able to run the Firefox process in domain mozilla_t by directly running the executable /usr/lib64/firefox/firefox, but the process remains in domain unconfined_t.

What is going on here? Why isn't the process context mozilla_t?

Best Answer

You nearly had it. The problem is that the allow rule

allow unconfined_t mozilla_t : process transition ;

allows the transition to take place, but doesn't cause it to happen. For that you need a type_transition rule:

type_transition unconfined_t mozilla_exec_t : process mozilla_t;

This causes the transition to occur when an unconfined_t process executes a mozilla_exec_t file.

With that done, firefox won't run. I used audit2allow to track down the additional rules needed to allow firefox to manage temp files and sockets.

Here is a policy that works on my CentOS 6-based VM. It needs the selinux boolean mozilla_read_content enabled (via: setsebool -P mozilla_read_content 1).

module mozilla 1.0;

require {
  role unconfined_r;
  type unconfined_t;
  type mozilla_t;
  type mozilla_exec_t;
  type tmp_t;
  type user_tmp_t;
  type fs_t;
  class process transition;
  class file { ioctl getattr setattr create read write unlink open relabelto };
  class dir { ioctl getattr setattr create read write unlink add_name remove_name };
  class filesystem getattr;
  class sock_file { getattr setattr create read write unlink };
  class unix_stream_socket connectto;
}

role unconfined_r types mozilla_t;

allow unconfined_t self:file relabelto;
allow unconfined_t mozilla_t : process transition ; 

type_transition unconfined_t mozilla_exec_t : process mozilla_t;

allow mozilla_t fs_t:filesystem getattr;
allow mozilla_t tmp_t:file { ioctl getattr setattr create write unlink open };
allow mozilla_t tmp_t:dir  { ioctl getattr setattr create read write add_name remove_name };
allow mozilla_t user_tmp_t:dir { ioctl create write add_name setattr remove_name };
allow mozilla_t user_tmp_t:sock_file { getattr setattr create read write unlink };
allow mozilla_t unconfined_t:unix_stream_socket connectto;  

To compile and install it:

# checkmodule -M -m -o mozilla.mod mozilla.te
checkmodule: loading policy configuration from rekado.te
checkmodule: policy configuration loaded
checkmodule: writing binary representation (version 10) to mozilla.mod
# semodule_package -o mozilla.pp -m mozilla.mod
# sudo semodule -i mozilla.pp

Related Topic