danwalsh


Dan Walsh's Blog

Got SELinux?


Previous Entry Add to Memories Share Next Entry
Google Chrome Policy
danwalsh
I received my first bugzilla on the chromium-browser from Google  the other day for Fedora 12. 

I figured it was time to bite the bullet and try it out.  While it works pretty well, there are several SELinux issues. 
First it needs execmem.  Execmem means that the application wants to be able to write memory and execute the same memory it wrote.  This is a signature required for buffer overflow attacks.    But developers also use it for things like Just In Time compilation.

Not great, but I will label it execmem_exec_t and it runs.  

My machine has my login account setup as a confined user staff_t.  When I execute chromium-browser, I notice chromium execs chromium-sandbox, which generates a ton of AVC messages.

In order to get this to work with staff_t in enforcing mode,  I  have to write policy for the chromium-sandbox.

I use sepolgen to get me started.

sepolgen -t 2 usr/lib64/chromium-browser/chrome-sandbox

-t tells sepolgen to generate a user application policy

sepolgen generated chrome_sandbox.te,if, fc, sh

Which I did not like, so I renamed to chrome.te,if,fc,sh,

Note to self, need to add an option to sepolgen to pick a name

Lets look at the files created by sepolgen and edited by me.

Remember, In SELinux the te file (Type Enforcement) contains all the rules and type definitions for a new policy domain.  In this case I will write all the rules on how a chromium-sandbox domain will run.

cat chrome,te

policy_module(chrome,1.0.0)

########################################
#
# Declarations
#

type chrome_sandbox_t;
type chrome_sandbox_exec_t;
application_domain(chrome_sandbox_t, chrome_sandbox_exec_t)
role system_r types chrome_sandbox_t;

This section defines the types for the process and the executable. It uses the application_domain interface to define chrome_sandbox_t as an application domain, meaning userdomains can execute this domain.  Application domain will take care of identifying chrome_sandbox_t as a domain type (process type),  and identify chrome_sandbox_exec_t as a file type.  It also adds rules that allow chrome_sandbox_t can be transitioned to, from files labelled chrome_sandbox_exec_t.

type chrome_sandbox_tmp_t;
files_tmp_file(chrome_sandbox_tmp_t)

type chrome_sandbox_tmpfs_t;
files_tmpfs_file(chrome_sandbox_tmpfs_t)
ubac_constrained(chrome_sandbox_tmpfs_t)

After running the chrome_sandbox_t domain I found that chrome-sandbox creates/writes /dev/shm tmpfs files and /tmp files.   chrome-sandbox needs to write to these files, I have to add types for each.  If a domain owns a file/directory and needs to write to the file/directory, you usually need to create a new type.

permissive chrome_sandbox_t;

When I write new policy now, I default to permissive domains to make sure I don't blow up the user environment.  I usually wait for the next version of the OS to turn permissive domains to enforcing domains.  This means I will probably leave chrome_sandbox_t as a permissive domain for all of F12 and turn it enforcing in F13.  This allows me to gather lots of AVC's and not force the user to disable SELinux on not use chrome. And hopefully allows me to write better policy.  You can use the seinfo --permissive command to list all the permissive domains on your system.

########################################
#
# chrome_sandbox local policy
#
allow chrome_sandbox_t self:capability { setuid sys_admin dac_override sys_chroot chown fsetid setgid };

chrome-sandbox needs a lot of privileges, I am not sure why.    I did not read the source.

Here is what I have surmised from looking at the AVC messages.  It is a setuid app and creates files directories in a chroot,  I figure this chroot is in my homedir somewhere and the setuid app needs to create files as my UID,  dac_override allows UID=0 processes to create files as my UID.  sys_chroot allows it to create chroot environment setuid, setgid allows the process to change to my uid and gid.  I am surprised that chrome-sandbox does not need getcap/setcap to drop its privileges.  Setuid apps should almost always drop privileges after they finish their initialization, to prevent bugs in the app allowing privilege escalation. 

allow chrome_sandbox_t self:process { setrlimit execmem };

This access allows to process to change its limits and execute writable memory, neither privilege is great to give to an application that will be running untrusted content.   But it probably needs it.

allow chrome_sandbox_t self:fifo_file manage_file_perms;
allow chrome_sandbox_t self:unix_stream_socket create_stream_socket_perms;
allow chrome_sandbox_t self:unix_dgram_socket { create_socket_perms sendto };
allow chrome_sandbox_t self:shm create_shm_perms;

All of these rules allow the process or groups of processes with this label to inter process communicate.

manage_dirs_pattern(chrome_sandbox_t, chrome_sandbox_tmp_t, chrome_sandbox_tmp_t)
manage_files_pattern(chrome_sandbox_t, chrome_sandbox_tmp_t, chrome_sandbox_tmp_t)
files_tmp_filetrans(chrome_sandbox_t, chrome_sandbox_tmp_t, { dir file })

manage_files_pattern(chrome_sandbox_t, chrome_sandbox_tmpfs_t, chrome_sandbox_tmpfs_t)
fs_tmpfs_filetrans(chrome_sandbox_t, chrome_sandbox_tmpfs_t, file)

These rules allow chrome_sandbox to manage these file types defined above.  The files_tmp_filetrans interface says, if a process labeled chrome_sandbox_t creates a file or directory in a directory labeled tmp_t, the kernel will create it labeled chrome_sandbox_tmp_t.  fs_tmpfs_filetrans works similary with directories labeled tmpfs_t.

kernel_read_kernel_sysctls(chrome_sandbox_t)

corecmd_exec_bin(chrome_sandbox_t)

This interface allows chrome_sandbox_t to execute most binaries on the system (Files labelled bin_t)  Not however these binaries will run under the label chrome_sandbox_t, meaning the ability to execute a random application will give the process no additional privileges.

dev_read_urand(chrome_sandbox_t)

This access allows chrome-sandbox to read /dev/urand, which is considered better then allowing an untrusted process to read /dev/rand.


files_read_etc_files(chrome_sandbox_t)

userdom_rw_user_tmpfs_files(chrome_sandbox_t)
userdom_use_user_ptys(chrome_sandbox_t)
Both of these are potentially dangerous.   The first one I think is needed to allow chrome_sandbox_t to communicate with pulseaudio via files in /dev/shm.  The second allows chrome_sandbox_t to read/write the terminal. 

If chrome_sandbox_t puts the word "password: ", into your terminal can you resist type yours?


miscfiles_read_localization(chrome_sandbox_t)
miscfiles_read_fonts(chrome_sandbox_t)

optional_policy(`
    execmem_exec(chrome_sandbox_t)
')
chrome-sandbox execs chromium, but will stay in the chrome_sandbox_t domain.

Remember, In SELinux the fc file (File Context) contains the regular expression mapping of files on disk to the types associated with the policy.

cat chrome.fc

/usr/lib(64)?/chromium-browser/chrome-sandbox    --    gen_context(system_u:object_r:chrome_sandbox_exec_t,s0)

The file context only had the label for the 64 bit browser sandbox location, so I changed this to work on 32 bit machines.

Elsewhere in the policy (execmem.fc) I have added

/usr/lib(64)?/chromium-browser/chromium-browser  gen_context(system_u:object_r:execmem_exec_t,s0)

I do not need to add file context for sandbox_chrome_tmpfs_t or sandbox_chrome_tmp_t since these should be temporary.


Remember, In SELinux the if file (Interface) contains the interfaces for how other domains can interact with the types created in the te file
cat chrome.if

--- snip ---
interface(`chrome_role',`
    gen_require(`
              type chrome_sandbox_t;
              type chrome_sandbox_tmpfs_t;
    ')

    role $1 types chrome_sandbox_t;

This rule allows the passed in role to execute chrome_sandbox_t.

    chrome_domtrans_sandbox($2)

This interface says that the userdomain passed in will transition to chrome_sandbox_t when it executes files labeled chrome_sandbox_file_t.

    ps_process_pattern($2, chrome_sandbox_t)
    allow $2 chrome_sandbox_t:process signal_perms;

These lines allow the user domain that transitioned to chrome_sandbox_t to look at the process and send it signals

    allow chrome_sandbox_t $2:unix_dgram_socket { read write };
    allow $2 chrome_sandbox_t:unix_dgram_socket { read write };
    allow chrome_sandbox_t $2:unix_stream_socket { read write };
    allow $2 chrome_sandbox_t:unix_stream_socket { read write };

    allow $2 chrome_sandbox_t:shm rw_shm_perms;
    allow $2 chrome_sandbox_tmpfs_t:file rw_file_perms;

Since Chromium is actually running in the users context these rules allow chromium to communicate with chromium-sandbox via unix stream sockets, unix datagram sockets, shared memory and the tmpfs file created in /dev/shm

')
---- snip ---

I also had to add

optional_policy(`
        chrome_role(unconfined_r, unconfined_execmem_t)
')

optional_policy(`
        chrome_role(staff_r, staff_execmem_t)
')


In other sections of the policy to make sure SELinux transitioned the user domain to the chrome_sandbox_t

Conclusion:

This policy seems to run fairly well for me on F12/Rawhide.  I have not seen any problems, although I tend to still use firefox for most of my browsing.

As you see from my description of my policy, SELinux has to make some compromises on what the application is allowed to do, in order to get its job done. 

So what does this prevent?  

SELinux prevents chrome-sandbox from:
  • Using the network
    • It can not copy files up to the internet
    • It can not send email and become a spam bot.
  • Writing anywhere on my home directory. Or pretty much anywhere on the system
  • Reading most locations on my system
    • Like mysql_db_t where I could have critical system data
    • /etc/shadow
    • ~/.ssh
    • ~/secret/DansPlanForWorldDomination.odp
  • Etc...
The power of least privilege is that the rules allowing the running of chrome-sandbox have to be stated directly, anything not allowed is denied.

If you want to examine all of the rules allowed for chrome_sandbox_t you can use sesearch in Fedora 12.

Policy in this document is based on policy in selinux-policy-3.6.32-24.fc12

sesearch --allow -s chrome_sandbox_t

chrome-sandbox is the binary that sets up the (much weaker than SELinux) chroot jail. On a real SELinux system I guess you'd want to skip it entirely and just use SELinux.

We've tried to implement some basic direct SELinux support, which is a compile-time flag. There's some code discussing it here:
http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/zygote_main_linux.cc?view=markup

My belief is that that the outer Chrome itself needs access to pretty much everything -- network, disk, etc. but without any RX pages. Then the renderer subprocess should be completely walled off from everything except for shared memory, but they need RX pages.

I started a thread on the developer list here:
http://groups.google.com/group/chromium-dev/browse_thread/thread/5753405090115104

No HTML allowed in subject

  
 
   
 

(will be screened)

You are viewing danwalsh