Showing posts with label SELinux. Show all posts
Showing posts with label SELinux. Show all posts

Tuesday, March 12, 2013

RHEL 6.4 SELinux user mapping

Normally, Red Hat does a decent job on their release notes about explaining what a new feature or change brings with each new RHEL minor release, but this time the release notes did not do the full scope of the change justice:
SSSD Fully Supported Features
A number of features introduced in Red Hat Enterprise Linux 6.3 are now fully supported in Red Hat Enterprise Linux 6.4. Specifically:
  • support for central management of SSH keys,
  • SELinux user mapping,
  • and support for automount map caching.
The key line here was "SELinux user mapping".  This played in with IPA to generate some undesirable results, since the installation of IPA that was serving these systems did not have any SELinux user mapping defined, other than the default role.

Prior to the upgrade, mappings were not enforced, so the SELinux context was unconfined:
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Post upgrade, the IPA default user was enforced.  This was not obvious at first, though.  The symptoms were that things that normally worked, didn't: sudo, su, dmesg, looking at log files.  Standard sysadmin diagnostics stuff suddenly stopped working completely.  

Trying to dig into this lead to very strange results, like not being able to run ls -l /bin/su directly and getting "?" for the su record when running ls -l /bin.  The same kind of strange behavior happened to /var, /root, and a few other key areas.  It behaved a lot like filesystem damage at first, but the fsck came back clean.  Logging in as root on the system console did work though, so that was my first clue.

Because this behavior was so bizarre, I tried a setenforce 0 to rule out SELinux, and all of a sudden things started working for non-root users logged in remotely.  I have been used to beating SELinux into submission a daemon context, but this was the first time I'd run into it as a user.
$id -Z
guest_u:guest_r:guest_t:s0-s0:c0.c1023
Up until now, there were no SELinux User Maps in IPA, so default mapping to the guest role was being used.  Thus, the first step was to define some non-guest roles to use.

There was not a lot of information about this on the IPA wiki, but I did find a decent writeup about configuring SELinux on Gentoo's site.  This gave me the key pieces that I needed to setup a map for the user_u:user_r:user_t and the staff_u:staff_r:staff_t mappings for mere mortals and sysadmins.

Amazing what happens when you have permissions to actually run things!

The next step required was to cleanly handle the staff_t to sysadm_t transition for sudo without requiring a separate newrole command to be run.  Thankfully, sudo is SELinux aware, so adding "role=sysadm_r" to the Sudo Rule in IPA that allows sysadmin commands took care of that part.

Thursday, February 14, 2013

SELinux policy for EZproxy

My "wish list" item for EZproxy to adopt support for SELinux seems to have generated a bit of general interest.  It seems that I am not the only one who distrusts big binary blobs of software, and wants to contain them as much as possible.

So, without further ado, here is the policy that I have developed for EZproxy on RHEL6/CentOS6.

ezproxy.te:

policy_module(ezproxy,1.0.20)

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

type ezproxy_t;
type ezproxy_exec_t;

init_daemon_domain(ezproxy_t, ezproxy_exec_t)

type ezproxy_script_exec_t;
init_script_file(ezproxy_script_exec_t)

type ezproxy_rw_t;
files_type(ezproxy_rw_t)

gen_require(`
        type initrc_exec_t;
        type sysctl_kernel_t;
        type proc_t;
        type fs_t;
        type tmpfs_t;
        type usr_t;
        type port_t;
        type dns_port_t;
        type public_content_t;
        type public_content_rw_t;
')

########################################
#
# ezproxy local policy
#
allow ezproxy_t self:capability { dac_read_search dac_override chown ipc_owner kill sys_resour
ce setgid setuid };
allow ezproxy_t self:fifo_file rw_file_perms;
allow ezproxy_t self:unix_stream_socket create_stream_socket_perms;allow ezproxy_t self:shm { create unix_read read setattr getattr associate unix_write write de
stroy };

# Init script handling
init_domtrans(ezproxy_t)
domain_use_interactive_fds(ezproxy_t)

allow ezproxy_t sysctl_kernel_t:dir { search read };
allow ezproxy_t sysctl_kernel_t:file read;

allow ezproxy_t self:process { setrlimit execmem };
allow ezproxy_t fs_t:filesystem getattr;
allow ezproxy_t tmpfs_t:file { read write };

allow ezproxy_t usr_t:file { read getattr open };
allow ezproxy_t proc_t:file { read open };

allow ezproxy_t initrc_t:process { signull sigkill };
allow ezproxy_t self:process { signull sigkill };
allow ezproxy_t initrc_t:shm { unix_read unix_write };

files_read_etc_files(ezproxy_t)

libs_use_ld_so(ezproxy_t)
libs_use_shared_libs(ezproxy_t)

miscfiles_read_localization(ezproxy_t)

allow ezproxy_t ezproxy_exec_t:file execute_no_trans;

allow ezproxy_t ezproxy_rw_t:file { manage_file_perms read write };allow ezproxy_t ezproxy_rw_t:dir { search create_dir_perms read write add_name remove_name ope
n };

# Allow the document directory to be a symlink into the ftp directory
allow ezproxy_t ezproxy_rw_t:lnk_file read;

allow ezproxy_t public_content_rw_t:lnk_file read;
allow ezproxy_t public_content_rw_t:dir { search read open };
allow ezproxy_t public_content_rw_t:file { getattr read open };

allow ezproxy_t public_content_t:lnk_file read;
allow ezproxy_t public_content_t:dir { search read };
allow ezproxy_t public_content_t:file { getattr read open };




allow ezproxy_t dns_port_t:udp_socket name_bind;
allow ezproxy_t dns_port_t:tcp_socket name_bind;

sysnet_dns_name_resolve(ezproxy_t)
corenet_all_recvfrom_unlabeled(ezproxy_t)

allow ezproxy_t self:tcp_socket create_stream_socket_perms;
allow ezproxy_t port_t:tcp_socket name_bind;
corenet_tcp_sendrecv_all_if(ezproxy_t)
corenet_tcp_sendrecv_all_nodes(ezproxy_t)
corenet_tcp_sendrecv_all_ports(ezproxy_t)
corenet_tcp_bind_all_nodes(ezproxy_t)
corenet_tcp_connect_all_ports(ezproxy_t)
corenet_tcp_bind_http_port(ezproxy_t)

auth_use_nsswitch(ezproxy_t)

dev_read_rand(ezproxy_t)
dev_read_urand(ezproxy_t)


ezproxy.fc:
/opt/ezproxy/ezproxy    --      gen_context(system_u:object_r:ezproxy_exec_t,s0)
/etc/init.d/ezproxy     --      gen_context(system_u:object_r:ezproxy_script_exec_t,s0)
/opt/ezproxy(/.*)?              gen_context(system_u:object_r:ezproxy_rw_t,s0)
/opt/ezproxy/docs(/.*)?         gen_context(system_u:object_r:public_content_t,s0)
Save those, make sure you have the SELinux development environment installed, and you should be able to just run "make -f /usr/share/selinux/devel/Makefile" to generate the ezproxy.pp file.

I have only used that in proxy-by-hostname configuration, so since I have not really tested proxy-by-port, there may be some gremlins in port-based setups.

Thursday, January 24, 2013

EZproxy wish list: SELinux support

SELinux is the software that I love to hate:  I love it when it works, but I hate it when I have to beat it into submission.

And I wouldn't have it any other way.

SELinux compartmentalizes each piece of software and defines a "software firewall" -- if you will -- for what a given program can do, what files it can read, what directories it can write to, what level of network access it has, etc.

Where many people get frustrated with SELinux is when they stray afield of where the OS vendor's policies expected them to go.  Running a web server on port 80 is normal.  Running on on port 6000, not so much.


For EZproxy, there was no existing policy, so I had to write my own from scratch.  I even found some interesting things along the way about EZproxy's memory handling that I had to put special exceptions in the policy to accommodate.  I don't know if OCLC fixed the special exception case or not, but I gave them a heads-up about it; I suppose I should remove the exception and see if the server still blows up spectacularly without it.

Basic support was fairly direct, but with each EZproxy upgrade I have to revalidate the policies to ensure that they are still working.  

Occasionally I have to tweak things due to OS vendor changes as well.  Those generally only show up when I build a new policy; so far the existing policies have continued to work even when I can't build a new one because I did not update for the new vendor changes.

Lately I've been doing more advanced work, allowing librarians to manage their content via FTP into the EZproxy documentation directories.

It is worth it, though, because I know that should someone find a remote compromise for EZproxy, that the damage that they can do as the ezproxy user is limited not only by the system's file permissions, but also by their SELinux context.

For OCLC to be successful with adding a SELinux policy to EZproxy, though, they need to move away from the statically linked binary installer that you can install anywhere.  They need to produce packages for each supported Linux variant so that the files will be installed into known places that the SELinux policies can reference.