Thursday, January 14, 2010

Another Fight between SELinux and PHP

After I installed the web portion of ZoneMinder, and navigated to the main console page, the system message log started filling up with a message saying:

SELinux is preventing /usr/bin/uptime from using potentially mislabeled files utmp (initrc_var_run_t)

Great, I thought... another annoying SELinux nag message to eliminate and another convoluted SELinux policy setting to figure out. Well, this time it was just PHP code, so then I thought, maybe there's an easier way to fix this one. There was.

ZoneMinder's PHP code was parsing the output of the uptime command just to get the system load information, and as long as the browser was sitting on the ZM console page, it would call the function again every few minutes. However, in addition to the system load info, the uptime command also collects the OS level user-session info by reading the /var/run/utmp file. SELinux prevents that file from being read by anything running in the web server (Apache) process. After a little searching around, I found that the load information is also available by just examining /proc/loadavg, so I changed the PHP code from
shell_exec('uptime')
to
shell_exec('cat /proc/loadavg')
which SELinux doesn't seem to care anything about.

When the uptime command is used in a PHP script, the output could be parsed in various ways, but in the ZoneMinder PHP code, the output from shell_exec( 'uptime' ), which looks like this:
16:22:09 up 284 days, 1:04, 1 user, load average: 0.06, 0.06, 0.00
was being parsed by the preg_match PHP function like this:
preg_match( '/load average: ([\d.]+)/', $uptime, $matches )
so that $matches[1] got the value of the first system load number.

Instead, since /proc/loadavg only has the system load numbers in it like this:
0.06 0.06 0.00 1/239 5581
the preg_match PHP function needed to be a little different, like this:
preg_match( '/([\d.]+)/', $loadRaw, $matches )
and the rest of the code worked just like it did when it used the output from the uptime command.

Now the logs are quiet again, SELinux is still standing guard and preventing access to utmp from anything running in Apache, and I can get back to whatever I was doing before this annoyance from SELinux popped up... well, if I can remember what that was. I think SELinux must be preventing access to my own short term memory now. Grrr.


Apparently, this will not be changed in SELinux's default policies per: https://bugzilla.redhat.com/show_bug.cgi?id=544145#c1

I reported this to the author(s) of ZoneMinder in case they care to fix it permanently in their product's PHP code. But, I'm sure this is a larger problem since there are many references floating around that describe executing the uptime command from PHP. ZoneMinder also has other SELinux conflicts, but they'll have to wait for another day... probably after I find a decent webcam for Linux that has a stable v4l compatible driver.

No comments: