ALIX3D2 Arrives

I’ve been hoping to upgrade my older ALIX2D3 router / firewall / wireless access point for a while now. While taking a few hours off from work over the holiday I surfed over to PCEngines and bought myself a Christmas present: a matching pair of ALIX3D2 boards and a Compex WLM200N5-23 MiniPCI card (802.11an) plus the necessary wires / cables / 5GHz antenna and enclosures etc.

Everything showed up in the mail today:

Unfortunately
one board arrived with minor damage to the CF socket. Bent pins suck:

I’m waiting to hear back from the folks over at PCEngines to see how they want to handle a repair / return. I really want to just bend it back and hope it works but I’m worried if I break it off they won’t accept a return. Glad I bought two so I still have one to play with in the meantime.

My next post should be about me finally complete Masters project, but likely it’ll be about building OE for this device 🙂

Update:
PC Engines support was super quick to respond. They gave me permission to try to bend the pin back myself and ensured me that if my attempted repair failed they’d still replace the board. The pin bent back into place easily enough. I’m hoping to do an install tomorrow to be sure the CF slot is functional.

Atom Based Home NFS

It’s been a while since I’ve posted any new content but that’s not because I haven’t been doing anything worthy of mention. During the few breaks I’ve had from my day job I took the time to replace my QNAP 419p NAS with a custom system to host NFS shares. Here’s just a quick laundry list of the parts I settled on after quite a bit of shopping.

My requirements for this system were really basic. All it does is host NFS shares and run rTorrent from time to time. There was no need to use a full desktop grade processor but I still wanted something x86 compatible with a good bit of ram and a PCI-E port so I could use a real hardware RAID card.

Motherboard

The Super Micro MBD-X7SPE-HF-D525 was a good fit. It has a sweet little Atom D525 soldered on to the board and it’s surprisingly quick (1.8GHz) though it’s no work horse. There’s only one 16x PCI-E port but that’s all I need. It supports up to 4G of ram though it’s pretty low end laptop memory. It also has two NICs so you can bond them for more throughput if you want to get fancy.

If you check out the Super Micro site you’ll see they advertise this board as having RAID on board. It’s still not hardware RAID though and since the RAID is done in firmware / driver the Atom processor on this board would have a very hard time keeping up with parity calculations under heavy usage. There’s plenty of literature out there about “fake RAID” so don’t be fooled.

RAID Card

I’ve had excellent luck with 3ware in the past so when they were bought out by LSI I was skeptical. Some of their older cards are still branded 3ware and I tracked down a 3ware 9650SE 8LPML on ebay for under 300 … since I couldn’t afford it new at close to $500 when I was looking 3 months back.

The Linux drivers for this card and the management software are still great. Setting up RAID 6 was easy though the card requires 5 drives to do this RAID level where theoretically it should only need 4.

RAM

The memory for the Super Micro board is practically free. I tracked down two 2G SODIMMs of Kingston ValueRAM for like $30. Not the fastest ram in the world but it works.

Disks

Buying 5 hard disks is not cheep. This is especially true if you want to get big drives and ones that will be fast enough to last. I went with 5 Western Digital AV-GP WD20EURS 2TB 3.0Gb/s drives. They’re nice and big, pretty fast and quiet. User reviews on sites like Newegg are a good way to check up on products before you buy. This one had particularly good reviews and so far they’ve been great. None were DOA as drives have a tendency to do. They’re also very quiet and run relatively cool.

Drive Enclosure

With this many drives it’s worth investing in an enclosure to hold them. You won’t have to rig fans on the drives to keep air moving over them and you’ll have the luxury of easy swapping if it something goes wrong and you need to swap out drives. There isn’t much available in this space so your choices are limited. I went with 2x ICY DOCK MB453SPF-B 3 in 2 enclosures.

I was a bit pissed when one of the enclosures showed up DOA but Newegg was pretty good about doing a quick exchange. It cost me a few extra bucks in shipping but it could have been worse … ::shrug::

Case

I had an old case from Lian Li and a small power supply that have been sitting in my basement unused for several years. Luckily the case it had the 4 5.25 bays that I need to hold these enclosures. Fitting enclosures into cases never goes as planned though.

The case is super nice but it had these little tabs that stuck out into the drive bays. These were intended to support individual 5.25 drives but they just got in the way of these enclosures. They were easy enough to remove with a saw and a file.

That’s about all there is to it. Setting up the RAID so I could boot Linux from the 3ware card was a bit of a pain and I wish I had documented the process. Setting it up through the firmware interface took some experimentation but it is possible. Then just install Debian and an NFS server and you’re done.

You do not have sufficient permissions to access this page

I’ve been working on a set of scripts to backup the wordpress instances on my server. While structuring these scripts I realized that I hadn’t structured my WP installs consistently. I had played around with using table prefixes and hosting multiple WP instances in a single database but eventually I just broke them out into unique databases for simplicity.

The table prefixes persisted however and while I was poking around I decided to rename the tables dropping the prefixes. What I didn’t count on is that some values in the usermeta and options tables are prepended with the table prefix from the wp-config.php. Without fixing up these values in the databse your site will function normally, but the admin interface will only show an error message:

You do not have sufficient permissions to access this page.

The database values that need to be fixed up are some entries in the meta_key column of the usermeta table and the option_name column of the options table. Let’s assume that your prefix is pre_, that you’ve already removed the prefix from your database and that you now want to fix up these values. The following SQL commands will remove your old prefix from these tables:

UPDATE usermeta SET meta_key = REPLACE(meta_key,'pre_','');
UPDATE options SET option_name = REPLACE(option_name,'pre_','');

References

http://www.tech-evangelist.com/2010/02/06/wordpress-error-sufficient-permissions/
http://wordpress.org/support/topic/changed-table-prefix-got-insufficient-permissions-error

Financial Site Password Policies

One of the many things I’ve had to do as part of transitioning to my new job is move my retirement savings (401k) over to a new provider. In this case I’ve been moving over to the Fidelity site. The security of financial web sites never fails to disappoint.

No I didn’t try some crazy SQL injection, CSS, or XSRF attack on the site (that would be illegal!). I just read their password policy:

  • Use 6 to 12 letters and/or numbers
  • Do not use one entire piece of personally identifiable information such as your Social Security number, telephone number, or date of birth. Instead, alter or disguise it (e.g., Jane212Smith)
  • Do not use more than 5 instances of a single number or letter, or easily recognized sequences (e.g., 12345 or 11111)
  • Do not use symbols, punctuation marks, or spaces (e.g., #,@, /, *, -.)

::Sigh:: 12 character max and only letters and numbers? Come on seriously? According to Microsoft [1] 14 characters is the recommended minimum for a password. But length isn’t the only factor. By excluding all special characters they effectively cut the character space in half.

Let’s think about this technically for a second though. Why would they need to place these restrictions on their customers security? Let’s assume the password is just another field in the Fidelity database because that’s exactly what it is. Typically there are two reasons to limit field length and content in a database:

  • efficiency: variable string length fields are very expensive
  • special characters can be a bit dangerous in that a scripting language or the SQL engine fronting the database might interpret the characters as commands

If however, Fidelity follows best practices for storing passwords in their database neither of these concerns apply because YOU SHOULD NEVER STORE THE PASSWORD DIRECTLY IN THE DATABASE! A hash of the password is what should be stored and the process of hashing addresses both of these concerns because it:

  • normalizes the password length
  • sanitizes any special characters

This last point can also be mitigated by using the proper and safe SQL commands available in any modern database engine.

So what these restrictions make me think is that the Fidelity site may actually be storing my password in plain text. That, or they’re just placing restrictions on my password strength arbitrarily which makes little sense.

Unfortunately this Fidelity site isn’t the worst offender that I’ve seen, and I don’t even analyze website security for a living. My experiences are limited only to the sites I’ve had to use over the years. Some time back around 2005 I had an account with a bank once that didn’t even let me change my password for their website if I wanted to. They set my password for their website when I established my pin for my ATM card! That’s right, my password for their website was a four digit number. I wrote them a letter pointing out the weakness in their password policy and I got back a form letter basically telling me to go away … so I did, and I took my money (totaling a whopping $2500) with me.

These are the people we trust with our life savings … Most of the web forums I have an account on fixed these problems back around 2007. Fixing something like this isn’t rocket science, just best practice.

UPDATE
After dialing into the phone system for Fidelity it became apparent that special characters are prohibited in passwords because their phone system authenticates users against the same database. It’s convenient, but touch-tone key pads just haven’t kept pace with keyboards 🙂 This also means that their passwords are probably case-insensitive too which nearly cuts the character space in half yet again. ::sigh:: balancing backward compatibility against security is an age old problem. You can look to Microsoft for a few of the biggest examples: the bazillion Windows users still surfing on IE6, the upcoming EOL for Windows XP etc. The Fidelity password strength issue isn’t anywhere near the scale of these examples but the principle holds.

[1]: http://www.microsoft.com/security/online-privacy/passwords-create.aspx

sVirt Simulation Demo

In my last post on this topic I gave a quick description of a simulation of the sVirt architecture. Talking about it is only half the work. In this post I’ll show it in action and interpret the output as it relates to the separation goals.

Building and Installing

After you clone the git repo from my last post you’ll have all of the source code and policy for the simulation. Typing make in the root of the tree should build both the policy and the simulation code. Install it with make install.

There are differences between different Linux distros and how they do their SELinux stuff. This was developed and tested on Debian Squeeze.

Interface

The simulation is a bit sparse so the interface is just a textual one. Run it on the console by running it as root:

svirt-sim

The simulation is run as root because we’re simulating a virtualization management stack like libvirt or xend and makes and manages mock VHDs in /var/lib/svirt-sim/images.

The initial output you’ll see just a prompt of two hashes ## and a message indicating you can get a list of commands by pressing ?. With these commands you can interactively perform actions typical for a virtualization stack: create, delete, start, stop and show information about virtual machines:

press ? for a list of commands
##:?
c : create a VM
d : delete a VM
h : start a VM
k : stop a VM
s : show objects and labels
q : quit

Creating VMs

First things first, we need to create two VMs. When we create a VM the svirt-sim process creates a VHD for it and allocates an MCS category for the mock QEMU instance (that we call not-qemu) that will be started when the VM is started. The first one we’ll create will do what we expect it to do: access it’s VHD file simulating disk access. We’ll call this VM ‘good-one’ since it’s well behaved. The second VM we’ll create will be the ‘bad-one’ and it will attempt to violate confinement and access VHDs belonging to the other VM. Here’s the output we’ll see:

##:c
what's the name of the VM?: good-one
what's the vm's disposition [good|bad]?: good
creating: /var/lib/svirt-sim/images/good-one.vhd
##:c
what's the name of the VM?: bad-one
what's the vm's disposition [good|bad]?: bad
creating: /var/lib/svirt-sim/images/bad-one.vhd

Now that we’ve created our VMs we can examine the internal state of the management stack by pressing ‘s’:

##:s
======================
VMs:
VM Name:        bad-one
  VHD Name:     /var/lib/svirt-sim/images/bad-one.vhd
  Disposition:  bad
  VM qemu PID   0
  VM Status:    Stopped
  mcs category:     s0:c850
  prev vhd context: (null)
VM Name:        good-one
  VHD Name:     /var/lib/svirt-sim/images/good-one.vhd
  Disposition:  good
  VM qemu PID   0
  VM Status:    Stopped
  mcs category:     s0:c440
  prev vhd context: (null)
======================
=============================
dumping security context list
  mcs: s0:c850
  mcs: s0:c440
=============================

We can also see the mock VHDs created by the management stack and examine their security context:

-rw-r-----. 1 root root unconfined_u:object_r:svirt_sim_image_t:s0:c0 0 Sep  3 23:27 bad-one.vhd
-rw-r-----. 1 root root unconfined_u:object_r:svirt_sim_image_t:s0:c0 0 Sep  3 23:27 good-one.vhd

We use the first category (c0) as the context for VMs that aren’t running. No VM should ever be run with this category so the VHD of a running VM should never be accessible to a not-qemu instance.

Running VMs

The VMs created above can be run by pressing ‘h’. Once they’re running press ‘s’ again to see the change in the internal state of the management stack. We’ll now see pid of the mock QEMU process started.

##:h
what's the name of the VM?: good-one
starting vm: good-one
security_start for vm with mcs: s0:c440
started child with pid 1298
##:h
what's the name of the VM?: bad-one
starting vm: bad-one
security_start for vm with mcs: s0:c850
started child with pid 1300
##:s
======================
VMs:
VM Name:        bad-one
  VHD Name:     /var/lib/svirt-sim/images/bad-one.vhd
  Disposition:  bad
  VM qemu PID   1300
  VM Status:    Running
  mcs category:     s0:c850
  prev vhd context: unconfined_u:object_r:svirt_sim_image_t:s0:c0
VM Name:        good-one
  VHD Name:     /var/lib/svirt-sim/images/good-one.vhd
  Disposition:  good
  VM qemu PID   1298
  VM Status:    Running
  mcs category:     s0:c440
  prev vhd context: unconfined_u:object_r:svirt_sim_image_t:s0:c0
======================
=============================
dumping security context list
  mcs: s0:c850
  mcs: s0:c440
=============================

Now that the simulated “VMs” are running we can view their contexts and those of their VHDs to be sure they match up to the internal state of the svirt-sim stack:

# ls -l /var/lib/svirt-sim/images
-rw-r-----. 1 root root system_u:object_r:mcs_server_image_t:s0:c850 0 Sep  3 23:27 bad-one.vhd
-rw-r-----. 1 root root system_u:object_r:mcs_server_image_t:s0:c440 1 Sep  3 23:28 good-one.vhd
ps auxZ | grep not-qemu
system_u:system_r:not_qemu_t:s0:c440 root 1298  0.0  0.1   1664   544 ?        Ss   23:28   0:00 /sbin/not-qemu --good --file=/var/lib/svirt-sim/images/good-one.vhd
system_u:system_r:not_qemu_t:s0:c850 root 1300  0.0  0.1   1696   544 ?        Ss   23:28   0:00 /sbin/not-qemu --bad --file=/var/lib/svirt-sim/images/bad-one.vhd

So far the output looks as we’d expect: the category assigned to the running not-qemu process matches the category of it’s VHD file.

Testing Confinement

Built in to this simulation is a simple confinement test. The not-qemu process has an option I call it’s disposition. If started with the option --good it will only attempt to access the VHD file it’s been assigned. If started with the --bad option then it will cycle through the directory containing all of the VHDs and it will attempt to access all of them. This is meant to simulate a malicious QEMU process reading the disk of another VM. Above we’ve started two VMs, one good and one bad. We can see the evidence of their behavior in the system logs.

The syslog on my system shows the following trace of accesses made by each of the not-qemu processes. I’ve removed the time stamps but the messages should be considered sequential.

/sbin/not-qemu[1298]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1298]: not-qemu with pid: 1298 still alive
/sbin/not-qemu[1300]: new file path: /var/lib/svirt-sim/images/.
/sbin/not-qemu[1300]: opening VHD file: /var/lib/svirt-sim/images/.
/sbin/not-qemu[1300]: open failed: Is a directory
/sbin/not-qemu[1298]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1298]: not-qemu with pid: 1298 still alive
/sbin/not-qemu[1300]: new file path: /var/lib/svirt-sim/images/..
/sbin/not-qemu[1300]: opening VHD file: /var/lib/svirt-sim/images/..
/sbin/not-qemu[1300]: open failed: Is a directory
/sbin/not-qemu[1298]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1298]: not-qemu with pid: 1298 still alive
/sbin/not-qemu[1300]: new file path: /var/lib/svirt-sim/images/bad-one.vhd
/sbin/not-qemu[1300]: opening VHD file: /var/lib/svirt-sim/images/bad-one.vhd
/sbin/not-qemu[1300]: not-qemu with pid: 1300 still alive
/sbin/not-qemu[1298]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1298]: not-qemu with pid: 1298 still alive
/sbin/not-qemu[1300]: new file path: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1300]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1300]: open failed: Permission denied
kernel: [ 2678.904913] type=1400 audit(1315107146.430:22): avc:  denied  { read write } for  pid=1300 comm="not-qemu" name="go
od-one.vhd" dev=sda3 ino=1444187 scontext=system_u:system_r:not_qemu_t:s0:c850 tcontext=system_u:object_r:mcs_server_image_t:s
0:c440 tclass=file
/sbin/not-qemu[1298]: opening VHD file: /var/lib/svirt-sim/images/good-one.vhd
/sbin/not-qemu[1298]: not-qemu with pid: 1298 still alive
/sbin/not-qemu[1300]: new file path: /var/lib/svirt-sim/images/.
/sbin/not-qemu[1300]: opening VHD file: /var/lib/svirt-sim/images/.
/sbin/not-qemu[1300]: open failed: Is a directory
/sbin/not-qemu[1298]: not-qemu with pid 1298 stopping on user request
/sbin/not-qemu[1298]: not-qemu with pid 1298 shutting down
/sbin/not-qemu[1300]: not-qemu with pid 1300 stopping on user request
/sbin/not-qemu[1300]: not-qemu with pid 1300 shutting down

There’s a bit of noise here in that ‘bad’ not-qemu instances loop through the images directory contents and don’t differentiate between files and directories so it will attempt to open and read the special directories . and .. which I’ll clean up in the future.

The important bits are that we can see the ‘bad’ not-qemu instance with PID 1300 attempt to access a VHD that doesn’t belong to it. This results in the operation failing and an AVC being displayed.

Conclusion

Whenever I’m writing SELinux policy I’m always looking for ways to test it. Policy analysis that proves a policy fulfills a specific security goal is the holy grail of security and this simulation isn’t policy analysis. Instead it’s just a simple simulation giving an example of what we’ve discussed using logical representation of the mlsconstrain statements in the SELinux MCS policy. Specifically, the category component of a processes context must dominate that of the object it’s accessing. We’ve represented this in logic previously now this simulation shows that the security server in the Linux kernel really does enforce this constraint.

Another interesting use of this simulation would be to use the real QEMU policy from the reference policy and a specifically crafted binary to push the limits of the policy. This binary could contain any number of known ways information can be leaked across QEMU instances. If anyone out there tries this I’d love to hear about it.

Debian Squeeze Bluetooth Headset

Working out of my “home office” these past two weeks I’ve found a few short comings in my setup. While on my first teleconference last week I spent an hour holding my cellphone to my head. Miserable. I never thought I’d miss a land line / speaker phone. Easy problem to solve though, just get a bluetooth headset on ebay. Top of the line will cost you $80 new.

Getting this to work with my cellphone was just a matter of pushing buttons. Nothing interesting. Getting it to work on my laptop (EliteBook 2560p running Debian Squeeze) was a bit of a trick. I’m a hopeless minimalist and I just want a simple GUI to manage my bluetooth devices and a new audio device to show up in alsamixer (1). The GUI can be either blueman or gnome-bluetooth. For the first time in a while I actually liked the gnome app better so that’s what I went with. Both worked fine for pairing the device.

Getting the Linux sound system to pick up the new devices was beyond me. The worst part was that all resources unearthed through web searches always pointed to stuff that didn’t work, or was a reference to the bluez wiki which has been down for 2 years. I tried a few times to hack a .asoundrc and just ended up feeling stupid. Unless you’ve got a day to burn don’t bother with this approach.

The solution I found was actually very simple once I found it. Turns out if you install pulseaudio it will do all the hard stuff for you (which I like). I only came to this solution after stumbling across a post on ask.debian.net: http://ask.debian.net/questions/how-to-make-bluetooth-headset-working-with-ekiga-in-squeeze. Nice fix that works perfectly. I had my bluetooth headset working on Squeeze in a matter of minutes after installing PulseAudio.

sVirt-like prototype

We’re getting close to the end of my on-going series exploring the SELinux mlsconstrain. Now that we’ve gone though and used some simple logic to reason through access control decisions it’s time for a simple and practical application.

Background

In my first post under my MastersProject tag I laid out some of the justification for why separating QEMU instances with SELinux policy in a Xen dom0 is important. To reiterate: my goal is to ensure that no qemu instance can read or write to the virtual disk belonging to another qemu instance. These are the same goals as the sVirt [1]
project which is responsible for the SELinux driver in libVirt [2]. We’ll use the same MLS categories we’ve been discussing to achieve the desired separation and we’ll validate our design with the logic previously discussed.

Requirements

A simulation like this requires a system with a functional SELinux policy (running in enforcing mode). We assume that the user is running in an unconfined domain as this is how my development system is configured.

Simulation Design

As always implementing a prototype/simulation first before starting in on the actual implementation is always a good idea. For our purposes this simulation will serve to familiarize us with the necessary bits of the SELinux API required to achieve our goals (will ease debugging later) and to prove to us through testing that our prototype can in fact fulfill the requirements. The simulation has three main parts:

SELinux-specific code

The central piece of this work is the code specific to managing SELinux labels on virtual disks (vhd files) and on running QEMU processes. We select a unique category for each running VM and the properties of these categories provide us with the separation we desire. There’s no primitive to perform this task explicitly so we generate unique category numbers using a naive algorithm.

Each time a QEMU instance is started a category number is generated at random and a list of allocated categories is searched to prevent duplicates. If the category is already in use, another number will be generated and the list searched again. This continues until an unused category is found. NOTE: This is the least efficient algorithm possible but for a simulation we only need a functional algorithm, not a perfect one. This would be a prime candidate for improvement in a real implementation.

The algorithm for generating unique categories I’ve described above relies on a test for equality. Remember our previous discussion of the mlsconstrain on read and write operations. Write permissions required that the subject and object labels be equal. Read permissions required that the subject label dominate the object label.

With this in mind it may seem that testing for equality alone wouldn’t be sufficient. But since an equality test is more strict than a test for dominance it is sufficient to test for equality only.

Finally the SELinux specific code must ensure that the unique category we’ve just generated is applied to the necessary subjects and objects. Firstly the VHD files belonging to the QEMU instance must be labeled with this category. Selecting the proper label, adding the category and changing the label of the VHD file requires the use of libselinux and the code can be found in the prototype sources at src/sec-selinux.c. We reserve the first category (c0) for VHD files that are currently not in use and ensure that no running QEMU processes ever get this category.

The QEMU process itself must also be labeled with the unique category when it is exec’d. Determining the label for the process is much the same as for the VHD file, but we must call the setexeccon function before forking the QEMU instance instead of directly manipulating the label on the running process.

While the man pages for these API calls are a great documentation source I’ve found that currently on Debian they are incomplete. Specifically functions like selinux_virtual_domain_context_path are undocumented in the man pages. A better source as of now can be found at the SELinux Wiki API page [3].

Mock QEMU Binary

Our prototype needs a binary to start up and test the limits of the confinement we’ve set up. We don’t intend to test the QEMU reference policy, only to test the limits of the confinement properties of the categories we’re assigning to each QEMU instance. As such we don’t want to use QEMU itself. Instead we want a simple binary that attempts to exceed its intended behavior.

As we’re aiming to limit access to the VHD files assigned to individual QEMU instances we want our mock QEMU to attempt to access the VHDs that don’t belong to it. We define two modes of operation for this program. First is what we term “good behavior” in which the process will only read and write to a file we specify on it’s command line. The second mode of operation we term “bad behavior” in which we specify a file on it’s command line again, but this time it will attempt to read and write to all files in that same directory.

To allow us to observe these fake QEMU instances at run-time I’ve added a number of syslog calls. These document the success or failure of attempted actions. Using this output we can observe the effectiveness of the protections offered by this system. This code is in the file: src/not-qemu.c

VM Driver

The final component is a text driven interface for manipulating the simulation. This component takes the place of the standard virtualization tool stack which creates, starts, stops and destroys VMs. We expose four primary actions the user may choose:

  1. Create VM: create internal representation of a VM including SELinux label and mock VHD file.
  2. Start VM: launch the mock QEMU process for a VM in the assigned SELinux domian.
  3. Stop VM: stop the mock QEMU process.
  4. Delete VM: free up the assigned SELinux category and mock VHD file for the specified VM.

With an interface like this the user can control the simulation explicitly. Tailing the output from syslog will allow the user to observe the behavior of the simulation in real time where they can judge for themselves whether or not the confinement is effective.

Policy

The policy for this simulation contains all of the necessary permissions for each component to function. There are also a number of permissions that are specific to the simulation. Any implementation directly in a tool stack won’t require any special permissions for SELinux users or groups as the stack will run as the system user in system role which is also the case for QEMU processes.

Our simulation is meant to be interactive and we assume that the user is unconfined. The user and role for the simulated qemu instances will be system_u and system_r respectively so some additional permissions are required by the simulation driver to allow changing the user and role label components when the qemu simulation is started and when labeling VHD files. This is simply a side effect of making the simulation interactive for the unconfined user.

The interesting parts are as follows:

allow mcs_server_t self:process { setexec };
allow mcs_server_t mcs_server_image_type:file { relabelfrom relabelto };

ifdef(`enable_mcs',`
        range_transition mcs_server_t mcs_server_image_t:file s0:c0;
')
mcs_server_manage_images(mcs_server_t)

seutil_read_default_contexts(mcs_server_t)
dev_read_rand(mcs_server_t)

You can see that we’ve defined two types, one for the driver (mcs_server_t) and one for the VHD files used by the simulated qemu instances (mcs_server_image_t). The server can manage the VHD files, it can read default contexts (required to use the libselinux API calls we need), and it can read from /dev/urandom which our category selection algorithm requires. The only nuance here is the range_transition which ensures that when the mcs_server_t type creates a new VHD file it is created with the proper context.

The permissions required for interaction between the mcs-server and the not-qemu instances is implemented as an interface in the mcs-server module (interface):

interface(`mcs_server_domain',`
        gen_require(`
                role system_r, unconfined_r;
                type mcs_server_t;
        ')

	type $1_t;
	domain_type($1_t)
	role system_r types $1_t;
	allow unconfined_r system_r;

	type $1_exec_t;
	files_type($1_exec_t)

        allow mcs_server_t $1_t:process { getattr getsched setsched signal signull sigkill };
	domtrans_pattern(mcs_server_t, $1_exec_t, $1_t)
	
        mcs_server_rw_images($1_t)

	# Only required in example where user directly invokes mcs-server.
        #   In actual implementation user will be system_u for source and
        #   destination domains so no exemption will be required.
	domain_user_exemption_target($1_t)
	role_transition unconfined_r $1_exec_t system_r;
')

This is a slightly strange pattern as the not-qemu module pretty much calls this one interface and that’s it. This allows the mcs-server to transition to the calling domain through an executable. It also allows the calling domain to read and write to read and write VHD files. There are two permissions at the end of the interface that are only required for our interactive simulation and they’ll be removed in a real implementation.

Installing

This simulation and the accompanying SELinux policy can be obtained from a public git treen on this server: git://twobit.us/svirt-sim.git. Just download it, build it and give it a try. Be sure to read the requirements above and be sure you’ve set all that up because there’s a lot of moving parts behind the scenes with the build system and stuff.

Conclusion

So that’s a brief description of a simulation implementing the sVirt design in an interactive prototype. It’s still very rough but has been extremely useful as a learning tool for myself. Next time I’ll do a walk through of the simulation and discuss some techniques we can use to be sure it’s functioning as expected.

References

1 sVirt Requirements Document: http://selinuxproject.org/page/Svirt_requirements_v1.0
2 SELinux sVirt confinement in libVirt: http://libvirt.org/drvqemu.html#securitysvirt
3 API Summary for libselinux: http://selinuxproject.org/page/LibselinuxAPISummary

EliteBook 2560p Intel 82579LM Debian Squeeze Install

Started with a new employer (Citrix) today. Naturally my first task of setting up a development system was more work than I wanted it to be. Turns out the EliteBook 2560p has Intel 83579LM network hardware and the Debian Squeeze e1000 driver predates it. Using ‘testing’ is always an option but not a very stable / appealing one.

The 2.6.38 kernel and drivers have been backported to squeeze so all that’s really needed is an installer with this kernel / drivers. I didn’t know until I’d burned a good half hour searching around the web that there are unofficial Squeeze installers complete with backports: http://cdimage.debian.org/cdimage/unofficial/backports/squeeze/. One of those images is all you’ll need to get Squeeze running on a system with Intel 82579LM network hardware.

Validating IP Addresses

UPDATE: Added terminating ‘$’ in ipv4 regex as noted in comment from raorn.

I’ve been working on a fix to a system script that passes around and manipulates IP addresses. With IPv6 becoming more prevalent this script must work with IPv6 addresses not just v4. While working on this and digging around the web I ran across some stuff that I think is worth sharing.

The first thing I always do when I’m working with a new data format is writing a script / function that can be used to validate it. Here’s what I came up with for IPv4 and IPv6.

IPv4 Regex

With IPv4 this pretty boring and can be done with a one line regular expression (regex) that’s all over the web. I clean things up a bit by using shell variables but the regex should be clear:

#!/bin/sh
QUAD="25[0-5]|2[0-4][0-9]|[0-1]?[0-9]?[0-9]"
is_ipv4 () {
    echo $1 | grep --silent "^(${QUAD})(.(${QUAD})){3}$"
    if [ $? -eq 0 ]; then
        return 1
    fi
    return 0
}

is_ipv4 $1
if [ $? -eq 1 ]; then
    exit 0
else
    echo "Invalid IPv4 address." >&2
    exit 1
fi

Nothing earth shattering.

IPv6 Regex

Working with IPv6 addresses is a bit more complex. To compensate for the larger addresses size when representing IPv6 addresses in text, the RFC recommends a canonical textual representation with rules that allow for compression (called “zero folding”). Addresses represented in this compressed format are more difficult to validate with just one regex and the regex is much longer:

#!/bin/sh
WORD="[0-9A-Fa-f]{1,4}"
# flat address, no compressed words
FLAT="^${WORD}(:${WORD}){7}$"
# ::'s compressions excluding beginning and end edge cases
COMP2="^(${WORD}:){1,1}(:${WORD}){1,6}$"
COMP3="^(${WORD}:){1,2}(:${WORD}){1,5}$"
COMP4="^(${WORD}:){1,3}(:${WORD}){1,4}$"
COMP5="^(${WORD}:){1,4}(:${WORD}){1,3}$"
COMP6="^(${WORD}:){1,5}(:${WORD}){1,2}$"
COMP7="^(${WORD}:){1,6}(:${WORD}){1,1}$"
# trailing :: edge case, includes case of only :: (all 0's)
EDGE_TAIL="^((${WORD}:){1,7}|:):$"
# leading :: edge case
EDGE_LEAD="^:(:${WORD}){1,7}$"
is_ipv6 () {
    echo $1 | grep --silent "(${FLAT})|(${COMP2})|(${COMP3})|(${COMP4})|(${COMP5})|(${COMP6})|(${COMP7})|(${EDGE_TAIL})|(${EDGE_LEAD})"
    if [ $? -eq 0 ]; then
        return 1
    fi
    return 0
}

is_ipv6 $1
if [ $? -eq 1 ]; then
    exit 0
else
    echo "Invalid IPv6 address: $1" >&2
    exit 1
fi

Folks on the web have got it right too and I definitely took a queue from Vernon Mauery. I got a bit caught up in the differences between addresses from RFC4291 and the recommendations in RFC5952. The prior allows for zero folding of single 16-bit 0 fields while the latter discourages this. As the “robustness principle” dictates this validation script will identify addresses with zero folded single 16-bit 0 fields as valid but tools producing addresses should not.

I haven’t taken on any of the weirdness that are mixed hexadecimal and dot decimal notations … those will remain for the interested reader.