SCSI command filtering has been the source of a number of Linux kernel
problems over the
years. In order to allow unprivileged users to have access to the commands
playing and burning CDs/DVDs, for example, the privilege requirement for
sending SCSI commands was lowered. But that, in turn, caused
problems where those unprivileged users could issue commands that were rather
dangerous, including some that could destroy devices entirely. That led
to a SCSI command whitelist being added to
the 2.6.8 kernel, way back in 2004.
That whitelisting approach has itself proved problematic to the point
where it was proposed for removal in 2006;
that proposal failed due to
strong opposition from Linus Torvalds. A privilege escalation vulnerability that was
found in late 2011 is a more recent example where the filtering wasn't
strict enough. Another hole has recently been discovered; Paolo Bonzini
has posted a patch set to close the hole, while also
addressing some other deficiencies in the SCSI command filtering.
The hole is CVE-2012-4542,
which is caused by SCSI commands that overlap between device classes. The
existing filter is set up to distinguish between devices opened for
read-only and those opened for read-write. But in some cases the same command
opcode will write to one kind of a device while it will read from some
other type. For example, the READ SUB-CHANNEL (0x42) command for an MMC
(CD or DVD) device is the same as the UNMAP command on a disk. So, using
the command to
request the sub-channel information for an audio CD would result in unmapping
logical blocks if sent to a disk.
There are other examples cited in the bug report and patches, but the basic
problem stems from the filtering not being aware of the destination device
Without that information, it is not possible to be sure which opcodes
are actually read-only and which will write to the device. The first part
of Bonzini's patch set restructures the filter table to associate the device
class and direction (read or write) with each command. He also changes
blk_verify_command() to use the device class and new table.
Another chunk of the patch set adds more entries to the table both to add
"rare & obsolete device types" and more whitelisted
commands for existing device types.
The last piece of the set (beyond a minor cleanup) adds the ability to turn
off the whitelist on a
per-device basis. Currently, a process can be given the
CAP_SYS_RAWIO capability, which will allow it to send any SCSI
command to any device. But that makes for fairly coarse-grained control
because it allows access to all devices. In addition,
CAP_SYS_RAWIO may be used to
elevate privileges, which may argue against its use.
Bonzini adds a new sysfs file,
/sys/block/<device>/unpriv_sgio, if it is set to '1', the
command filter will be bypassed for any file descriptor that is not
read-only. This can be
used to pass suitable file descriptors to trusted processes, as described
in the patch:
This is useful for virtualization, where some trusted guests would like
to send commands such as persistent reservations, but still the virtual
machine monitor should run with restricted permissions.
Other than some fairly minor quibbles from Tejun Heo, there have been no
comments on the patch set. Given that it fixes a CVE, it seems likely to
be picked up fairly soon (even if the CVE number in the patch subject may
get lost in translation to
Torvalds's Git tree). The other pieces of the patch set are perhaps less
important, but seem relatively uncontroversial.
Allowing non-root users to access hardware more or less directly is always
problematic from a security standpoint. There is always tension, though,
because users have strong ideas about how they want to use their systems.
The history of the SCSI command whitelist shows that it is rather difficult
to find the right balance between protecting the system and its hardware,
and making a system that is usable—at least for some definitions of "usable".
to post comments)