LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 1/2] xen-pciback: limit guest control of command register
@ 2015-03-11 13:51 Jan Beulich
2015-03-11 14:36 ` [Xen-devel] " David Vrabel
0 siblings, 1 reply; 2+ messages in thread
From: Jan Beulich @ 2015-03-11 13:51 UTC (permalink / raw)
To: David Vrabel, Boris Ostrovsky, Konrad Rzeszutek Wilk
Cc: xen-devel, linux-kernel
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@suse.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@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 | 58 ++++++++++++++++++++++------
3 files changed, 49 insertions(+), 13 deletions(-)
--- 4.0-rc3-xen-pciback.orig/drivers/xen/xen-pciback/conf_space.c
+++ 4.0-rc3-xen-pciback/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,
--- 4.0-rc3-xen-pciback.orig/drivers/xen/xen-pciback/conf_space.h
+++ 4.0-rc3-xen-pciback/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
--- 4.0-rc3-xen-pciback.orig/drivers/xen/xen-pciback/conf_space_header.c
+++ 4.0-rc3-xen-pciback/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;
+
+ if (!cmd)
+ return ERR_PTR(-ENOMEM);
- 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;
+ 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 +103,19 @@ 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 +315,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,
},
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [Xen-devel] [PATCH 1/2] xen-pciback: limit guest control of command register
2015-03-11 13:51 [PATCH 1/2] xen-pciback: limit guest control of command register Jan Beulich
@ 2015-03-11 14:36 ` David Vrabel
0 siblings, 0 replies; 2+ messages in thread
From: David Vrabel @ 2015-03-11 14:36 UTC (permalink / raw)
To: Jan Beulich, David Vrabel, Boris Ostrovsky, Konrad Rzeszutek Wilk
Cc: xen-devel, linux-kernel
On 11/03/15 13:51, Jan Beulich wrote:
> 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.
Applied to stable/for-linus-4.0 and tagged for stable, thanks.
David
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-03-11 14:36 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-11 13:51 [PATCH 1/2] xen-pciback: limit guest control of command register Jan Beulich
2015-03-11 14:36 ` [Xen-devel] " David Vrabel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).