Tip: mark your wireless mouse and USB dongle

We have several identical wireless rodents (Logitech M525, they are nice). This means we also have several identical USB receivers.

To prevent mixups, I’ve color-coded the USB receivers as well as the CE-markings on the mice, using different permanent markers:

Fixing corroded battery contacts on the Wii Fit Balance Board

I inadvertently left some Duracell alkaline batteries in the Balance Board. Sure enough, they were already starting to leak – damaging the battery contacts in the Balance Board.

It turns out there is a relatively easy way to remove the gunk from the leaky Duracells: they are alkaline batteries, so a mild acid (household vinegar) should do the trick. After disassembling the Balance Board, carefully remove the corroded metal contacts from the battery holder and drop them in a small jar with household vinegar:

Dip battery contacts in small glass jar with vinegarIMG_5323

Watch the corrosion dissolve; if needed, use a toothbrush or Q-tip to brush the last bits of gunk from the contacts. Rinse with water, and allow the contacts to properly dry before re-assembly.

P.S. It seems that Duracell batteries are quite prone to leaking – quality sure went downhill over the years. I’m replacing all of them to prevent further damage.

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:


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:


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


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 ;-)


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.


Making Cobbler work with SElinux on CentOS / RHEL 6

By default, Cobbler will not work properly on a CentOS / RHEL 6 machine with SElinux enabled. The easy way out is to disable SElinux entirely, but I prefer to write a custom policy instead – it is not that difficult.

The basic approach is this:

  1. Use Cobbler as you normally would (you will trigger several SElinux denials, so expect errors)
  2. Extract the relevant SElinux audit messages; convert them into a local policy
  3. Load your local policy
  4. Repeat steps 1..3 until everything works as expected

First attempt: the “cobbler import” command fails; rsync cannot access files on the mounted DVD ISO. Time to start writing a local policy!

The following command generates a basic SElinux policy from the SElinux audit messages:

  cat /var/log/audit/audit.log | audit2allow -l -v -m local > local.te

The resulting local.te file (ASCII, open it in your favorite editor) will list various items, some if which are not related to the Cobbler / Rsync operations. Edit the file to taste. Now, compile and load that policy:

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

Note: every invocation of “audit2allow -l” will overwrite your local.te policy file with new events since the last time a policy module was loaded. This is why you should keep backup copies of the previous versions so you can merge new events in with the existing ones.

In the end, you will end up with a policy in local.te like this:

module local 1.0;

require {
    type cobblerd_t;
    type cobbler_var_lib_t;
    type iso9660_t;
    type public_content_t;
    type rpm_var_lib_t;
    type rsync_etc_t;
    type security_t;
    type tmp_t;
    class capability { sys_module fsetid };
    class dir { add_name create getattr open read remove_name rmdir search write };
    class file { create getattr open read unlink write };
    class lnk_file create;
    class unix_dgram_socket create;

#============= cobblerd_t ==============
allow cobblerd_t cobbler_var_lib_t:lnk_file create;
allow cobblerd_t iso9660_t:dir { open read search getattr };
allow cobblerd_t iso9660_t:file { open read getattr };
allow cobblerd_t public_content_t:dir { write rmdir remove_name };
allow cobblerd_t rpm_var_lib_t:dir { open read search getattr write };
allow cobblerd_t rsync_etc_t:file create;
allow cobblerd_t security_t:dir read;
allow cobblerd_t self:capability fsetid;
allow cobblerd_t self:unix_dgram_socket create;
allow cobblerd_t tmp_t:dir { add_name create remove_name rmdir write };
allow cobblerd_t tmp_t:file { create getattr open read unlink write };