October 2nd, 2007

More small customizations to policy

Tim Fenn, has asked a question on the Fedora  SELinux mail list that I would like to expand to a wider audience.

> I recently upgraded a machine from FC6 to F7, and I used to use a
> /etc/dhclient-exit-hooks script to call some iptables functions after
> bringing up my external interface.  This used to work on FC6 as long
> as I setsebool -P dhcpc_disable_trans 1, but the policy in F7 no
> longer contains such a boolean, so dhclient-script is prevented from
> getattr/executing iptables.  Is there a simple fix to this, or do I
> need to write a policy and compile it?  If the latter, any pointers on
> what the policy file should contain?
>
> Thanks for any help,
> tim
>
We have decided in FC7 and beyond to remove the *_disable_trans booleans.  The problem with these booleans is they caused unexpected side effects.  When you disable a transition of a domain, all of the files created by that domain will not necessarily get created with the right context, this can cause other confined domains, that depend on those contexts to no longer work.  Causing more problems then disable_trans was there to help.  For an extreme example, if you set the boolean syslog_disable_trans,  the /dev/log will get created with a context type of device_t rather then devlog_t and all confined domains that syslog, will now blow up.

So what is the solution to the problem where a confined domain will not work with SELInux in enforcing mode?

Well you can still get the app to not transition, by simply setting the executables file context to bin_t,

# chcon -t bin_t PATH_TO_NO_LONGER_CONFINED_APP

This will cause the transitions to not happen.  Of course, this ends up with the same problem of disable_trans described above and will not survive a relabel.

A second and better option is to use audit2allow to create custom policy for your application.  The easiest way to do this is to simply execute
# grep BADAPP_t /var/log/audit/audit.log | audit2allow -M myBADDAPP
# semodule -i myBADAPP.pp


These commands  generates a bunch of allow rules and compiles and builds policy to allow them.  You might want to run your application in permissive mode to gather all the avc messages.

NOTE:  myBADDAPP.pp will replace all the rules of a previously install myBADDAPP.pp

While this is a good solution for a lot of people, it can sometimes write some bad policy.  It is a good idea to look at the generated policy (myBADAPP.te has the generated rules) and try to understand what the audit2allow command has generated.

  • Look for rules allowing writes to standard/default system file context (for example etc_t, usr_t, root_t, var_lib_t, var_run_t, var_log_t, lib_t, bin_t default_t )  you might have a labeling problem.  A restorecon on the file/directory that the confined application is trying to writte, might solve your problem.
  • Look for rules that allow the execution of a files labeled as an APP_exec_t, this usually indicates you need a rule allowing a transition to the other confined domain.  Adding a transtion rule APP_domtrans(myBADDAPP_t) will allow you confined app to run the second confined application under the correct domain and eliminate lots of AVC messages and prevent you from adding those rules to your confined domain.  This is an example of writing policy for least priveledge,  only give the allow rules to the domains that need them.

So lets get back to Tim's question:

Worst Solution:

He basically wants to be able to run iptables rules when he brings up and down his interfaces.  In FC6 he disabled the transition on dhcp which potentially could have left files like /etc/resolv.conf with the wrong label, causing lots of other problems.  In FC7, he can change the context to bin_t, but that could also end up with resolv.conf having a bad context. 

Better Solution:

Or he can run his start up in permissive mode.

# setenforce 0
service Network start
#setenforce 1
# grep dhcp /var/log/audit/audit.log | audit2allow -M mydhcp
# semodule -i mydchp.pp


This will give dhcp all of the power of iptables

Best solution,  Create a custom policy file that will allow dhcpc_t to transition to iptables_t.

Make sure you install the policy devel interfaces.


# yum install selinux-policy-devel

Create a te file that looks something like:

#cat mydhcp.te
policy_module(mydhcp,1.0.0)

########################################
#
# Declarations
#
require {
        type dhcpc_t;
}

iptables_domtrans(dhcpc_t)


Compile up the custom policy

# make -f /usr/share/selinux/devel/Makefile


Install the policy package

# semodule -i mydhcp.pp

Now you still may have additional avc's that you have to handle. and you can add those to your local policy packages.

# service network start
# audit2allow -R -m -l -i /var/log/audit/audit.log >> mydhcp.te

Note:  -R tells audit2allow to search for appropriate interface rather then just generate allow rules.   -l says only look at avc messages since the last time I generated policy.   -m Says generate all of the rules to generate a module. 

# make -f /usr/share/selinux/devel/Makefile
# semodule -i mydhcp.pp


Your rules should be more specify now to dhcpc and iptables_t, giving you a better custom policy.  If you don't understand the rules that are added, you can always ask someone to look at your custom policy.  One of the big advantages of Open Source is the many eyes theory.

Creating a Kiosk Account using SELinux and Fedora 8.

Over the last few months, in between playing my own personal version of Wack A Mole (AVC).   I have been working on Roles Based Access Control (RBAC) or confining users.  As I have explained in previous blogs, I have defined a policy to be used for the least privledged login terminal and X Windows users. 

One of the goals of this was to define a Kiosk User account. the idea was to secure these machines that you can walk up to at the library, bank,  airport, coffee shop and just login and use the internet.  So I investigated how to do this with SELinux. 

I demonstrated this account to  Jonathan Blandford from the Fedora Desktop Team saw it and suggested it would be cool to use one of these accounts with Fast User Switching.
 
One problem with this,  we need to be able to use this account without a password.   From a security stand point. we can only protect the account if SELinux is enabled and in enforcing mode.   We needed a new pam module  for this.  I asked Tomas Mraz to look into this and he created pam_selinux_permit

man pam_selinux_permit

PAM_SELINUX_PERMIT(8)          Linux-PAM Manual          PAM_SELINUX_PERMIT(8)

NAME
       pam_selinux_permit - PAM module to allow/deny login depending on
       SELinux enforcement state

SYNOPSIS
       pam_selinux_permit.so [debug] [conf=/path/to/config/file]

DESCRIPTION
       The pam_selinux module allows or denies login depending on SELinux
       enforcement state.

       When the user which is logging in matches an entry in the config file
       he is allowed access only when the SELinux is in enforcing mode.
       Otherwise he is denied access. For users not matching any entry in the
       config file the pam_selinux_permit module returns PAM_IGNORE return
       value.

       The config file contains a simple list of user names one per line. If
       the name is prefixed with @ character it means that all users in the
       group name match. If it is prefixed with a % character the SELinux user
       is used to match against the name instead of the account name. Note
       that when SELinux is disabled the SELinux user assigned to the account
       cannot be determined. This means that such entries are never matched
       when SELinux is disabled and pam_selinux_permit will return PAM_IGNORE.
...

Now we can create an xguest account with disabled  password.  Then we can setup xdm to use pam_selinux_permit.

# useradd -Z xguest_u xguest


# cat /etc/pam.d/gdm
#%PAM-1.0
auth     [success=done ignore=ignore default=bad] pam_selinux_permit.so
auth       required    pam_env.so
auth       include     system-auth
auth       optional    pam_gnome_keyring.so auto_start
account    required    pam_nologin.so
account    include     system-auth
...
session    required    pam_selinux.so open
session    required    pam_namespace.so
session    optional    pam_gnome_keyring.so


Add the xguest user to the /etcv/security/sepermit.conf
# cat
/etc/security/sepermit.conf
# /etc/security/sepermit.conf
#
# Each line contains either:
#        - an user name
#        - a group name, with @group syntax
#        - a SELinux user name, with %seuser syntax
xguest



If SELinux is in enforcing mode, you can log into this account just by clicking on the xguest user.  If you try to reach this accound by any means other then xdm you will not be able to login.  sshd, rshd, telnetd will all fail.

If you put the machine into permissive mode  or disable selinux, you  will no longer be able to login as this user.  This will not effect a currently logged in user however.

You can also use Fast User Switching to switch to this user.  Just add the User Switcher applet to your tool bar and select xguest.  You should switch to this account and be automagically logged in.

To add additional security to this account, it would be useful to have all files/directories removed that were created by the xguest user.  So if a new person uses the xguest, he can guarantee a clean environment.  So we can setup pam_namespace to generate a new Homedir, /tmp and /var/tmp. Every time the X Windows session ends.  You need pam_namespace.so added to /etc/init.d/gdm for this, as shown above.

Also add these lines to /etc/secuirty/namespace.conf
/tmp    tmpfs   tmpfs   ~xguest
/var/tmp        tmpfs   tmpfs   ~xguest
$HOME           tmpfs   tmpfs   ~xguest

This says to generate three temporary filesystems mounted on  /tmp, /var/tmp and $HOME directory for only xguest any time he logs in.

I have generated an rpm package and spec file that will set this all up for you.  You can try this out at

http://people.fedoraproject.org/~dwalsh/xguest/



There are three booleans that you can set for this account.
getsebool -a | grep xguest

  • browser_confine_xguest

    This indicates whether the xguest account will transition to xguest_mozilla_t or not.  If you turn this boolean on, xguest will be able to browse the web using firefox/mozilla.  If you turn it off the account will only be allowed to run mozilla/firefox locally.  You will not have any access to the net.

  • browser_write_xguest_data

This will determine whether firefox can write to the home directory or not.

If this boolean is turned off firefox will only be allowed to write to .mozilla and .gnome in the home directory.
If you wanted to add a download directory you could add a file context and label it xguest_mozilla_home_t

# semanage fcontext -a -t xguest_mozilla_home_t /home/xguest/Download(/.*)?
# restorecon -R -v ~/xguest
  • allow_xguest_exec_content
This boolean determines whether the xguest account can execute files in its home directory or /tmp.  This can prevent some forms of attack on users.

I have created xguest.spec and xguest-1.0.0-1.fc8.noarch.rpm

out on
http://people.fedoraproject.org/~dwalsh/xguest/
Which will set everything up for you.  Try it out and tell me what you think.