Filtering SCSI commands
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 needed for 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 class. 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:
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".
Index entries for this article | |
---|---|
Kernel | SCSI/Command filtering |
Security | Linux kernel |