SeLinux - is it worth it?

Francesco Peeters francesco at fampeeters.com
Wed Sep 10 16:10:04 CST 2014


On 9/10/14 07:06 , Ant wrote:
>
> In my current job there is a culture to use selinux where it makes 
> sense. Nearly all applications run on dedicated VMs, and with selinux 
> enabled.
>
> Today in the RedHat world (maybe beyond) the default policy is 
> targeted and the provided default rules are good. You get a working 
> system with selinux enabled out of the box. Good place to start.
>
> Most tools eg ls have a -Z flag to display selinux info. You need to 
> be aware that copying a file from one place to another does not update 
> its context to be correct for the new location, so it is advisable to 
> be mindful of moves and run restorecon on the destination path after 
> moving files around. restorecon will update selinux permissions that 
> need to be updated and report what was changed when in verbose mode.
>
> Other than that, you can get most apps working by running the system 
> in permissive mode for testing or in production with real users 
> hammering it until you know the application has been solidly used. 
> Then use tools like audit2why to provide some clearer insight as to 
> whats been logged to the audit log (things which would have been 
> blocked, but wernt) and audit2allow to generate policies which will 
> allow the behaviour observed. Probably the rules wont be too complex 
> and you can tweak by hand if something looks too restrictive.
>
> For example, a light weight monitoring cgi which runs under apache and 
> reports if a process is alive. This needs more access than apache has 
> out of the box. Without a deep understanding of selinux internals you 
> can make a policy and get it working with:
>
> # disable enforcement of selinux so the app will run in full
> [root at process01 <mailto:root at process01> ~]# setenforce 0
>
> # check the existing context on new file(s)
> [root at process01 <mailto:root at process01> ~]# ls -Z 
> /var/www/cgi-bin/status.cgi
> -rw-rw-r--. root root unconfined_u:object_r:user_home_t:s0 
> /var/www/cgi-bin/status.cgi
>
> # see if they are correct for the system, and fix if they arn't
> [root at process01 <mailto:root at process01> ~]# restorecon -rv 
> /var/www/cgi-bin/
> restorecon reset /var/www/cgi-bin/status.cgi context 
> unconfined_u:object_r:user_home_t:s0->unconfined_u:object_r:httpd_sys_script_exec_t:s0
>
> # optionally inspect he new context
> [root at process01 <mailto:root at process01> ~]# ls -Z 
> /var/www/cgi-bin/status.cgi
> -rw-rw-r--. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 
> /var/www/cgi-bin/status.cgi
>
> #Use the app, make it do what it needs to, while gathering the denials
> [root at process01  <mailto:root at processing01>  ~]# tail -f  /var/log/audit/audit.log > denials
>
> # have a look at what would have been denied:
> [root at process01 ~]# audit2why < denials |grep denied
> type=AVC msg=audit(1403496601.298:59710): avc:  denied  { getattr } for  pid=13593 comm="appname" path="/var/run/appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
> type=AVC msg=audit(1403496601.298:59711): avc:  denied  { read } for  pid=13593 comm="appname" name="appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
> type=AVC msg=audit(1403496601.298:59712): avc:  denied  { open } for  pid=13593 comm="appname" name="appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
> type=AVC msg=audit(1403496601.298:59713): avc:  denied  { ioctl } for  pid=13593 comm="appname" path="/var/run/appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
> type=AVC msg=audit(1403496601.298:59714): avc:  denied  { getattr } for  pid=13593 comm="appname" path="/proc/21465" dev=proc ino=2347059 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:system_r:initrc_t:s0 tclass=dir
>
> # generate a policy with just enough access for this app:
> [root at process01 ~]# audit2allow -M statusapp < denials
> ******************** IMPORTANT ***********************
> To make this policy package active, execute:
>
> semodule -i statusapp.pp
>
> # inspect the rules
> [root at process01  <mailto:root at processing01>  ~]# cat statusapp.te
>
> module statusapp 1.0;
>
> require {
> 	type initrc_var_run_t;
> 	type httpd_sys_script_t;
> 	type initrc_t;
> 	class dir getattr;
> 	class file { read getattr open ioctl };
> }
>
> #============= httpd_sys_script_t ==============
>
> #!!!! This avc is allowed in the current policy
> allow httpd_sys_script_t initrc_t:dir getattr;
>
> #!!!! This avc is allowed in the current policy
> allow httpd_sys_script_t initrc_var_run_t:file { read getattr open ioctl };
>
> # install the policy
> [root at process01  <mailto:root at process01>  ~]# semodule -i statusapp.pp
>
> # re-enable enforcement, and retest the app
> [root at process01  <mailto:root at process01>  ~]# setenforce 1
>
> # re-test the app, it should now work with no denials logged.
>
> And for that you get the warm fuzzy feeling that your system is still locked down tight with an additional layer of defence.
>
> Ant
>
>
>
>
As stated earlier: It's too complex for the average user! Your example 
clearly demonstrates that, unfortunately... These things should be in a 
single tool...

Start monitoring with a single command, e.g. "sepolicy monitor -start 
statusapp"
After a while stop monitoring with (again) a single command, e.g. 
"sepolicy monitor -stop statusapp"
It then comes up with something like:

"Observed activities which would have been denied:

{ getattr } for path="/var/run/appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
{ read } for name="appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
{ open } for name="appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
{ ioctl } for path="/var/run/appname.pid" dev=dm-2 ino=1249 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:object_r:initrc_var_run_t:s0 tclass=file
{ getattr } for path="/proc/21465" dev=proc ino=2347059 scontext=unconfined_u:system_r:httpd_sys_script_t:s0 tcontext=unconfined_u:system_r:initrc_t:s0 tclass=dir

Would you like to allow these activities? (Yes, No, Specify - Y/n/s):"

And that's it...

WHY is it so difficult for linux developers to think user-friendly? I'm 
a geek and (ex-)programmer myself, but I always started with the desired 
users experience, and would then try to get as close as possible while 
doing the hard work under the covers... (But usually also provided 
'expert' options...)

-- 
Francesco



More information about the linuxsa mailing list