CVE-2013-2852: b43 wireless driver
The b43 driver reports error strings that can be interpreted as format
strings. Under normal conditions, this is not a problem, but it is
possible for the "fwpostfix" module parameter to change the filenames
used to fetch firmware. When such a file is not found, the filename
will be processed as a format string. This flaw could potentially allow
escalation from uid-0 to ring-0, so except for certain environments,
it is not too serious.
If b43 hardware is available, this should show itself easily. I don't have
any available for testing, but it seems it would show itself like this:
# rmmod b43
# modprobe b43 fwpostfix=AA%xBB
...
# dmesg
...
b43-0 ERROR: Firmware file "b43AAdeff80ccBB/a0g1bsinitvals5.fw" not found
Using %n instead of %x would lead to exciting crashes. :)
It has been fixed in the upstream wireless tree:
http://git.kernel.org/cgit/linux/kernel/git/linville/wireless.git/commit/?id=9538cbaab6e8b8046039b4b2eb6c9d614dc782bd
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 6dd07e2..a95b77a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2458,7 +2458,7 @@ static void b43_request_firmware(struct work_struct *work)
for (i = 0; i < B43_NR_FWTYPES; i++) {
errmsg = ctx->errors[i];
if (strlen(errmsg))
- b43err(dev->wl, errmsg);
+ b43err(dev->wl, "%s", errmsg);
}
b43_print_fw_helptext(dev->wl, 1);
goto out;
CVE-2013-2851: block layer
The block layer uses the "disk_name" field as a format
string in a number of places. While this is normally not a problem due
to how disk names are created (statically or incrementally), there
is currently at least one way to define nearly arbitrary names via
md. Instead of filtering md, this should be fixed within the kernel's
interfaces. This flaw could potentially allow escalation from uid-0 to
ring-0, so except for certain environments, it is not too serious.
The test case is trivial:
# echo md_%x.%x.%x.%x > /sys/module/md_mod/parameters/new_array
# ls /dev/md_*
/dev/md_c12cc370.df66d800.df66d80c.c13da45b
Using %n instead of %x leads to exciting crashes. :)
The fix has been sent upstream:
http://marc.info/?l=linux-kernel&m=137055204522556&w=2
---
block/genhd.c | 2 +-
drivers/block/nbd.c | 3 ++-
drivers/scsi/osd/osd_uld.c | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c
index 20625ee..cdeb527 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -512,7 +512,7 @@ static void register_disk(struct gendisk *disk)
ddev->parent = disk->driverfs_dev;
- dev_set_name(ddev, disk->disk_name);
+ dev_set_name(ddev, "%s", disk->disk_name);
/* delay uevents, until we scanned partition table */
dev_set_uevent_suppress(ddev, 1);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 037288e..46b35f7 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -714,7 +714,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
else
blk_queue_flush(nbd->disk->queue, 0);
- thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name);
+ thread = kthread_create(nbd_thread, nbd, "%s",
+ nbd->disk->disk_name);
if (IS_ERR(thread)) {
mutex_lock(&nbd->tx_lock);
return PTR_ERR(thread);
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 0fab6b5..9d86947 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -485,7 +485,7 @@ static int osd_probe(struct device *dev)
oud->class_dev.class = &osd_uld_class;
oud->class_dev.parent = dev;
oud->class_dev.release = __remove;
- error = dev_set_name(&oud->class_dev, disk->disk_name);
+ error = dev_set_name(&oud->class_dev, "%s", disk->disk_name);
if (error) {
OSD_ERR("dev_set_name failed => %d\n", error);
goto err_put_cdev;
--
1.7.9.5
With the above fixes, a series of additional format string related clean
ups has also been sent upstream:
http://marc.info/?l=linux-kernel&m=137055207522563&w=2