SELinux fix: allowing write to /var/lib/mod_security/

There’s a long-standing bug that prevents mod_security from writing to /var/lib/mod_security/.

According to Red Hat Bugzilla this bug should been fixed around May 2013, but it still exists – on fully patched CentOS 6.5. From /var/log/audit/audit.log:

type=AVC msg=audit(1411718594.811:7017): avc: denied { write } for pid=28144 comm="httpd" name="global.dir" \
dev=dm-0 ino=1577960 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file

type=AVC msg=audit(1411718594.812:7018): avc: denied { write } for pid=28144 comm="httpd" name="ip.dir" \
dev=dm-0 ino=1577962 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file

To relabel this directory with the proper “httpd_var_lib_t” context, run the following as root:

semanage fcontext -a -t httpd_var_lib_t "/var/lib/mod_security(/.*)?"
restorecon -Rv /var/lib/mod_security

Sending SMS notifications with Gnokii on CentOS 6

I had a couple of Huawei USB UMTS/HSPA sticks gathering dust, so I decided to use them for SMS notifications. Below is a quick set of notes I took during the experiment.

Configuration

My setup:

  • CentOS 6.3 (64-bit)
  • GNOKII 0.6.30 (available from EPEL)
  • Huawei E160G and Huawei E176
  • Valid SIM card, PIN entry disabled

Plug in the USB stick, watch /var/log/messages. You should see something like this:

Jan 19 23:23:47 hal kernel: usb 2-2: new high speed USB device number 13 using ehci_hcd
Jan 19 23:23:48 hal kernel: usb 2-2: New USB device found, idVendor=12d1, idProduct=1003
Jan 19 23:23:48 hal kernel: usb 2-2: New USB device strings: Mfr=2, Product=1, SerialNumber=0
Jan 19 23:23:48 hal kernel: usb 2-2: Product: HUAWEI Mobile
Jan 19 23:23:48 hal kernel: usb 2-2: Manufacturer: HUAWEI Technology
Jan 19 23:23:48 hal kernel: usb 2-2: configuration #1 chosen from 1 choice
Jan 19 23:23:48 hal kernel: scsi36 : SCSI emulation for USB Mass Storage devices
Jan 19 23:23:48 hal kernel: usb 2-2: USB disconnect, device number 13
Jan 19 23:23:54 hal kernel: usb 2-2: new high speed USB device number 14 using ehci_hcd
Jan 19 23:23:54 hal kernel: usb 2-2: New USB device found, idVendor=12d1, idProduct=1003
Jan 19 23:23:54 hal kernel: usb 2-2: New USB device strings: Mfr=2, Product=1, SerialNumber=0
Jan 19 23:23:54 hal kernel: usb 2-2: Product: HUAWEI Mobile
Jan 19 23:23:54 hal kernel: usb 2-2: Manufacturer: HUAWEI Technology
Jan 19 23:23:54 hal kernel: usb 2-2: configuration #1 chosen from 1 choice
Jan 19 23:23:54 hal kernel: option 2-2:1.0: GSM modem (1-port) converter detected
Jan 19 23:23:54 hal kernel: usb 2-2: GSM modem (1-port) converter now attached to ttyUSB0
Jan 19 23:23:54 hal kernel: option 2-2:1.1: GSM modem (1-port) converter detected
Jan 19 23:23:54 hal kernel: usb 2-2: GSM modem (1-port) converter now attached to ttyUSB1
Jan 19 23:23:54 hal kernel: scsi39 : SCSI emulation for USB Mass Storage devices
Jan 19 23:23:54 hal kernel: scsi40 : SCSI emulation for USB Mass Storage devices
Jan 19 23:23:55 hal kernel: scsi 39:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
Jan 19 23:23:55 hal kernel: scsi 40:0:0:0: Direct-Access     HUAWEI   MMC Storage      2.31 PQ: 0 ANSI: 2
Jan 19 23:23:55 hal kernel: sr1: scsi-1 drive
Jan 19 23:23:55 hal kernel: sr 39:0:0:0: Attached scsi generic sg3 type 5
Jan 19 23:23:55 hal kernel: sd 40:0:0:0: Attached scsi generic sg4 type 0
Jan 19 23:23:55 hal kernel: sd 40:0:0:0: [sdc] Attached SCSI removable disk

Each Huawei sticks presents itself as 2 separate USB modems: /dev/ttyUSB0 and /dev/ttyUSB1. I will use /dev/ttyUSB1 since SMS notifications are apparently only sent to the second port. The Micro-SD slot is reported as a SCSI device – not used here.

Now it’s time to configure Gnokii. I’ll send SMS as root, so I created directories under /root:

$ mkdir -p /root/.config/gnokii
$ mkdir -p /root/.cache/gnokii

Copy the default configuration file from /etc/gnokiirc to /root/.config/gnokii/config and add the following section:

# Huawei USB Stick
[phone_huawei]
model = AT
port = /dev/ttyUSB1
connection = serial

Issue a Gnokii command to verify that it works:

$ gnokii --phone huawei --identify
GNOKII Version 0.6.30
IMEI         : 333444555666777
Manufacturer : huawei
No flags section in the config file.
Model        : E176
Product name : E176
Revision     : 11.126.02.01.55

Sending SMS

OK, now for the real test – sending an SMS:

$ echo "SMS from Huawei" | gnokii --sendsms +31612341234 -r

If the SMS was sent correctly, gnokii exits with status 0. You can check that using the $? variable in your shell.

Receiving SMS

Incoming SMS are saved on the SIM-card memory, in memory slots starting at 0 (zero). To read the first (oldest) received message:

$ gnokii --phone huawei --getsms SM 0

The next one can be read using:

$ gnokii --phone huawei --getsms SM 1

… and so on.

Once you processed a message, you can delete it from the SIM-card:

$ gnokii --phone huawei --deletesms SM 1

There’s a lot of fun to be had with this setup – using simple SMS.

For interactive viewing of incoming SMS, use:

$ gnokii --phone huawei --smsreader

This will show new messages immediately.

Wrap-up

There’s lots more information to be found on the Gnokii Wiki.

My Huawei E160G turns out to have a SIM-lock on it. It would error out on most requests until I inserted a SIM of the correct network. Not all documented commands work:

$ gnokii --phone huawei --getlocksinfo
GNOKII Version 0.6.30
Error: Command called isn't implemented in model.

This makes troubleshooting quite a bit harder…

Nagios alerting

Next on my list is integration with Nagios – this is fairly simple; set up a Host Notification and Service Notification command that echoes a message to Gnokii. Voila: SMS alerting for Nagios ;-)

Process incoming SMS

Incoming SMS can be read using “gnokii --getsms“, but “gnokii-smsd” is a better option. It polls the USB modem regularly, and stores received messages in a database (PostgreSQL or MySQL). This makes it quite easy to use SMS from your own applications.

Have fun!

SELinux context for website with FTP access

So, you have decided to leave SELinux enabled. Congratulations, you have just taken a major step in securing your Internet-facing system.

Let’s say you are hosting a website that needs to be updated using FTP. By default, webserver content is labeled as:

httpd_sys_content_t

This context prevents you from updating files using the FTP server. If both HTTP (Apache) and FTP (vsftpd) access is needed, the SELinux context should be:

public_content_rw_t

You can either run “chcon” to temporarily fix this, or make the changes permanent by adding a proper local SELinux rule:

semanage fcontext -a -t public_content_rw_t "/var/www/html(/.*)?"
restorecon -Rv /var/www/html

Replace “/var/www/html” by your actual DocumentRoot as defined in Apache. The “semanage” command merely adds the rule to the SELinux database. The “restorecon” command performs the actual relabeling of your files.

Verify your changes using “ls -lZ”:

[root@webserver www]# ls -lZ
drwxr-sr-x. ed www unconfined_u:object_r:httpd_sys_content_t:s0 cgi-bin
drwxr-sr-x. ed www unconfined_u:object_r:httpd_sys_content_t:s0 error
drwxr-sr-x. ed www unconfined_u:object_r:public_content_rw_t:s0 html
drwxr-sr-x. ed www unconfined_u:object_r:httpd_sys_content_t:s0 icons

Done!

Workaround for Nagios check_linux_raid failure in RHEL / CentOS 6.2

I recently stumbled upon another Nagios plugin that no longer works with SELinux under RHEL / CentOS 6.2: check_linux_raid.

Just like the check_disk plugin, it has the nagios_checkdisk_plugin_exec_t SELinux type. As of May 2012, this problem has not yet been fixed.

The workaround is simple, as with the check_disk plugin:

chcon -t nagios_unconfined_plugin_exec_t /usr/lib64/nagios/plugins/check_linux_raid

Or, for 32-bit systems:

chcon -t nagios_unconfined_plugin_exec_t /usr/lib/nagios/plugins/check_linux_raid

PNP4Nagios with SElinux on CentOS / RHEL 6

PNP4Nagios is commonly used to add performance graphs to a Nagios installation.

For additional security, SElinux is enabled on the monitoring host. There is no standard SElinux policy for applications like PNP4Nagios, so we need to develop a custom policy. This sounds harder than it actually is:

  • Run the software as you normally would (SElinux will interfere, so prepare for errors)
  • Extract audit messages and use them to create or update a local SElinux policy for the software
  • Repeat until everything works

In this example, I am running Nagios 3.2.3 with PNP4Nagios 0.6.16 on EL6, 64-bit.

After configuring Nagios and PNP4Nagios integration in Synchronous Mode (see documentation), I noticed that PNP4Nagios is not logging any performance data to /var/lib/pnp4nagios/.

Normally, PNP4Nagios should automatically create directories and files under /var/lib/pnp4nagios as performance data is received by Nagios. This smells of an SElinux issue, so check /var/log/audit/audit.log for suspicious messages. Sure enough, several audit messages have been logged. They look like this:

type=AVC msg=audit(1329129875.344:198212): avc:  denied  { getattr } for  pid=26692 comm="process_perfdat" \
    path="/var/lib/pnp4nagios/orac/Root_Partition.xml.26692" dev=dm-0 ino=1444378 \
    scontext=unconfined_u:system_r:nagios_t:s0 tcontext=unconfined_u:object_r:var_lib_t:s0 tclass=file
type=SYSCALL msg=audit(1329129875.344:198212): arch=c000003e syscall=5 success=no exit=-13 a0=3 a1=25440a0 \
    a2=25440a0 a3=0 items=0 ppid=26691 pid=26692 auid=0 uid=498 gid=498 euid=498 suid=498 fsuid=498 egid=498 \
    sgid=498 fsgid=498 tty=(none) ses=14942 comm="process_perfdat" exe="/usr/bin/perl" subj=unconfined_u:system_r:nagios_t:s0 key=(null)

Create a policy

You can run the “audit2allow” command (part of the policycoreutils-python RPM) to display suggested policy improvements based on the audit log:

audit2allow -a

The output can be saved in a file, for example local_nagios.te:

grep nagios_t /var/log/audit/audit.log | audit2allow -l -v -m local_nagios > local_nagios.te

This generates an output file suitable for compiling into a custom SElinux module.

Note: ALWAYS prefix the policy name with something like local_ to prevent overwriting system policies!

Test and refine the policy

Compile and load the SElinux policy module:

checkmodule -M -m -o local_nagios.mod local_nagios.te
semodule_package -o local_nagios.pp -m local_nagios.mod
semodule -v -i local_nagios.pp

Note: The above tools can be found in the checkpolicy and policycoreutils RPMs.

Re-run the software and check for SElinux audit messages. New issues can be captured and translated into a new policy:

grep nagios_t /var/log/audit/audit.log | audit2allow -l -v -m local_nagios > local_nagios.te_NEW

Merge the new results (in local_nagios.te_NEW) with your existing policy (in local_nagios.te). Compile and reload the module.

Lather, rinse, repeat ;-)

Results

After some iterations, your local_nagios.te file will look something like this:

module local_nagios 1.0;

require {
    type nagios_t;
    type var_log_t;
    type var_lib_t;
    class dir { write create add_name remove_name };
    class file { create getattr ioctl lock open read rename unlink write };
}

#============= nagios_t ==============
allow nagios_t var_lib_t:dir { add_name create remove_name write };
allow nagios_t var_lib_t:file { create getattr ioctl lock open read rename unlink write };
allow nagios_t var_log_t:file { read rename unlink };

If all is well, the audit.log should not show any new messages for nagios_t:

clear;tail -f /var/log/audit/audit.log |grep nagios_t

Note: The new SElinux policy will survive reboots; it is automatically copied to /etc/selinux/targeted/modules/active/modules/local_nagios.pp.

Enjoy!