{"id":2272,"date":"2017-11-14T23:06:14","date_gmt":"2017-11-15T04:06:14","guid":{"rendered":"http:\/\/osric.com\/chris\/accidental-developer\/?p=2272"},"modified":"2017-11-14T23:06:14","modified_gmt":"2017-11-15T04:06:14","slug":"selinux-audit2why-audit2allow-policy-files","status":"publish","type":"post","link":"https:\/\/osric.com\/chris\/accidental-developer\/2017\/11\/selinux-audit2why-audit2allow-policy-files\/","title":{"rendered":"SELinux, audit2why, audit2allow, and policy files"},"content":{"rendered":"<p>I&#8217;m no expert on SELinux, but I cringe whenever I read an online tutorial that includes the step <em>Disable SELinux<\/em>.<\/p>\n<p>I ran into such a problem recently when I was installing <a href=\"https:\/\/www.icinga.com\/\">Icinga<\/a>. The service failed to start because of permissions issues creating the process ID (PID) file. One site suggested disabling SELinux, but I thought it was time to learn to update SELinux&#8217;s Type Enforcement (TE) policies instead.<\/p>\n<p>First, I needed the <code>audit2why<\/code> tool, to explain what was being blocked and why:<\/p>\n<pre><code># yum -q provides audit2why\r\npolicycoreutils-python-2.5-17.1.el7.x86_64 : SELinux policy core python\r\n                                           : utilities\r\nRepo        : base\r\nMatched from:\r\nFilename    : \/usr\/bin\/audit2allow<\/code><\/pre>\n<p>I installed the <code>policycoreutils-python<\/code> package (and dependencies):<\/p>\n<pre><code># yum install policycoreutils-python<\/code><\/pre>\n<p>I then ran <code>audit2why<\/code> against the audit log:<\/p>\n<pre><code># audit2why -i \/var\/log\/audit\/audit.log\r\ntype=AVC msg=audit(1510711476.690:132): avc:  denied  { chown } for  pid=2459 comm=\"icinga\" capability=0  scontext=system_u:system_r:nagios_t:s0 tcontext=system_u:system_r:nagios_t:s0 tclass=capability\r\n\r\n        Was caused by:\r\n                Missing type enforcement (TE) allow rule.\r\n\r\n                You can use audit2allow to generate a loadable module to allow this access.\r\n\r\ntype=AVC msg=audit(1510711476.724:134): avc:  denied  { read write } for  pid=2465 comm=\"icinga\" name=\"icinga.pid\" dev=\"tmpfs\" ino=19128 scontext=system_u:system_r:nagios_t:s0 tcontext=system_u:object_r:initrc_var_run_t:s0 tclass=file\r\n\r\n        Was caused by:\r\n                Missing type enforcement (TE) allow rule.\r\n\r\n                You can use audit2allow to generate a loadable module to allow this access.<\/code><\/pre>\n<p>That&#8217;s still a little opaque. It&#8217;s not entirely clear to me why <code>chown<\/code> was blocked, for example. Look at the following specifics:<\/p>\n<pre><code>scontext=system_u:system_r:nagios_t:s0\r\ntcontext=system_u:system_r:nagios_t:s0<\/code><\/pre>\n<p>To help decode that:<\/p>\n<ul>\n<li>scontext = Source Context<\/li>\n<li>tcontext = Target Context<\/li>\n<li>_u:_r:_t:s# = user:role:type:security level<\/li>\n<\/ul>\n<p>The source and target contexts are identical, and so it seems to me that the command should be allowed. But let&#8217;s try <code>audit2allow<\/code> and see what that tells us:<\/p>\n<pre><code># audit2allow -i \/var\/log\/audit\/audit.log\r\n\r\n\r\n#============= nagios_t ==============\r\nallow nagios_t initrc_var_run_t:file { lock open read write };\r\nallow nagios_t self:capability chown;<\/code><\/pre>\n<p>It is unclear to me how broad the first rule is: does it allow the nagios type (<code>nagios_t<\/code>) access to all <code>initrc_var_run_t<\/code> files? If so, that&#8217;s probably too broad. As the man page warns:<\/p>\n<pre><code>Care must be exercised while acting on the output of  this  utility  to\r\nensure  that  the  operations  being  permitted  do not pose a security\r\nthreat. Often it is better to define new domains and\/or types, or  make\r\nother structural changes to narrowly allow an optimal set of operations\r\nto succeed, as opposed to  blindly  implementing  the  sometimes  broad\r\nchanges  recommended  by this utility.<\/code><\/pre>\n<p>That&#8217;s fairly terrifying. Although if the alternative is disabling SELinux completely, an overly broad SELinux policy is not the worst thing in the world.<\/p>\n<p>So <code>audit2allow<\/code> provided a couple rules. Now what? Fortunately the <code>audit2why<\/code> and <code>audit2allow<\/code> man pages both include details on how to incorporate the rules into your SELinux policy. First, generate a new type enforcement policy:<\/p>\n<pre><code># audit2allow -i \/var\/log\/audit\/audit.log --module local &gt; local.te<\/code><\/pre>\n<p>This includes some extra information in addition to the default output:<\/p>\n<pre><code># cat local.te\r\n\r\nmodule local 1.0;\r\n\r\nrequire {\r\n        type nagios_t;\r\n        type initrc_var_run_t;\r\n        class capability chown;\r\n        class file { lock open read write };\r\n}\r\n\r\n#============= nagios_t ==============\r\nallow nagios_t initrc_var_run_t:file { lock open read write };\r\nallow nagios_t self:capability chown;<\/code><\/pre>\n<p>Next the man page says:<\/p>\n<pre><code># SELinux provides a policy devel environment under\r\n# \/usr\/share\/selinux\/devel including all of the shipped\r\n# interface files.\r\n# You can create a te file and compile it by executing\r\n\r\n$ make -f \/usr\/share\/selinux\/devel\/Makefile local.pp<\/code><\/pre>\n<p>However, my system had no <code>\/usr\/share\/selinux\/devel<\/code> directory:<\/p>\n<pre><code># ls \/usr\/share\/selinux\/\r\npackages  targeted<\/code><\/pre>\n<p>I needed to install the <code>policycoreutils-devel<\/code> package (and dependencies):<\/p>\n<pre><code># yum install policycoreutils-devel<\/code><\/pre>\n<p>Now compile the policy file to a binary:<\/p>\n<pre><code># make -f \/usr\/share\/selinux\/devel\/Makefile local.pp\r\nCompiling targeted local module\r\n\/usr\/bin\/checkmodule:  loading policy configuration from tmp\/local.tmp\r\n\/usr\/bin\/checkmodule:  policy configuration loaded\r\n\/usr\/bin\/checkmodule:  writing binary representation (version 17) to tmp\/local.mod\r\nCreating targeted local.pp policy package\r\nrm tmp\/local.mod.fc tmp\/local.mod<\/code><\/pre>\n<p>Now install it using the <code>semodule<\/code> command:<\/p>\n<pre><code># semodule -i local.pp<\/code><\/pre>\n<p>Did that solve the problem?<\/p>\n<pre><code># systemctl start icinga\r\n# systemctl status icinga\r\n\u25cf icinga.service - LSB: start and stop Icinga monitoring daemon\r\n   Loaded: loaded (\/etc\/rc.d\/init.d\/icinga; bad; vendor preset: disabled)\r\n   Active: active (running) since Tue 2017-11-14 22:35:23 EST; 6s ago\r\n     Docs: man:systemd-sysv-generator(8)\r\n  Process: 2661 ExecStop=\/etc\/rc.d\/init.d\/icinga stop (code=exited, status=0\/SUCCESS)\r\n  Process: 3838 ExecStart=\/etc\/rc.d\/init.d\/icinga start (code=exited, status=0\/SUCCESS)\r\n   CGroup: \/system.slice\/icinga.service\r\n           \u2514\u25003850 \/usr\/bin\/icinga -d \/etc\/icinga\/icinga.cfg\r\n\r\nNov 14 22:35:23 localhost.localdomain systemd[1]: Starting LSB: start and sto...\r\nNov 14 22:35:23 localhost.localdomain icinga[3838]: Running configuration che...\r\nNov 14 22:35:23 localhost.localdomain icinga[3838]: Icinga with PID  not runn...\r\nNov 14 22:35:23 localhost.localdomain icinga[3838]: Starting icinga: Starting...\r\nNov 14 22:35:23 localhost.localdomain systemd[1]: Started LSB: start and stop...\r\nNov 14 22:35:23 localhost.localdomain icinga[3850]: Finished daemonizing... (...\r\nNov 14 22:35:23 localhost.localdomain icinga[3850]: Event loop started...\r\nHint: Some lines were ellipsized, use -l to show in full.<\/code><\/pre>\n<p>It worked! The permissions issues were resolved without resorting to disabling SELinux.<\/p>\n<p>There is still more I need to understand about SELinux, but it&#8217;s a start.<\/p>\n<p>Additional reading:<br \/>\n<a href=\"https:\/\/www.centos.org\/docs\/5\/html\/Deployment_Guide-en-US\/rhlcommon-chapter-0001.html\">CentOS: SELinux Policy Overview<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently encountered a permissions issue caused by SELinux. Some online sources suggested disabling SELinux, which seems like a bad idea. I used the audit2why and audit2allow commands to look more closely at the denied actions, and used audit2allow to modify the system SELinux policy to allow the actions.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,422],"tags":[474,475,458],"class_list":["post-2272","post","type-post","status-publish","format-standard","hentry","category-security","category-sysadmin","tag-audit2allow","tag-audit2why","tag-selinux"],"_links":{"self":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2272","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/comments?post=2272"}],"version-history":[{"count":5,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2272\/revisions"}],"predecessor-version":[{"id":2277,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2272\/revisions\/2277"}],"wp:attachment":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/media?parent=2272"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/categories?post=2272"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/tags?post=2272"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}