]> code.ossystems Code Review - openembedded-core.git/blob
5bfcf5e166b17e0e398ea349066e99d36f0edada
[openembedded-core.git] /
1 Upstream-Status: Backport
2
3 Signed-off-by: Kai Kang <kai.kang@windriver.com>
4
5 From c25bbf1545a53ac051f9e51d4140e397660c10ae Mon Sep 17 00:00:00 2001
6 From: Jan Beulich <jbeulich@suse.com>
7 Date: Tue, 2 Jun 2015 15:07:01 +0000
8 Subject: xen/pt: unknown PCI config space fields should be read-only
9 Bug-Debian: http://bugs.debian.org/787547
10
11 ... by default. Add a per-device "permissive" mode similar to pciback's
12 to allow restoring previous behavior (and hence break security again,
13 i.e. should be used only for trusted guests).
14
15 This is part of XSA-131.
16
17 Signed-off-by: Jan Beulich <jbeulich@suse.com>
18 Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
19 Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>)
20 ---
21  hw/xen/xen_pt.c             | 32 +++++++++++++++++++++++++++++---
22  hw/xen/xen_pt.h             |  2 ++
23  hw/xen/xen_pt_config_init.c |  4 ++++
24  3 files changed, 35 insertions(+), 3 deletions(-)
25
26 diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
27 index 8923582..9afcda8 100644
28 --- a/hw/xen/xen_pt.c
29 +++ b/hw/xen/xen_pt.c
30 @@ -239,6 +239,7 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
31      XenPTReg *reg_entry = NULL;
32      uint32_t find_addr = addr;
33      XenPTRegInfo *reg = NULL;
34 +    bool wp_flag = false;
35  
36      if (xen_pt_pci_config_access_check(d, addr, len)) {
37          return;
38 @@ -278,6 +279,10 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
39  
40      /* pass directly to the real device for passthrough type register group */
41      if (reg_grp_entry == NULL) {
42 +        if (!s->permissive) {
43 +            wb_mask = 0;
44 +            wp_flag = true;
45 +        }
46          goto out;
47      }
48  
49 @@ -298,12 +303,15 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
50              uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
51              uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
52              uint8_t *ptr_val = NULL;
53 +            uint32_t wp_mask = reg->emu_mask | reg->ro_mask;
54  
55              valid_mask <<= (find_addr - real_offset) << 3;
56              ptr_val = (uint8_t *)&val + (real_offset & 3);
57 -            if (reg->emu_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) {
58 -                wb_mask &= ~((reg->emu_mask
59 -                              >> ((find_addr - real_offset) << 3))
60 +            if (!s->permissive) {
61 +                wp_mask |= reg->res_mask;
62 +            }
63 +            if (wp_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) {
64 +                wb_mask &= ~((wp_mask >> ((find_addr - real_offset) << 3))
65                               << ((len - emul_len) << 3));
66              }
67  
68 @@ -347,6 +355,16 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
69          } else {
70              /* nothing to do with passthrough type register,
71               * continue to find next byte */
72 +            if (!s->permissive) {
73 +                wb_mask &= ~(0xff << ((len - emul_len) << 3));
74 +                /* Unused BARs will make it here, but we don't want to issue
75 +                 * warnings for writes to them (bogus writes get dealt with
76 +                 * above).
77 +                 */
78 +                if (index < 0) {
79 +                    wp_flag = true;
80 +                }
81 +            }
82              emul_len--;
83              find_addr++;
84          }
85 @@ -358,6 +376,13 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
86      memory_region_transaction_commit();
87  
88  out:
89 +    if (wp_flag && !s->permissive_warned) {
90 +        s->permissive_warned = true;
91 +        xen_pt_log(d, "Write-back to unknown field 0x%02x (partially) inhibited (0x%0*x)\n",
92 +                   addr, len * 2, wb_mask);
93 +        xen_pt_log(d, "If the device doesn't work, try enabling permissive mode\n");
94 +        xen_pt_log(d, "(unsafe) and if it helps report the problem to xen-devel\n");
95 +    }
96      for (index = 0; wb_mask; index += len) {
97          /* unknown regs are passed through */
98          while (!(wb_mask & 0xff)) {
99 @@ -824,6 +849,7 @@ static void xen_pt_unregister_device(PCIDevice *d)
100  
101  static Property xen_pci_passthrough_properties[] = {
102      DEFINE_PROP_PCI_HOST_DEVADDR("hostaddr", XenPCIPassthroughState, hostaddr),
103 +    DEFINE_PROP_BOOL("permissive", XenPCIPassthroughState, permissive, false),
104      DEFINE_PROP_END_OF_LIST(),
105  };
106  
107 diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
108 index f9795eb..4bba559 100644
109 --- a/hw/xen/xen_pt.h
110 +++ b/hw/xen/xen_pt.h
111 @@ -197,6 +197,8 @@ struct XenPCIPassthroughState {
112  
113      PCIHostDeviceAddress hostaddr;
114      bool is_virtfn;
115 +    bool permissive;
116 +    bool permissive_warned;
117      XenHostPCIDevice real_device;
118      XenPTRegion bases[PCI_NUM_REGIONS]; /* Access regions */
119      QLIST_HEAD(, XenPTRegGroup) reg_grps;
120 diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
121 index 19f926b..f3cf069 100644
122 --- a/hw/xen/xen_pt_config_init.c
123 +++ b/hw/xen/xen_pt_config_init.c
124 @@ -101,6 +101,10 @@ static uint32_t get_throughable_mask(const XenPCIPassthroughState *s,
125  {
126      uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask);
127  
128 +    if (!s->permissive) {
129 +        throughable_mask &= ~reg->res_mask;
130 +    }
131 +
132      return throughable_mask & valid_mask;
133  }
134  
135 -- 
136 2.1.4
137