version 3.12.40-1
This commit is contained in:
parent
2f9784a097
commit
243eb35ff7
@ -1,134 +0,0 @@
|
|||||||
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.
|
|
||||||
|
|
||||||
This is CVE-2015-2150 / XSA-120.
|
|
||||||
|
|
||||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
|
||||||
|
|
||||||
--- 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,
|
|
||||||
--- 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
|
|
||||||
--- 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;
|
|
||||||
+ struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
- 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;
|
|
||||||
+ 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
|
|
||||||
{
|
|
||||||
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 +101,18 @@ static int command_write(struct pci_dev
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ 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 +312,8 @@ static const struct config_field header_
|
|
||||||
{
|
|
||||||
.offset = PCI_COMMAND,
|
|
||||||
.size = 2,
|
|
||||||
+ .init = command_init,
|
|
||||||
+ .release = bar_release,
|
|
||||||
.u.w.read = command_read,
|
|
||||||
.u.w.write = command_write,
|
|
||||||
},
|
|
@ -1,7 +1,6 @@
|
|||||||
patches.rpmify/makefile-after_link.patch
|
patches.rpmify/makefile-after_link.patch
|
||||||
|
|
||||||
# security fixes
|
# security fixes
|
||||||
patches.xen/xsa120.patch
|
|
||||||
|
|
||||||
# should be included in 3.13
|
# should be included in 3.13
|
||||||
patches.xen/PCI-Add-x86_msi-msi_mask_irq-and-msix_mask_irq.patch
|
patches.xen/PCI-Add-x86_msi-msi_mask_irq-and-msix_mask_irq.patch
|
||||||
|
@ -1 +1 @@
|
|||||||
3.12.38
|
3.12.40
|
||||||
|
Loading…
Reference in New Issue
Block a user