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).