[kernel/f21] CVE-2015-2150 xen: NMIs triggerable by guests (rhbz 1196266 1200397)

Josh Boyer jwboyer at fedoraproject.org
Wed Mar 11 15:48:01 UTC 2015


commit af400aec620b253529191412eb0ba96e64dccd67
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date:   Wed Mar 11 10:19:12 2015 -0400

    CVE-2015-2150 xen: NMIs triggerable by guests (rhbz 1196266 1200397)

 kernel.spec                                        |   7 +
 ...k-limit-guest-control-of-command-register.patch | 156 +++++++++++++++++++++
 2 files changed, 163 insertions(+)
---
diff --git a/kernel.spec b/kernel.spec
index d750a34..85c5689 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -664,6 +664,9 @@ Patch26161: Input-synaptics-re-route-tracksticks-buttons-on-the-.patch
 Patch26162: Input-synaptics-remove-X1-Carbon-3rd-gen-from-the-to.patch
 Patch26163: Input-synaptics-remove-X250-from-the-topbuttonpad-li.patch
 
+#CVE-2015-2150 rhbz 1196266 1200397
+Patch26165: xen-pciback-limit-guest-control-of-command-register.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1433,6 +1436,9 @@ ApplyPatch Input-synaptics-re-route-tracksticks-buttons-on-the-.patch
 ApplyPatch Input-synaptics-remove-X1-Carbon-3rd-gen-from-the-to.patch
 ApplyPatch Input-synaptics-remove-X250-from-the-topbuttonpad-li.patch
 
+#CVE-2015-2150 rhbz 1196266 1200397
+ApplyPatch xen-pciback-limit-guest-control-of-command-register.patch
+
 %if 0%{?aarch64patches}
 ApplyPatch kernel-arm64.patch
 %ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does.
@@ -2304,6 +2310,7 @@ fi
 #                                    ||     ||
 %changelog
 * Wed Mar 11 2015 Josh Boyer <jwboyer at fedoraproject.org>
+- CVE-2015-2150 xen: NMIs triggerable by guests (rhbz 1196266 1200397)
 - Patch series to fix Lenovo *40 and Carbon X1 touchpads (rhbz 1200777 1200778)
 
 * Tue Mar 10 2015 Josh Boyer <jwboyer at fedoraproject.org>
diff --git a/xen-pciback-limit-guest-control-of-command-register.patch b/xen-pciback-limit-guest-control-of-command-register.patch
new file mode 100644
index 0000000..8760046
--- /dev/null
+++ b/xen-pciback-limit-guest-control-of-command-register.patch
@@ -0,0 +1,156 @@
+From: Jan Beulich <JBeulich at suse.com>
+Date: Wed, 11 Mar 2015 13:51:17 +0000
+Subject: [PATCH] xen-pciback: limit guest control of command register
+
+Otherwise the guest can abuse that control to cause e.g. PCIe
+Unsupported Request responses (by disabling memory and/or I/O decoding
+and subsequently causing [CPU side] accesses to the respective address
+ranges), which (depending on system configuration) may be fatal to the
+host.
+
+Note that to alter any of the bits collected together as
+PCI_COMMAND_GUEST permissive mode is now required to be enabled
+globally or on the specific device.
+
+This is CVE-2015-2150 / XSA-120.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+---
+ drivers/xen/xen-pciback/conf_space.c        |  2 +-
+ drivers/xen/xen-pciback/conf_space.h        |  2 +
+ drivers/xen/xen-pciback/conf_space_header.c | 61 +++++++++++++++++++++++------
+ 3 files changed, 51 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
+index 46ae0f9f02ad..75fe3d466515 100644
+--- a/drivers/xen/xen-pciback/conf_space.c
++++ b/drivers/xen/xen-pciback/conf_space.c
+@@ -16,7 +16,7 @@
+ #include "conf_space.h"
+ #include "conf_space_quirks.h"
+ 
+-static bool permissive;
++bool permissive;
+ module_param(permissive, bool, 0644);
+ 
+ /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
+diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h
+index e56c934ad137..2e1d73d1d5d0 100644
+--- a/drivers/xen/xen-pciback/conf_space.h
++++ b/drivers/xen/xen-pciback/conf_space.h
+@@ -64,6 +64,8 @@ struct config_field_entry {
+ 	void *data;
+ };
+ 
++extern bool permissive;
++
+ #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
+ 
+ /* Add fields to a device - the add_fields macro expects to get a pointer to
+diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c
+index c5ee82587e8c..2d7369391472 100644
+--- a/drivers/xen/xen-pciback/conf_space_header.c
++++ b/drivers/xen/xen-pciback/conf_space_header.c
+@@ -11,6 +11,10 @@
+ #include "pciback.h"
+ #include "conf_space.h"
+ 
++struct pci_cmd_info {
++	u16 val;
++};
++
+ struct pci_bar_info {
+ 	u32 val;
+ 	u32 len_val;
+@@ -20,22 +24,36 @@ struct pci_bar_info {
+ #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
+ #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
+ 
+-static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
++/* Bits guests are allowed to control in permissive mode. */
++#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
++			   PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
++			   PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
++
++static void *command_init(struct pci_dev *dev, int offset)
+ {
+-	int i;
+-	int ret;
+-
+-	ret = xen_pcibk_read_config_word(dev, offset, value, data);
+-	if (!pci_is_enabled(dev))
+-		return ret;
+-
+-	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+-		if (dev->resource[i].flags & IORESOURCE_IO)
+-			*value |= PCI_COMMAND_IO;
+-		if (dev->resource[i].flags & IORESOURCE_MEM)
+-			*value |= PCI_COMMAND_MEMORY;
++	struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
++	int err;
++
++	if (!cmd)
++		return ERR_PTR(-ENOMEM);
++
++	err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
++	if (err) {
++		kfree(cmd);
++		return ERR_PTR(err);
+ 	}
+ 
++	return cmd;
++}
++
++static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
++{
++	int ret = pci_read_config_word(dev, offset, value);
++	const struct pci_cmd_info *cmd = data;
++
++	*value &= PCI_COMMAND_GUEST;
++	*value |= cmd->val & ~PCI_COMMAND_GUEST;
++
+ 	return ret;
+ }
+ 
+@@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+ {
+ 	struct xen_pcibk_dev_data *dev_data;
+ 	int err;
++	u16 val;
++	struct pci_cmd_info *cmd = data;
+ 
+ 	dev_data = pci_get_drvdata(dev);
+ 	if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
+@@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+ 		}
+ 	}
+ 
++	cmd->val = value;
++
++	if (!permissive && (!dev_data || !dev_data->permissive))
++		return 0;
++
++	/* Only allow the guest to control certain bits. */
++	err = pci_read_config_word(dev, offset, &val);
++	if (err || val == value)
++		return err;
++
++	value &= PCI_COMMAND_GUEST;
++	value |= val & ~PCI_COMMAND_GUEST;
++
+ 	return pci_write_config_word(dev, offset, value);
+ }
+ 
+@@ -282,6 +315,8 @@ static const struct config_field header_common[] = {
+ 	{
+ 	 .offset    = PCI_COMMAND,
+ 	 .size      = 2,
++	 .init      = command_init,
++	 .release   = bar_release,
+ 	 .u.w.read  = command_read,
+ 	 .u.w.write = command_write,
+ 	},
+-- 
+2.1.0
+


More information about the scm-commits mailing list