mirror of
https://git.freebsd.org/ports.git
synced 2025-07-18 01:39:16 -04:00
xen: update to 4.5.2
...and add XSA-156. Sponsored by: Citrix Systems R&D Reviewed by: bapt Differential Revision: https://reviews.freebsd.org/D4150
This commit is contained in:
parent
9b9d8e5f9c
commit
9da11fae56
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=401564
26 changed files with 139 additions and 1626 deletions
|
@ -2,12 +2,11 @@
|
||||||
|
|
||||||
PORTNAME= xen
|
PORTNAME= xen
|
||||||
PKGNAMESUFFIX= -kernel
|
PKGNAMESUFFIX= -kernel
|
||||||
PORTVERSION= 4.5.1
|
PORTVERSION= 4.5.2
|
||||||
PORTREVISION= 1
|
|
||||||
CATEGORIES= emulators
|
CATEGORIES= emulators
|
||||||
MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/
|
MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/
|
||||||
|
|
||||||
MAINTAINER= ports@FreeBSD.org
|
MAINTAINER= royger@FreeBSD.org
|
||||||
COMMENT= Hypervisor using a microkernel design
|
COMMENT= Hypervisor using a microkernel design
|
||||||
|
|
||||||
LICENSE= GPLv2
|
LICENSE= GPLv2
|
||||||
|
@ -31,12 +30,7 @@ EXTRA_PATCHES= ${FILESDIR}/0001-introduce-a-helper-to-allocate-non-contiguous-me
|
||||||
${FILESDIR}/0005-x86-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch:-p2 \
|
${FILESDIR}/0005-x86-rework-paging_log_dirty_op-to-work-with-hvm-gues.patch:-p2 \
|
||||||
${FILESDIR}/0006-xen-pvh-enable-mmu_update-hypercall.patch:-p2 \
|
${FILESDIR}/0006-xen-pvh-enable-mmu_update-hypercall.patch:-p2 \
|
||||||
${FILESDIR}/0007-iommu-fix-usage-of-shared-EPT-IOMMU-page-tables-on-P.patch:-p2 \
|
${FILESDIR}/0007-iommu-fix-usage-of-shared-EPT-IOMMU-page-tables-on-P.patch:-p2 \
|
||||||
${FILESDIR}/0008-xen-arm-mm-Do-not-dump-the-p2m-when-mapping-a-foreig.patch:-p2 \
|
${FILESDIR}/xsa156-4.5.patch:-p2
|
||||||
${FILESDIR}/xsa148-4.5.patch:-p2 \
|
|
||||||
${FILESDIR}/xsa149.patch:-p2 \
|
|
||||||
${FILESDIR}/xsa150.patch:-p2 \
|
|
||||||
${FILESDIR}/xsa151.patch:-p2 \
|
|
||||||
${FILESDIR}/xsa152-4.5.patch:-p2
|
|
||||||
|
|
||||||
.include <bsd.port.options.mk>
|
.include <bsd.port.options.mk>
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
SHA256 (xen-4.5.1.tar.gz) = 668c11d4fca67ac44329e369f810356eacd37b28d28fb96e66aac77f3c5e1371
|
SHA256 (xen-4.5.2.tar.gz) = 4c9e5dac4eea484974e9f76da2756c8e0973b4e884d28d37e955df9ebf00e7e8
|
||||||
SIZE (xen-4.5.1.tar.gz) = 18410400
|
SIZE (xen-4.5.2.tar.gz) = 18416220
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
From 403805aca7a4a508cf193d63aa525b3a76bb09dd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Grall <julien.grall@citrix.com>
|
|
||||||
Date: Fri, 9 Oct 2015 13:00:35 +0200
|
|
||||||
Subject: [PATCH 8/8] xen/arm: mm: Do not dump the p2m when mapping a foreign
|
|
||||||
gfn
|
|
||||||
|
|
||||||
The physmap operation XENMAPSPACE_gfmn_foreign is dumping the p2m when
|
|
||||||
an error occured by calling dump_p2m_lookup. But this function is not
|
|
||||||
using ratelimited printk.
|
|
||||||
|
|
||||||
Any domain able to map foreign gfmn would be able to flood the Xen
|
|
||||||
console.
|
|
||||||
|
|
||||||
The information wasn't not useful so drop it.
|
|
||||||
|
|
||||||
This is XSA-141.
|
|
||||||
|
|
||||||
Signed-off-by: Julien Grall <julien.grall@citrix.com>
|
|
||||||
Acked-by: Ian Campbell <ian.campbell@citrix.com>
|
|
||||||
(cherry picked from commit afc13fe5e21d18c09e44f8ae6f7f4484e9f1de7f)
|
|
||||||
---
|
|
||||||
xen/arch/arm/mm.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
|
|
||||||
index 7d4ba0c..7d95961 100644
|
|
||||||
--- a/xen/arch/arm/mm.c
|
|
||||||
+++ b/xen/arch/arm/mm.c
|
|
||||||
@@ -1103,7 +1103,6 @@ int xenmem_add_to_physmap_one(
|
|
||||||
page = get_page_from_gfn(od, idx, &p2mt, P2M_ALLOC);
|
|
||||||
if ( !page )
|
|
||||||
{
|
|
||||||
- dump_p2m_lookup(od, pfn_to_paddr(idx));
|
|
||||||
rcu_unlock_domain(od);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.9.5 (Apple Git-50.3)
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
x86: guard against undue super page PTE creation
|
|
||||||
|
|
||||||
When optional super page support got added (commit bd1cd81d64 "x86: PV
|
|
||||||
support for hugepages"), two adjustments were missed: mod_l2_entry()
|
|
||||||
needs to consider the PSE and RW bits when deciding whether to use the
|
|
||||||
fast path, and the PSE bit must not be removed from L2_DISALLOW_MASK
|
|
||||||
unconditionally.
|
|
||||||
|
|
||||||
This is XSA-148.
|
|
||||||
|
|
||||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
Reviewed-by: Tim Deegan <tim@xen.org>
|
|
||||||
|
|
||||||
--- a/xen/arch/x86/mm.c
|
|
||||||
+++ b/xen/arch/x86/mm.c
|
|
||||||
@@ -162,7 +162,10 @@ static void put_superpage(unsigned long
|
|
||||||
static uint32_t base_disallow_mask;
|
|
||||||
/* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */
|
|
||||||
#define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL)
|
|
||||||
-#define L2_DISALLOW_MASK (base_disallow_mask & ~_PAGE_PSE)
|
|
||||||
+
|
|
||||||
+#define L2_DISALLOW_MASK (unlikely(opt_allow_superpage) \
|
|
||||||
+ ? base_disallow_mask & ~_PAGE_PSE \
|
|
||||||
+ : base_disallow_mask)
|
|
||||||
|
|
||||||
#define l3_disallow_mask(d) (!is_pv_32on64_domain(d) ? \
|
|
||||||
base_disallow_mask : \
|
|
||||||
@@ -1770,7 +1773,10 @@ static int mod_l2_entry(l2_pgentry_t *pl
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fast path for identical mapping and presence. */
|
|
||||||
- if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT) )
|
|
||||||
+ if ( !l2e_has_changed(ol2e, nl2e,
|
|
||||||
+ unlikely(opt_allow_superpage)
|
|
||||||
+ ? _PAGE_PSE | _PAGE_RW | _PAGE_PRESENT
|
|
||||||
+ : _PAGE_PRESENT) )
|
|
||||||
{
|
|
||||||
adjust_guest_l2e(nl2e, d);
|
|
||||||
if ( UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, vcpu, preserve_ad) )
|
|
|
@ -1,20 +0,0 @@
|
||||||
xen: free domain's vcpu array
|
|
||||||
|
|
||||||
This was overlooked in fb442e2171 ("x86_64: allow more vCPU-s per
|
|
||||||
guest").
|
|
||||||
|
|
||||||
This is XSA-149.
|
|
||||||
|
|
||||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
Reviewed-by: Ian Campbell <ian.campbell@citrix.com>
|
|
||||||
|
|
||||||
--- a/xen/common/domain.c
|
|
||||||
+++ b/xen/common/domain.c
|
|
||||||
@@ -841,6 +841,7 @@ static void complete_domain_destroy(stru
|
|
||||||
|
|
||||||
xsm_free_security_domain(d);
|
|
||||||
free_cpumask_var(d->domain_dirty_cpumask);
|
|
||||||
+ xfree(d->vcpu);
|
|
||||||
free_domain_struct(d);
|
|
||||||
|
|
||||||
send_global_virq(VIRQ_DOM_EXC);
|
|
|
@ -1,201 +0,0 @@
|
||||||
x86/PoD: Eager sweep for zeroed pages
|
|
||||||
|
|
||||||
Based on the contents of a guests physical address space,
|
|
||||||
p2m_pod_emergency_sweep() could degrade into a linear memcmp() from 0 to
|
|
||||||
max_gfn, which runs non-preemptibly.
|
|
||||||
|
|
||||||
As p2m_pod_emergency_sweep() runs behind the scenes in a number of contexts,
|
|
||||||
making it preemptible is not feasible.
|
|
||||||
|
|
||||||
Instead, a different approach is taken. Recently-populated pages are eagerly
|
|
||||||
checked for reclaimation, which amortises the p2m_pod_emergency_sweep()
|
|
||||||
operation across each p2m_pod_demand_populate() operation.
|
|
||||||
|
|
||||||
Note that in the case that a 2M superpage can't be reclaimed as a superpage,
|
|
||||||
it is shattered if 4K pages of zeros can be reclaimed. This is unfortunate
|
|
||||||
but matches the previous behaviour, and is required to avoid regressions
|
|
||||||
(domain crash from PoD exhaustion) with VMs configured close to the limit.
|
|
||||||
|
|
||||||
This is CVE-2015-7970 / XSA-150.
|
|
||||||
|
|
||||||
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
||||||
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
|
|
||||||
|
|
||||||
--- a/xen/arch/x86/mm/p2m-pod.c
|
|
||||||
+++ b/xen/arch/x86/mm/p2m-pod.c
|
|
||||||
@@ -920,28 +920,6 @@ p2m_pod_zero_check(struct p2m_domain *p2
|
|
||||||
}
|
|
||||||
|
|
||||||
#define POD_SWEEP_LIMIT 1024
|
|
||||||
-
|
|
||||||
-/* When populating a new superpage, look at recently populated superpages
|
|
||||||
- * hoping that they've been zeroed. This will snap up zeroed pages as soon as
|
|
||||||
- * the guest OS is done with them. */
|
|
||||||
-static void
|
|
||||||
-p2m_pod_check_last_super(struct p2m_domain *p2m, unsigned long gfn_aligned)
|
|
||||||
-{
|
|
||||||
- unsigned long check_gfn;
|
|
||||||
-
|
|
||||||
- ASSERT(p2m->pod.last_populated_index < POD_HISTORY_MAX);
|
|
||||||
-
|
|
||||||
- check_gfn = p2m->pod.last_populated[p2m->pod.last_populated_index];
|
|
||||||
-
|
|
||||||
- p2m->pod.last_populated[p2m->pod.last_populated_index] = gfn_aligned;
|
|
||||||
-
|
|
||||||
- p2m->pod.last_populated_index =
|
|
||||||
- ( p2m->pod.last_populated_index + 1 ) % POD_HISTORY_MAX;
|
|
||||||
-
|
|
||||||
- p2m_pod_zero_check_superpage(p2m, check_gfn);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
#define POD_SWEEP_STRIDE 16
|
|
||||||
static void
|
|
||||||
p2m_pod_emergency_sweep(struct p2m_domain *p2m)
|
|
||||||
@@ -982,7 +960,7 @@ p2m_pod_emergency_sweep(struct p2m_domai
|
|
||||||
* NB that this is a zero-sum game; we're increasing our cache size
|
|
||||||
* by re-increasing our 'debt'. Since we hold the pod lock,
|
|
||||||
* (entry_count - count) must remain the same. */
|
|
||||||
- if ( p2m->pod.count > 0 && i < limit )
|
|
||||||
+ if ( i < limit && (p2m->pod.count > 0 || hypercall_preempt_check()) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -994,6 +972,58 @@ p2m_pod_emergency_sweep(struct p2m_domai
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void pod_eager_reclaim(struct p2m_domain *p2m)
|
|
||||||
+{
|
|
||||||
+ struct pod_mrp_list *mrp = &p2m->pod.mrp;
|
|
||||||
+ unsigned int i = 0;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Always check one page for reclaimation.
|
|
||||||
+ *
|
|
||||||
+ * If the PoD pool is empty, keep checking some space is found, or all
|
|
||||||
+ * entries have been exhaused.
|
|
||||||
+ */
|
|
||||||
+ do
|
|
||||||
+ {
|
|
||||||
+ unsigned int idx = (mrp->idx + i++) % ARRAY_SIZE(mrp->list);
|
|
||||||
+ unsigned long gfn = mrp->list[idx];
|
|
||||||
+
|
|
||||||
+ if ( gfn != INVALID_GFN )
|
|
||||||
+ {
|
|
||||||
+ if ( gfn & POD_LAST_SUPERPAGE )
|
|
||||||
+ {
|
|
||||||
+ gfn &= ~POD_LAST_SUPERPAGE;
|
|
||||||
+
|
|
||||||
+ if ( p2m_pod_zero_check_superpage(p2m, gfn) == 0 )
|
|
||||||
+ {
|
|
||||||
+ unsigned int x;
|
|
||||||
+
|
|
||||||
+ for ( x = 0; x < SUPERPAGE_PAGES; ++x, ++gfn )
|
|
||||||
+ p2m_pod_zero_check(p2m, &gfn, 1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ p2m_pod_zero_check(p2m, &gfn, 1);
|
|
||||||
+
|
|
||||||
+ mrp->list[idx] = INVALID_GFN;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ } while ( (p2m->pod.count == 0) && (i < ARRAY_SIZE(mrp->list)) );
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void pod_eager_record(struct p2m_domain *p2m,
|
|
||||||
+ unsigned long gfn, unsigned int order)
|
|
||||||
+{
|
|
||||||
+ struct pod_mrp_list *mrp = &p2m->pod.mrp;
|
|
||||||
+
|
|
||||||
+ ASSERT(mrp->list[mrp->idx] == INVALID_GFN);
|
|
||||||
+ ASSERT(gfn != INVALID_GFN);
|
|
||||||
+
|
|
||||||
+ mrp->list[mrp->idx++] =
|
|
||||||
+ gfn | (order == PAGE_ORDER_2M ? POD_LAST_SUPERPAGE : 0);
|
|
||||||
+ mrp->idx %= ARRAY_SIZE(mrp->list);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
|
|
||||||
unsigned int order,
|
|
||||||
@@ -1034,6 +1064,8 @@ p2m_pod_demand_populate(struct p2m_domai
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ pod_eager_reclaim(p2m);
|
|
||||||
+
|
|
||||||
/* Only sweep if we're actually out of memory. Doing anything else
|
|
||||||
* causes unnecessary time and fragmentation of superpages in the p2m. */
|
|
||||||
if ( p2m->pod.count == 0 )
|
|
||||||
@@ -1070,6 +1102,8 @@ p2m_pod_demand_populate(struct p2m_domai
|
|
||||||
p2m->pod.entry_count -= (1 << order);
|
|
||||||
BUG_ON(p2m->pod.entry_count < 0);
|
|
||||||
|
|
||||||
+ pod_eager_record(p2m, gfn_aligned, order);
|
|
||||||
+
|
|
||||||
if ( tb_init_done )
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
@@ -1085,12 +1119,6 @@ p2m_pod_demand_populate(struct p2m_domai
|
|
||||||
__trace_var(TRC_MEM_POD_POPULATE, 0, sizeof(t), &t);
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Check the last guest demand-populate */
|
|
||||||
- if ( p2m->pod.entry_count > p2m->pod.count
|
|
||||||
- && (order == PAGE_ORDER_2M)
|
|
||||||
- && (q & P2M_ALLOC) )
|
|
||||||
- p2m_pod_check_last_super(p2m, gfn_aligned);
|
|
||||||
-
|
|
||||||
pod_unlock(p2m);
|
|
||||||
return 0;
|
|
||||||
out_of_memory:
|
|
||||||
--- a/xen/arch/x86/mm/p2m.c
|
|
||||||
+++ b/xen/arch/x86/mm/p2m.c
|
|
||||||
@@ -58,6 +58,7 @@ boolean_param("hap_2mb", opt_hap_2mb);
|
|
||||||
/* Init the datastructures for later use by the p2m code */
|
|
||||||
static int p2m_initialise(struct domain *d, struct p2m_domain *p2m)
|
|
||||||
{
|
|
||||||
+ unsigned int i;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
mm_rwlock_init(&p2m->lock);
|
|
||||||
@@ -73,6 +74,9 @@ static int p2m_initialise(struct domain
|
|
||||||
|
|
||||||
p2m->np2m_base = P2M_BASE_EADDR;
|
|
||||||
|
|
||||||
+ for ( i = 0; i < ARRAY_SIZE(p2m->pod.mrp.list); ++i )
|
|
||||||
+ p2m->pod.mrp.list[i] = INVALID_GFN;
|
|
||||||
+
|
|
||||||
if ( hap_enabled(d) && cpu_has_vmx )
|
|
||||||
ret = ept_p2m_init(p2m);
|
|
||||||
else
|
|
||||||
--- a/xen/include/asm-x86/p2m.h
|
|
||||||
+++ b/xen/include/asm-x86/p2m.h
|
|
||||||
@@ -292,10 +292,20 @@ struct p2m_domain {
|
|
||||||
entry_count; /* # of pages in p2m marked pod */
|
|
||||||
unsigned long reclaim_single; /* Last gpfn of a scan */
|
|
||||||
unsigned long max_guest; /* gpfn of max guest demand-populate */
|
|
||||||
-#define POD_HISTORY_MAX 128
|
|
||||||
- /* gpfn of last guest superpage demand-populated */
|
|
||||||
- unsigned long last_populated[POD_HISTORY_MAX];
|
|
||||||
- unsigned int last_populated_index;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Tracking of the most recently populated PoD pages, for eager
|
|
||||||
+ * reclamation.
|
|
||||||
+ */
|
|
||||||
+ struct pod_mrp_list {
|
|
||||||
+#define NR_POD_MRP_ENTRIES 32
|
|
||||||
+
|
|
||||||
+/* Encode ORDER_2M superpage in top bit of GFN */
|
|
||||||
+#define POD_LAST_SUPERPAGE (INVALID_GFN & ~(INVALID_GFN >> 1))
|
|
||||||
+
|
|
||||||
+ unsigned long list[NR_POD_MRP_ENTRIES];
|
|
||||||
+ unsigned int idx;
|
|
||||||
+ } mrp;
|
|
||||||
mm_lock_t lock; /* Locking of private pod structs, *
|
|
||||||
* not relying on the p2m lock. */
|
|
||||||
} pod;
|
|
|
@ -1,28 +0,0 @@
|
||||||
xenoprof: free domain's vcpu array
|
|
||||||
|
|
||||||
This was overlooked in fb442e2171 ("x86_64: allow more vCPU-s per
|
|
||||||
guest").
|
|
||||||
|
|
||||||
This is XSA-151.
|
|
||||||
|
|
||||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
Reviewed-by: Ian Campbell <ian.campbell@citrix.com>
|
|
||||||
|
|
||||||
--- a/xen/common/xenoprof.c
|
|
||||||
+++ b/xen/common/xenoprof.c
|
|
||||||
@@ -239,6 +239,7 @@ static int alloc_xenoprof_struct(
|
|
||||||
d->xenoprof->rawbuf = alloc_xenheap_pages(get_order_from_pages(npages), 0);
|
|
||||||
if ( d->xenoprof->rawbuf == NULL )
|
|
||||||
{
|
|
||||||
+ xfree(d->xenoprof->vcpu);
|
|
||||||
xfree(d->xenoprof);
|
|
||||||
d->xenoprof = NULL;
|
|
||||||
return -ENOMEM;
|
|
||||||
@@ -286,6 +287,7 @@ void free_xenoprof_pages(struct domain *
|
|
||||||
free_xenheap_pages(x->rawbuf, order);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ xfree(x->vcpu);
|
|
||||||
xfree(x);
|
|
||||||
d->xenoprof = NULL;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
x86: rate-limit logging in do_xen{oprof,pmu}_op()
|
|
||||||
|
|
||||||
Some of the sub-ops are acessible to all guests, and hence should be
|
|
||||||
rate-limited. In the xenoprof case, just like for XSA-146, include them
|
|
||||||
only in debug builds. Since the vPMU code is rather new, allow them to
|
|
||||||
be always present, but downgrade them to (rate limited) guest messages.
|
|
||||||
|
|
||||||
This is XSA-152.
|
|
||||||
|
|
||||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
||||||
|
|
||||||
--- a/xen/common/xenoprof.c
|
|
||||||
+++ b/xen/common/xenoprof.c
|
|
||||||
@@ -676,15 +676,13 @@ ret_t do_xenoprof_op(int op, XEN_GUEST_H
|
|
||||||
|
|
||||||
if ( (op < 0) || (op > XENOPROF_last_op) )
|
|
||||||
{
|
|
||||||
- printk("xenoprof: invalid operation %d for domain %d\n",
|
|
||||||
- op, current->domain->domain_id);
|
|
||||||
+ gdprintk(XENLOG_DEBUG, "invalid operation %d\n", op);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) )
|
|
||||||
{
|
|
||||||
- printk("xenoprof: dom %d denied privileged operation %d\n",
|
|
||||||
- current->domain->domain_id, op);
|
|
||||||
+ gdprintk(XENLOG_DEBUG, "denied privileged operation %d\n", op);
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -907,8 +905,7 @@ ret_t do_xenoprof_op(int op, XEN_GUEST_H
|
|
||||||
spin_unlock(&xenoprof_lock);
|
|
||||||
|
|
||||||
if ( ret < 0 )
|
|
||||||
- printk("xenoprof: operation %d failed for dom %d (status : %d)\n",
|
|
||||||
- op, current->domain->domain_id, ret);
|
|
||||||
+ gdprintk(XENLOG_DEBUG, "operation %d failed: %d\n", op, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
127
emulators/xen-kernel/files/xsa156-4.5.patch
Normal file
127
emulators/xen-kernel/files/xsa156-4.5.patch
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
x86/HVM: always intercept #AC and #DB
|
||||||
|
|
||||||
|
Both being benign exceptions, and both being possible to get triggered
|
||||||
|
by exception delivery, this is required to prevent a guest from locking
|
||||||
|
up a CPU (resulting from no other VM exits occurring once getting into
|
||||||
|
such a loop).
|
||||||
|
|
||||||
|
The specific scenarios:
|
||||||
|
|
||||||
|
1) #AC may be raised during exception delivery if the handler is set to
|
||||||
|
be a ring-3 one by a 32-bit guest, and the stack is misaligned.
|
||||||
|
|
||||||
|
2) #DB may be raised during exception delivery when a breakpoint got
|
||||||
|
placed on a data structure involved in delivering the exception. This
|
||||||
|
can result in an endless loop when a 64-bit guest uses a non-zero IST
|
||||||
|
for the vector 1 IDT entry, but even without use of IST the time it
|
||||||
|
takes until a contributory fault would get raised (results depending
|
||||||
|
on the handler) may be quite long.
|
||||||
|
|
||||||
|
This is XSA-156.
|
||||||
|
|
||||||
|
Reported-by: Benjamin Serebrin <serebrin@google.com>
|
||||||
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||||
|
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||||
|
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||||||
|
|
||||||
|
--- a/xen/arch/x86/hvm/svm/svm.c
|
||||||
|
+++ b/xen/arch/x86/hvm/svm/svm.c
|
||||||
|
@@ -1045,10 +1045,11 @@ static void noreturn svm_do_resume(struc
|
||||||
|
unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
|
||||||
|
{
|
||||||
|
uint32_t intercepts = vmcb_get_exception_intercepts(vmcb);
|
||||||
|
- uint32_t mask = (1U << TRAP_debug) | (1U << TRAP_int3);
|
||||||
|
+
|
||||||
|
v->arch.hvm_vcpu.debug_state_latch = debug_state;
|
||||||
|
vmcb_set_exception_intercepts(
|
||||||
|
- vmcb, debug_state ? (intercepts | mask) : (intercepts & ~mask));
|
||||||
|
+ vmcb, debug_state ? (intercepts | (1U << TRAP_int3))
|
||||||
|
+ : (intercepts & ~(1U << TRAP_int3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
|
||||||
|
@@ -2435,8 +2436,9 @@ void svm_vmexit_handler(struct cpu_user_
|
||||||
|
|
||||||
|
case VMEXIT_EXCEPTION_DB:
|
||||||
|
if ( !v->domain->debugger_attached )
|
||||||
|
- goto unexpected_exit_type;
|
||||||
|
- domain_pause_for_debugger();
|
||||||
|
+ hvm_inject_hw_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE);
|
||||||
|
+ else
|
||||||
|
+ domain_pause_for_debugger();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VMEXIT_EXCEPTION_BP:
|
||||||
|
@@ -2484,6 +2486,11 @@ void svm_vmexit_handler(struct cpu_user_
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ case VMEXIT_EXCEPTION_AC:
|
||||||
|
+ HVMTRACE_1D(TRAP, TRAP_alignment_check);
|
||||||
|
+ hvm_inject_hw_exception(TRAP_alignment_check, vmcb->exitinfo1);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case VMEXIT_EXCEPTION_UD:
|
||||||
|
svm_vmexit_ud_intercept(regs);
|
||||||
|
break;
|
||||||
|
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||||||
|
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||||||
|
@@ -1186,16 +1186,10 @@ static void vmx_update_host_cr3(struct v
|
||||||
|
|
||||||
|
void vmx_update_debug_state(struct vcpu *v)
|
||||||
|
{
|
||||||
|
- unsigned long mask;
|
||||||
|
-
|
||||||
|
- mask = 1u << TRAP_int3;
|
||||||
|
- if ( !cpu_has_monitor_trap_flag )
|
||||||
|
- mask |= 1u << TRAP_debug;
|
||||||
|
-
|
||||||
|
if ( v->arch.hvm_vcpu.debug_state_latch )
|
||||||
|
- v->arch.hvm_vmx.exception_bitmap |= mask;
|
||||||
|
+ v->arch.hvm_vmx.exception_bitmap |= 1U << TRAP_int3;
|
||||||
|
else
|
||||||
|
- v->arch.hvm_vmx.exception_bitmap &= ~mask;
|
||||||
|
+ v->arch.hvm_vmx.exception_bitmap &= ~(1U << TRAP_int3);
|
||||||
|
|
||||||
|
vmx_vmcs_enter(v);
|
||||||
|
vmx_update_exception_bitmap(v);
|
||||||
|
@@ -2801,9 +2795,10 @@ void vmx_vmexit_handler(struct cpu_user_
|
||||||
|
__vmread(EXIT_QUALIFICATION, &exit_qualification);
|
||||||
|
HVMTRACE_1D(TRAP_DEBUG, exit_qualification);
|
||||||
|
write_debugreg(6, exit_qualification | 0xffff0ff0);
|
||||||
|
- if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag )
|
||||||
|
- goto exit_and_crash;
|
||||||
|
- domain_pause_for_debugger();
|
||||||
|
+ if ( !v->domain->debugger_attached )
|
||||||
|
+ hvm_inject_hw_exception(vector, HVM_DELIVER_NO_ERROR_CODE);
|
||||||
|
+ else
|
||||||
|
+ domain_pause_for_debugger();
|
||||||
|
break;
|
||||||
|
case TRAP_int3:
|
||||||
|
{
|
||||||
|
@@ -2868,6 +2863,11 @@ void vmx_vmexit_handler(struct cpu_user_
|
||||||
|
|
||||||
|
hvm_inject_page_fault(regs->error_code, exit_qualification);
|
||||||
|
break;
|
||||||
|
+ case TRAP_alignment_check:
|
||||||
|
+ HVMTRACE_1D(TRAP, vector);
|
||||||
|
+ __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode);
|
||||||
|
+ hvm_inject_hw_exception(vector, ecode);
|
||||||
|
+ break;
|
||||||
|
case TRAP_nmi:
|
||||||
|
if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) !=
|
||||||
|
(X86_EVENTTYPE_NMI << 8) )
|
||||||
|
--- a/xen/include/asm-x86/hvm/hvm.h
|
||||||
|
+++ b/xen/include/asm-x86/hvm/hvm.h
|
||||||
|
@@ -378,7 +378,10 @@ static inline int hvm_event_pending(stru
|
||||||
|
(X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))
|
||||||
|
|
||||||
|
/* These exceptions must always be intercepted. */
|
||||||
|
-#define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op))
|
||||||
|
+#define HVM_TRAP_MASK ((1U << TRAP_debug) | \
|
||||||
|
+ (1U << TRAP_invalid_op) | \
|
||||||
|
+ (1U << TRAP_alignment_check) | \
|
||||||
|
+ (1U << TRAP_machine_check))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* x86 event types. This enumeration is valid for:
|
|
@ -1,11 +1,10 @@
|
||||||
# $FreeBSD$
|
# $FreeBSD$
|
||||||
|
|
||||||
PORTNAME= xen
|
PORTNAME= xen
|
||||||
PORTVERSION= 4.5.1
|
PORTVERSION= 4.5.2
|
||||||
PORTREVISION= 1
|
|
||||||
CATEGORIES= emulators
|
CATEGORIES= emulators
|
||||||
|
|
||||||
MAINTAINER= ports@FreeBSD.org
|
MAINTAINER= royger@FreeBSD.org
|
||||||
COMMENT= Xen Hyvervisor meta port
|
COMMENT= Xen Hyvervisor meta port
|
||||||
|
|
||||||
LICENSE= GPLv2
|
LICENSE= GPLv2
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
# $FreeBSD$
|
# $FreeBSD$
|
||||||
|
|
||||||
PORTNAME= xen
|
PORTNAME= xen
|
||||||
PORTVERSION= 4.5.1
|
PORTVERSION= 4.5.2
|
||||||
PORTREVISION= 2
|
|
||||||
CATEGORIES= sysutils emulators
|
CATEGORIES= sysutils emulators
|
||||||
MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/ \
|
MASTER_SITES= http://bits.xensource.com/oss-xen/release/${PORTVERSION}/ \
|
||||||
http://code.coreboot.org/p/seabios/downloads/get/:seabios
|
http://code.coreboot.org/p/seabios/downloads/get/:seabios
|
||||||
PKGNAMESUFFIX= -tools
|
PKGNAMESUFFIX= -tools
|
||||||
|
|
||||||
MAINTAINER= ports@FreeBSD.org
|
MAINTAINER= royger@FreeBSD.org
|
||||||
COMMENT= Xen management tool, based on LibXenlight
|
COMMENT= Xen management tool, based on LibXenlight
|
||||||
|
|
||||||
LICENSE= GPLv2 LGPL3
|
LICENSE= GPLv2 LGPL3
|
||||||
|
@ -48,10 +47,7 @@ QEMU_ARGS= --disable-gtk \
|
||||||
--disable-curl \
|
--disable-curl \
|
||||||
--cxx=c++
|
--cxx=c++
|
||||||
|
|
||||||
EXTRA_PATCHES= ${FILESDIR}/xsa137.patch:-p1 \
|
EXTRA_PATCHES= ${FILESDIR}/0002-libxc-fix-xc_dom_load_elf_symtab.patch:-p1
|
||||||
${FILESDIR}/xsa142-4.5.patch:-p1 \
|
|
||||||
${FILESDIR}/xsa153-libxl.patch:-p1 \
|
|
||||||
${FILESDIR}/0002-libxc-fix-xc_dom_load_elf_symtab.patch:-p1
|
|
||||||
|
|
||||||
CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}"
|
CONFIGURE_ARGS+= --with-extra-qemuu-configure-args="${QEMU_ARGS}"
|
||||||
SHEBANG_FILES= tools/misc/xencov_split \
|
SHEBANG_FILES= tools/misc/xencov_split \
|
||||||
|
@ -78,10 +74,6 @@ post-patch:
|
||||||
${WRKSRC}/tools/libxl/libxl_dm.c \
|
${WRKSRC}/tools/libxl/libxl_dm.c \
|
||||||
${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \
|
${WRKSRC}/tools/qemu-xen-traditional/i386-dm/helper2.c \
|
||||||
${WRKSRC}/docs/man/*
|
${WRKSRC}/docs/man/*
|
||||||
@for p in ${FILESDIR}/*qemuu*.patch; do \
|
|
||||||
${ECHO_CMD} "====> Applying $${p##*/}" ; \
|
|
||||||
${PATCH} -s -p1 -i $${p} -d ${WRKSRC}/tools/qemu-xen ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
post-install:
|
post-install:
|
||||||
${MKDIR} ${STAGEDIR}/var/run/xen
|
${MKDIR} ${STAGEDIR}/var/run/xen
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
SHA256 (xen-4.5.1.tar.gz) = 668c11d4fca67ac44329e369f810356eacd37b28d28fb96e66aac77f3c5e1371
|
SHA256 (xen-4.5.2.tar.gz) = 4c9e5dac4eea484974e9f76da2756c8e0973b4e884d28d37e955df9ebf00e7e8
|
||||||
SIZE (xen-4.5.1.tar.gz) = 18410400
|
SIZE (xen-4.5.2.tar.gz) = 18416220
|
||||||
SHA256 (seabios-1.8.1.tar.gz) = 283bd848f5ce9d4bc52add973a856347e02c9ce89a9e6bc92c99359b87c9871d
|
SHA256 (seabios-1.8.1.tar.gz) = 283bd848f5ce9d4bc52add973a856347e02c9ce89a9e6bc92c99359b87c9871d
|
||||||
SIZE (seabios-1.8.1.tar.gz) = 537712
|
SIZE (seabios-1.8.1.tar.gz) = 537712
|
||||||
|
|
|
@ -1,231 +0,0 @@
|
||||||
From 593fe52faa1b85567a7ec20c69d8cfbc7368ae5b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
|
||||||
Date: Mon, 15 Jun 2015 14:50:42 +0100
|
|
||||||
Subject: [PATCH] xl: Sane handling of extra config file arguments
|
|
||||||
|
|
||||||
Various xl sub-commands take additional parameters containing = as
|
|
||||||
additional config fragments.
|
|
||||||
|
|
||||||
The handling of these config fragments has a number of bugs:
|
|
||||||
|
|
||||||
1. Use of a static 1024-byte buffer. (If truncation would occur,
|
|
||||||
with semi-trusted input, a security risk arises due to quotes
|
|
||||||
being lost.)
|
|
||||||
|
|
||||||
2. Mishandling of the return value from snprintf, so that if
|
|
||||||
truncation occurs, the to-write pointer is updated with the
|
|
||||||
wanted-to-write length, resulting in stack corruption. (This is
|
|
||||||
XSA-137.)
|
|
||||||
|
|
||||||
3. Clone-and-hack of the code for constructing the appended
|
|
||||||
config file.
|
|
||||||
|
|
||||||
These are fixed here, by introducing a new function
|
|
||||||
`string_realloc_append' and using it everywhere. The `extra_info'
|
|
||||||
buffers are replaced by pointers, which start off NULL and are
|
|
||||||
explicitly freed on all return paths.
|
|
||||||
|
|
||||||
The separate variable which will become dom_info.extra_config is
|
|
||||||
abolished (which involves moving the clearing of dom_info).
|
|
||||||
|
|
||||||
Additional bugs I observe, not fixed here:
|
|
||||||
|
|
||||||
4. The functions which now call string_realloc_append use ad-hoc
|
|
||||||
error returns, with multiple calls to `return'. This currently
|
|
||||||
necessitates multiple new calls to `free'.
|
|
||||||
|
|
||||||
5. Many of the paths in xl call exit(-rc) where rc is a libxl status
|
|
||||||
code. This is a ridiculous exit status `convention'.
|
|
||||||
|
|
||||||
6. The loops for handling extra config data are clone-and-hacks.
|
|
||||||
|
|
||||||
7. Once the extra config buffer is accumulated, it must be combined
|
|
||||||
with the appropriate main config file. The code to do this
|
|
||||||
combining is clone-and-hacked too.
|
|
||||||
|
|
||||||
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
|
|
||||||
Tested-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
|
|
||||||
Acked-by: Ian Campbell <ian,campbell@citrix.com>
|
|
||||||
---
|
|
||||||
v2: Use SSIZE_MAX, not INT_MAX.
|
|
||||||
Check *accumulate for NULL, not accumulate.
|
|
||||||
Move memset of dom_info.
|
|
||||||
---
|
|
||||||
tools/libxl/xl_cmdimpl.c | 64 +++++++++++++++++++++++++++++-----------------
|
|
||||||
1 file changed, 40 insertions(+), 24 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
|
|
||||||
index c858068..c01a851 100644
|
|
||||||
--- a/tools/libxl/xl_cmdimpl.c
|
|
||||||
+++ b/tools/libxl/xl_cmdimpl.c
|
|
||||||
@@ -151,7 +151,7 @@ struct domain_create {
|
|
||||||
int console_autoconnect;
|
|
||||||
int checkpointed_stream;
|
|
||||||
const char *config_file;
|
|
||||||
- const char *extra_config; /* extra config string */
|
|
||||||
+ char *extra_config; /* extra config string */
|
|
||||||
const char *restore_file;
|
|
||||||
int migrate_fd; /* -1 means none */
|
|
||||||
char **migration_domname_r; /* from malloc */
|
|
||||||
@@ -4805,11 +4805,25 @@ int main_vm_list(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void string_realloc_append(char **accumulate, const char *more)
|
|
||||||
+{
|
|
||||||
+ /* Appends more to accumulate. Accumulate is either NULL, or
|
|
||||||
+ * points (always) to a malloc'd nul-terminated string. */
|
|
||||||
+
|
|
||||||
+ size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
|
|
||||||
+ size_t morelen = strlen(more) + 1/*nul*/;
|
|
||||||
+ if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
|
|
||||||
+ fprintf(stderr,"Additional config data far too large\n");
|
|
||||||
+ exit(-ERROR_FAIL);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *accumulate = xrealloc(*accumulate, oldlen + morelen);
|
|
||||||
+ memcpy(*accumulate + oldlen, more, morelen);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int main_create(int argc, char **argv)
|
|
||||||
{
|
|
||||||
const char *filename = NULL;
|
|
||||||
- char *p;
|
|
||||||
- char extra_config[1024];
|
|
||||||
struct domain_create dom_info;
|
|
||||||
int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
|
|
||||||
quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
|
|
||||||
@@ -4824,6 +4838,8 @@ int main_create(int argc, char **argv)
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
+ dom_info.extra_config = NULL;
|
|
||||||
+
|
|
||||||
if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
|
|
||||||
filename = argv[1];
|
|
||||||
argc--; argv++;
|
|
||||||
@@ -4863,20 +4879,21 @@ int main_create(int argc, char **argv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- extra_config[0] = '\0';
|
|
||||||
- for (p = extra_config; optind < argc; optind++) {
|
|
||||||
+ memset(&dom_info, 0, sizeof(dom_info));
|
|
||||||
+
|
|
||||||
+ for (; optind < argc; optind++) {
|
|
||||||
if (strchr(argv[optind], '=') != NULL) {
|
|
||||||
- p += snprintf(p, sizeof(extra_config) - (p - extra_config),
|
|
||||||
- "%s\n", argv[optind]);
|
|
||||||
+ string_realloc_append(&dom_info.extra_config, argv[optind]);
|
|
||||||
+ string_realloc_append(&dom_info.extra_config, "\n");
|
|
||||||
} else if (!filename) {
|
|
||||||
filename = argv[optind];
|
|
||||||
} else {
|
|
||||||
help("create");
|
|
||||||
+ free(dom_info.extra_config);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- memset(&dom_info, 0, sizeof(dom_info));
|
|
||||||
dom_info.debug = debug;
|
|
||||||
dom_info.daemonize = daemonize;
|
|
||||||
dom_info.monitor = monitor;
|
|
||||||
@@ -4884,16 +4901,18 @@ int main_create(int argc, char **argv)
|
|
||||||
dom_info.dryrun = dryrun_only;
|
|
||||||
dom_info.quiet = quiet;
|
|
||||||
dom_info.config_file = filename;
|
|
||||||
- dom_info.extra_config = extra_config;
|
|
||||||
dom_info.migrate_fd = -1;
|
|
||||||
dom_info.vnc = vnc;
|
|
||||||
dom_info.vncautopass = vncautopass;
|
|
||||||
dom_info.console_autoconnect = console_autoconnect;
|
|
||||||
|
|
||||||
rc = create_domain(&dom_info);
|
|
||||||
- if (rc < 0)
|
|
||||||
+ if (rc < 0) {
|
|
||||||
+ free(dom_info.extra_config);
|
|
||||||
return -rc;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ free(dom_info.extra_config);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4901,8 +4920,7 @@ int main_config_update(int argc, char **argv)
|
|
||||||
{
|
|
||||||
uint32_t domid;
|
|
||||||
const char *filename = NULL;
|
|
||||||
- char *p;
|
|
||||||
- char extra_config[1024];
|
|
||||||
+ char *extra_config = NULL;
|
|
||||||
void *config_data = 0;
|
|
||||||
int config_len = 0;
|
|
||||||
libxl_domain_config d_config;
|
|
||||||
@@ -4940,15 +4958,15 @@ int main_config_update(int argc, char **argv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- extra_config[0] = '\0';
|
|
||||||
- for (p = extra_config; optind < argc; optind++) {
|
|
||||||
+ for (; optind < argc; optind++) {
|
|
||||||
if (strchr(argv[optind], '=') != NULL) {
|
|
||||||
- p += snprintf(p, sizeof(extra_config) - (p - extra_config),
|
|
||||||
- "%s\n", argv[optind]);
|
|
||||||
+ string_realloc_append(&extra_config, argv[optind]);
|
|
||||||
+ string_realloc_append(&extra_config, "\n");
|
|
||||||
} else if (!filename) {
|
|
||||||
filename = argv[optind];
|
|
||||||
} else {
|
|
||||||
help("create");
|
|
||||||
+ free(extra_config);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4957,7 +4975,8 @@ int main_config_update(int argc, char **argv)
|
|
||||||
rc = libxl_read_file_contents(ctx, filename,
|
|
||||||
&config_data, &config_len);
|
|
||||||
if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
|
|
||||||
- filename, strerror(errno)); return ERROR_FAIL; }
|
|
||||||
+ filename, strerror(errno));
|
|
||||||
+ free(extra_config); return ERROR_FAIL; }
|
|
||||||
if (strlen(extra_config)) {
|
|
||||||
if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
|
|
||||||
fprintf(stderr, "Failed to attach extra configration\n");
|
|
||||||
@@ -4998,7 +5017,7 @@ int main_config_update(int argc, char **argv)
|
|
||||||
libxl_domain_config_dispose(&d_config);
|
|
||||||
|
|
||||||
free(config_data);
|
|
||||||
-
|
|
||||||
+ free(extra_config);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -7255,7 +7274,7 @@ int main_cpupoolcreate(int argc, char **argv)
|
|
||||||
{
|
|
||||||
const char *filename = NULL, *config_src=NULL;
|
|
||||||
const char *p;
|
|
||||||
- char extra_config[1024];
|
|
||||||
+ char *extra_config = NULL;
|
|
||||||
int opt;
|
|
||||||
static struct option opts[] = {
|
|
||||||
{"defconfig", 1, 0, 'f'},
|
|
||||||
@@ -7289,13 +7308,10 @@ int main_cpupoolcreate(int argc, char **argv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- memset(extra_config, 0, sizeof(extra_config));
|
|
||||||
while (optind < argc) {
|
|
||||||
if ((p = strchr(argv[optind], '='))) {
|
|
||||||
- if (strlen(extra_config) + 1 + strlen(argv[optind]) < sizeof(extra_config)) {
|
|
||||||
- strcat(extra_config, "\n");
|
|
||||||
- strcat(extra_config, argv[optind]);
|
|
||||||
- }
|
|
||||||
+ string_realloc_append(&extra_config, "\n");
|
|
||||||
+ string_realloc_append(&extra_config, argv[optind]);
|
|
||||||
} else if (!filename) {
|
|
||||||
filename = argv[optind];
|
|
||||||
} else {
|
|
||||||
--
|
|
||||||
1.7.10.4
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
From a9de14175548c04e0f8be7fae219246509ba46a9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Wed, 3 Jun 2015 14:13:31 +0200
|
|
||||||
Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
|
|
||||||
(CVE-2015-5154)
|
|
||||||
|
|
||||||
If the end_transfer_func of a command is called because enough data has
|
|
||||||
been read or written for the current PIO transfer, and it fails to
|
|
||||||
correctly call the command completion functions, the DRQ bit in the
|
|
||||||
status register and s->end_transfer_func may remain set. This allows the
|
|
||||||
guest to access further bytes in s->io_buffer beyond s->data_end, and
|
|
||||||
eventually overflowing the io_buffer.
|
|
||||||
|
|
||||||
One case where this currently happens is emulation of the ATAPI command
|
|
||||||
START STOP UNIT.
|
|
||||||
|
|
||||||
This patch fixes the problem by adding explicit array bounds checks
|
|
||||||
before accessing the buffer instead of relying on end_transfer_func to
|
|
||||||
function correctly.
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
hw/ide/core.c | 16 ++++++++++++++++
|
|
||||||
1 file changed, 16 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
|
||||||
index 122e955..44fcc23 100644
|
|
||||||
--- a/hw/ide/core.c
|
|
||||||
+++ b/hw/ide/core.c
|
|
||||||
@@ -2021,6 +2021,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
|
|
||||||
}
|
|
||||||
|
|
||||||
p = s->data_ptr;
|
|
||||||
+ if (p + 2 > s->data_end) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
*(uint16_t *)p = le16_to_cpu(val);
|
|
||||||
p += 2;
|
|
||||||
s->data_ptr = p;
|
|
||||||
@@ -2042,6 +2046,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
p = s->data_ptr;
|
|
||||||
+ if (p + 2 > s->data_end) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
ret = cpu_to_le16(*(uint16_t *)p);
|
|
||||||
p += 2;
|
|
||||||
s->data_ptr = p;
|
|
||||||
@@ -2063,6 +2071,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
|
|
||||||
}
|
|
||||||
|
|
||||||
p = s->data_ptr;
|
|
||||||
+ if (p + 4 > s->data_end) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
*(uint32_t *)p = le32_to_cpu(val);
|
|
||||||
p += 4;
|
|
||||||
s->data_ptr = p;
|
|
||||||
@@ -2084,6 +2096,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
p = s->data_ptr;
|
|
||||||
+ if (p + 4 > s->data_end) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
ret = cpu_to_le32(*(uint32_t *)p);
|
|
||||||
p += 4;
|
|
||||||
s->data_ptr = p;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
|
@ -1,28 +0,0 @@
|
||||||
From aa851d30acfbb9580098ac1dc82885530cb8b3c1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Wed, 3 Jun 2015 14:17:46 +0200
|
|
||||||
Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion
|
|
||||||
|
|
||||||
The command must be completed on all code paths. START STOP UNIT with
|
|
||||||
pwrcnd set should succeed without doing anything.
|
|
||||||
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
hw/ide/atapi.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
|
|
||||||
index 950e311..79dd167 100644
|
|
||||||
--- a/hw/ide/atapi.c
|
|
||||||
+++ b/hw/ide/atapi.c
|
|
||||||
@@ -983,6 +983,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
|
|
||||||
|
|
||||||
if (pwrcnd) {
|
|
||||||
/* eject/load only happens for power condition == 0 */
|
|
||||||
+ ide_atapi_cmd_ok(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
From 1d3c2268f8708126a34064c2e0c1000b40e6f3e5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Wed, 3 Jun 2015 14:41:27 +0200
|
|
||||||
Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses
|
|
||||||
|
|
||||||
This is additional hardening against an end_transfer_func that fails to
|
|
||||||
clear the DRQ status bit. The bit must be unset as soon as the PIO
|
|
||||||
transfer has completed, so it's better to do this in a central place
|
|
||||||
instead of duplicating the code in all commands (and forgetting it in
|
|
||||||
some).
|
|
||||||
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
hw/ide/core.c | 16 ++++++++++++----
|
|
||||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
|
||||||
index 44fcc23..50449ca 100644
|
|
||||||
--- a/hw/ide/core.c
|
|
||||||
+++ b/hw/ide/core.c
|
|
||||||
@@ -2028,8 +2028,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
|
|
||||||
*(uint16_t *)p = le16_to_cpu(val);
|
|
||||||
p += 2;
|
|
||||||
s->data_ptr = p;
|
|
||||||
- if (p >= s->data_end)
|
|
||||||
+ if (p >= s->data_end) {
|
|
||||||
+ s->status &= ~DRQ_STAT;
|
|
||||||
s->end_transfer_func(s);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
|
||||||
@@ -2053,8 +2055,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
|
|
||||||
ret = cpu_to_le16(*(uint16_t *)p);
|
|
||||||
p += 2;
|
|
||||||
s->data_ptr = p;
|
|
||||||
- if (p >= s->data_end)
|
|
||||||
+ if (p >= s->data_end) {
|
|
||||||
+ s->status &= ~DRQ_STAT;
|
|
||||||
s->end_transfer_func(s);
|
|
||||||
+ }
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2078,8 +2082,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
|
|
||||||
*(uint32_t *)p = le32_to_cpu(val);
|
|
||||||
p += 4;
|
|
||||||
s->data_ptr = p;
|
|
||||||
- if (p >= s->data_end)
|
|
||||||
+ if (p >= s->data_end) {
|
|
||||||
+ s->status &= ~DRQ_STAT;
|
|
||||||
s->end_transfer_func(s);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|
||||||
@@ -2103,8 +2109,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
|
|
||||||
ret = cpu_to_le32(*(uint32_t *)p);
|
|
||||||
p += 4;
|
|
||||||
s->data_ptr = p;
|
|
||||||
- if (p >= s->data_end)
|
|
||||||
+ if (p >= s->data_end) {
|
|
||||||
+ s->status &= ~DRQ_STAT;
|
|
||||||
s->end_transfer_func(s);
|
|
||||||
+ }
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
pci_piix3_xen_ide_unplug should completely unhook the unplugged
|
|
||||||
IDEDevice from the corresponding BlockBackend, otherwise the next call
|
|
||||||
to release_drive will try to detach the drive again.
|
|
||||||
|
|
||||||
Suggested-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
|
||||||
---
|
|
||||||
hw/ide/piix.c | 7 +++++++
|
|
||||||
1 file changed, 7 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
|
|
||||||
index 40757eb..0524dce 100644
|
|
||||||
--- a/hw/ide/piix.c
|
|
||||||
+++ b/hw/ide/piix.c
|
|
||||||
@@ -172,6 +172,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
|
|
||||||
PCIIDEState *pci_ide;
|
|
||||||
DriveInfo *di;
|
|
||||||
int i = 0;
|
|
||||||
+ IDEDevice *idedev;
|
|
||||||
|
|
||||||
pci_ide = PCI_IDE(dev);
|
|
||||||
|
|
||||||
@@ -184,6 +185,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
|
|
||||||
}
|
|
||||||
bdrv_close(di->bdrv);
|
|
||||||
pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
|
|
||||||
+ if (!(i % 2)) {
|
|
||||||
+ idedev = pci_ide->bus[di->bus].master;
|
|
||||||
+ } else {
|
|
||||||
+ idedev = pci_ide->bus[di->bus].slave;
|
|
||||||
+ }
|
|
||||||
+ idedev->conf.bs = NULL;
|
|
||||||
drive_put_ref(di);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
From 5e0c290415b9d57077a86e70c8e6a058868334d3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:16:58 +0100
|
|
||||||
Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing
|
|
||||||
|
|
||||||
Transmit offload needs to parse packet headers. If header fields have
|
|
||||||
unexpected values the offload processing is skipped.
|
|
||||||
|
|
||||||
The code currently uses nested ifs because there is relatively little
|
|
||||||
input validation. The next patches will add missing input validation
|
|
||||||
and a goto label is more appropriate to avoid deep if statement nesting.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 41 ++++++++++++++++++++++-------------------
|
|
||||||
1 file changed, 22 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index 5f0197c..91ba33b 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2174,28 +2174,30 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
size_t eth_payload_len = 0;
|
|
||||||
|
|
||||||
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
|
||||||
- if (proto == ETH_P_IP)
|
|
||||||
+ if (proto != ETH_P_IP)
|
|
||||||
{
|
|
||||||
- DPRINTF("+++ C+ mode has IP packet\n");
|
|
||||||
-
|
|
||||||
- /* not aligned */
|
|
||||||
- eth_payload_data = saved_buffer + ETH_HLEN;
|
|
||||||
- eth_payload_len = saved_size - ETH_HLEN;
|
|
||||||
-
|
|
||||||
- ip = (ip_header*)eth_payload_data;
|
|
||||||
-
|
|
||||||
- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
|
||||||
- DPRINTF("+++ C+ mode packet has bad IP version %d "
|
|
||||||
- "expected %d\n", IP_HEADER_VERSION(ip),
|
|
||||||
- IP_HEADER_VERSION_4);
|
|
||||||
- ip = NULL;
|
|
||||||
- } else {
|
|
||||||
- hlen = IP_HEADER_LENGTH(ip);
|
|
||||||
- ip_protocol = ip->ip_p;
|
|
||||||
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
- }
|
|
||||||
+ goto skip_offload;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ DPRINTF("+++ C+ mode has IP packet\n");
|
|
||||||
+
|
|
||||||
+ /* not aligned */
|
|
||||||
+ eth_payload_data = saved_buffer + ETH_HLEN;
|
|
||||||
+ eth_payload_len = saved_size - ETH_HLEN;
|
|
||||||
+
|
|
||||||
+ ip = (ip_header*)eth_payload_data;
|
|
||||||
+
|
|
||||||
+ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
|
||||||
+ DPRINTF("+++ C+ mode packet has bad IP version %d "
|
|
||||||
+ "expected %d\n", IP_HEADER_VERSION(ip),
|
|
||||||
+ IP_HEADER_VERSION_4);
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ hlen = IP_HEADER_LENGTH(ip);
|
|
||||||
+ ip_protocol = ip->ip_p;
|
|
||||||
+ ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
+
|
|
||||||
if (ip)
|
|
||||||
{
|
|
||||||
if (txdw0 & CP_TX_IPCS)
|
|
||||||
@@ -2391,6 +2393,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+skip_offload:
|
|
||||||
/* update tally counter */
|
|
||||||
++s->tally_counters.TxOk;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,373 +0,0 @@
|
||||||
From 2d7d80e8dc160904fa7276cc05da26c062a50066 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:16:59 +0100
|
|
||||||
Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement
|
|
||||||
|
|
||||||
The previous patch stopped using the ip pointer as an indicator that the
|
|
||||||
IP header is present. When we reach the if (ip) {...} statement we know
|
|
||||||
ip is always non-NULL.
|
|
||||||
|
|
||||||
Remove the if statement to reduce nesting.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 305 +++++++++++++++++++++++++++----------------------------
|
|
||||||
1 file changed, 151 insertions(+), 154 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index 91ba33b..2f12d42 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2198,198 +2198,195 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
ip_protocol = ip->ip_p;
|
|
||||||
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
|
|
||||||
- if (ip)
|
|
||||||
+ if (txdw0 & CP_TX_IPCS)
|
|
||||||
{
|
|
||||||
- if (txdw0 & CP_TX_IPCS)
|
|
||||||
- {
|
|
||||||
- DPRINTF("+++ C+ mode need IP checksum\n");
|
|
||||||
+ DPRINTF("+++ C+ mode need IP checksum\n");
|
|
||||||
|
|
||||||
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
|
||||||
- /* bad packet header len */
|
|
||||||
- /* or packet too short */
|
|
||||||
- }
|
|
||||||
- else
|
|
||||||
- {
|
|
||||||
- ip->ip_sum = 0;
|
|
||||||
- ip->ip_sum = ip_checksum(ip, hlen);
|
|
||||||
- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
|
||||||
- hlen, ip->ip_sum);
|
|
||||||
- }
|
|
||||||
+ if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
|
||||||
+ /* bad packet header len */
|
|
||||||
+ /* or packet too short */
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
+ else
|
|
||||||
{
|
|
||||||
- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
|
||||||
+ ip->ip_sum = 0;
|
|
||||||
+ ip->ip_sum = ip_checksum(ip, hlen);
|
|
||||||
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
|
||||||
+ hlen, ip->ip_sum);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
|
||||||
- "frame data %d specified MSS=%d\n", ETH_MTU,
|
|
||||||
- ip_data_len, saved_size - ETH_HLEN, large_send_mss);
|
|
||||||
+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
+ {
|
|
||||||
+ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
|
||||||
|
|
||||||
- int tcp_send_offset = 0;
|
|
||||||
- int send_count = 0;
|
|
||||||
+ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
|
||||||
+ "frame data %d specified MSS=%d\n", ETH_MTU,
|
|
||||||
+ ip_data_len, saved_size - ETH_HLEN, large_send_mss);
|
|
||||||
|
|
||||||
- /* maximum IP header length is 60 bytes */
|
|
||||||
- uint8_t saved_ip_header[60];
|
|
||||||
+ int tcp_send_offset = 0;
|
|
||||||
+ int send_count = 0;
|
|
||||||
|
|
||||||
- /* save IP header template; data area is used in tcp checksum calculation */
|
|
||||||
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
|
||||||
+ /* maximum IP header length is 60 bytes */
|
|
||||||
+ uint8_t saved_ip_header[60];
|
|
||||||
|
|
||||||
- /* a placeholder for checksum calculation routine in tcp case */
|
|
||||||
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
|
||||||
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
|
||||||
+ /* save IP header template; data area is used in tcp checksum calculation */
|
|
||||||
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
|
||||||
|
|
||||||
- /* pointer to TCP header */
|
|
||||||
- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
|
||||||
+ /* a placeholder for checksum calculation routine in tcp case */
|
|
||||||
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
|
||||||
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
|
||||||
|
|
||||||
- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
|
||||||
+ /* pointer to TCP header */
|
|
||||||
+ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
|
||||||
|
|
||||||
- /* ETH_MTU = ip header len + tcp header len + payload */
|
|
||||||
- int tcp_data_len = ip_data_len - tcp_hlen;
|
|
||||||
- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
|
||||||
+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
|
||||||
|
|
||||||
- DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
|
|
||||||
- "data len %d TCP chunk size %d\n", ip_data_len,
|
|
||||||
- tcp_hlen, tcp_data_len, tcp_chunk_size);
|
|
||||||
+ /* ETH_MTU = ip header len + tcp header len + payload */
|
|
||||||
+ int tcp_data_len = ip_data_len - tcp_hlen;
|
|
||||||
+ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
|
||||||
|
|
||||||
- /* note the cycle below overwrites IP header data,
|
|
||||||
- but restores it from saved_ip_header before sending packet */
|
|
||||||
+ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
|
|
||||||
+ "data len %d TCP chunk size %d\n", ip_data_len,
|
|
||||||
+ tcp_hlen, tcp_data_len, tcp_chunk_size);
|
|
||||||
|
|
||||||
- int is_last_frame = 0;
|
|
||||||
+ /* note the cycle below overwrites IP header data,
|
|
||||||
+ but restores it from saved_ip_header before sending packet */
|
|
||||||
|
|
||||||
- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
|
||||||
- {
|
|
||||||
- uint16_t chunk_size = tcp_chunk_size;
|
|
||||||
-
|
|
||||||
- /* check if this is the last frame */
|
|
||||||
- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
|
||||||
- {
|
|
||||||
- is_last_frame = 1;
|
|
||||||
- chunk_size = tcp_data_len - tcp_send_offset;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
|
|
||||||
- be32_to_cpu(p_tcp_hdr->th_seq));
|
|
||||||
-
|
|
||||||
- /* add 4 TCP pseudoheader fields */
|
|
||||||
- /* copy IP source and destination fields */
|
|
||||||
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
|
||||||
-
|
|
||||||
- DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
|
|
||||||
- "packet with %d bytes data\n", tcp_hlen +
|
|
||||||
- chunk_size);
|
|
||||||
-
|
|
||||||
- if (tcp_send_offset)
|
|
||||||
- {
|
|
||||||
- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* keep PUSH and FIN flags only for the last frame */
|
|
||||||
- if (!is_last_frame)
|
|
||||||
- {
|
|
||||||
- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* recalculate TCP checksum */
|
|
||||||
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
- p_tcpip_hdr->zeros = 0;
|
|
||||||
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
|
||||||
- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
|
||||||
-
|
|
||||||
- p_tcp_hdr->th_sum = 0;
|
|
||||||
-
|
|
||||||
- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
|
||||||
- DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
|
|
||||||
- tcp_checksum);
|
|
||||||
-
|
|
||||||
- p_tcp_hdr->th_sum = tcp_checksum;
|
|
||||||
-
|
|
||||||
- /* restore IP header */
|
|
||||||
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
|
||||||
-
|
|
||||||
- /* set IP data length and recalculate IP checksum */
|
|
||||||
- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
|
||||||
-
|
|
||||||
- /* increment IP id for subsequent frames */
|
|
||||||
- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
|
||||||
-
|
|
||||||
- ip->ip_sum = 0;
|
|
||||||
- ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
|
||||||
- DPRINTF("+++ C+ mode TSO IP header len=%d "
|
|
||||||
- "checksum=%04x\n", hlen, ip->ip_sum);
|
|
||||||
-
|
|
||||||
- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
|
||||||
- DPRINTF("+++ C+ mode TSO transferring packet size "
|
|
||||||
- "%d\n", tso_send_size);
|
|
||||||
- rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
|
|
||||||
- 0, (uint8_t *) dot1q_buffer);
|
|
||||||
-
|
|
||||||
- /* add transferred count to TCP sequence number */
|
|
||||||
- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
|
||||||
- ++send_count;
|
|
||||||
- }
|
|
||||||
+ int is_last_frame = 0;
|
|
||||||
|
|
||||||
- /* Stop sending this frame */
|
|
||||||
- saved_size = 0;
|
|
||||||
- }
|
|
||||||
- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
|
||||||
+ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
|
|
||||||
{
|
|
||||||
- DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
|
|
||||||
+ uint16_t chunk_size = tcp_chunk_size;
|
|
||||||
|
|
||||||
- /* maximum IP header length is 60 bytes */
|
|
||||||
- uint8_t saved_ip_header[60];
|
|
||||||
- memcpy(saved_ip_header, eth_payload_data, hlen);
|
|
||||||
+ /* check if this is the last frame */
|
|
||||||
+ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
|
|
||||||
+ {
|
|
||||||
+ is_last_frame = 1;
|
|
||||||
+ chunk_size = tcp_data_len - tcp_send_offset;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
|
||||||
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
|
||||||
+ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
|
|
||||||
+ be32_to_cpu(p_tcp_hdr->th_seq));
|
|
||||||
|
|
||||||
/* add 4 TCP pseudoheader fields */
|
|
||||||
/* copy IP source and destination fields */
|
|
||||||
memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
|
||||||
|
|
||||||
- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
+ DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
|
|
||||||
+ "packet with %d bytes data\n", tcp_hlen +
|
|
||||||
+ chunk_size);
|
|
||||||
+
|
|
||||||
+ if (tcp_send_offset)
|
|
||||||
{
|
|
||||||
- DPRINTF("+++ C+ mode calculating TCP checksum for "
|
|
||||||
- "packet with %d bytes data\n", ip_data_len);
|
|
||||||
+ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
- p_tcpip_hdr->zeros = 0;
|
|
||||||
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
|
||||||
- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
|
||||||
+ /* keep PUSH and FIN flags only for the last frame */
|
|
||||||
+ if (!is_last_frame)
|
|
||||||
+ {
|
|
||||||
+ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
|
||||||
+ /* recalculate TCP checksum */
|
|
||||||
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
+ p_tcpip_hdr->zeros = 0;
|
|
||||||
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
|
||||||
+ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
|
|
||||||
|
|
||||||
- p_tcp_hdr->th_sum = 0;
|
|
||||||
+ p_tcp_hdr->th_sum = 0;
|
|
||||||
|
|
||||||
- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
|
||||||
- DPRINTF("+++ C+ mode TCP checksum %04x\n",
|
|
||||||
- tcp_checksum);
|
|
||||||
+ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
|
|
||||||
+ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
|
|
||||||
+ tcp_checksum);
|
|
||||||
|
|
||||||
- p_tcp_hdr->th_sum = tcp_checksum;
|
|
||||||
- }
|
|
||||||
- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
|
||||||
- {
|
|
||||||
- DPRINTF("+++ C+ mode calculating UDP checksum for "
|
|
||||||
- "packet with %d bytes data\n", ip_data_len);
|
|
||||||
+ p_tcp_hdr->th_sum = tcp_checksum;
|
|
||||||
|
|
||||||
- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
- p_udpip_hdr->zeros = 0;
|
|
||||||
- p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
|
||||||
- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
|
||||||
+ /* restore IP header */
|
|
||||||
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
|
||||||
|
|
||||||
- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
|
||||||
+ /* set IP data length and recalculate IP checksum */
|
|
||||||
+ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
|
|
||||||
|
|
||||||
- p_udp_hdr->uh_sum = 0;
|
|
||||||
+ /* increment IP id for subsequent frames */
|
|
||||||
+ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
|
|
||||||
|
|
||||||
- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
|
||||||
- DPRINTF("+++ C+ mode UDP checksum %04x\n",
|
|
||||||
- udp_checksum);
|
|
||||||
+ ip->ip_sum = 0;
|
|
||||||
+ ip->ip_sum = ip_checksum(eth_payload_data, hlen);
|
|
||||||
+ DPRINTF("+++ C+ mode TSO IP header len=%d "
|
|
||||||
+ "checksum=%04x\n", hlen, ip->ip_sum);
|
|
||||||
|
|
||||||
- p_udp_hdr->uh_sum = udp_checksum;
|
|
||||||
- }
|
|
||||||
+ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
|
|
||||||
+ DPRINTF("+++ C+ mode TSO transferring packet size "
|
|
||||||
+ "%d\n", tso_send_size);
|
|
||||||
+ rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
|
|
||||||
+ 0, (uint8_t *) dot1q_buffer);
|
|
||||||
|
|
||||||
- /* restore IP header */
|
|
||||||
- memcpy(eth_payload_data, saved_ip_header, hlen);
|
|
||||||
+ /* add transferred count to TCP sequence number */
|
|
||||||
+ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
|
|
||||||
+ ++send_count;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* Stop sending this frame */
|
|
||||||
+ saved_size = 0;
|
|
||||||
+ }
|
|
||||||
+ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
|
|
||||||
+ {
|
|
||||||
+ DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
|
|
||||||
+
|
|
||||||
+ /* maximum IP header length is 60 bytes */
|
|
||||||
+ uint8_t saved_ip_header[60];
|
|
||||||
+ memcpy(saved_ip_header, eth_payload_data, hlen);
|
|
||||||
+
|
|
||||||
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
|
|
||||||
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
|
|
||||||
+
|
|
||||||
+ /* add 4 TCP pseudoheader fields */
|
|
||||||
+ /* copy IP source and destination fields */
|
|
||||||
+ memcpy(data_to_checksum, saved_ip_header + 12, 8);
|
|
||||||
+
|
|
||||||
+ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
+ {
|
|
||||||
+ DPRINTF("+++ C+ mode calculating TCP checksum for "
|
|
||||||
+ "packet with %d bytes data\n", ip_data_len);
|
|
||||||
+
|
|
||||||
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
+ p_tcpip_hdr->zeros = 0;
|
|
||||||
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
|
|
||||||
+ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
|
||||||
+
|
|
||||||
+ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
|
|
||||||
+
|
|
||||||
+ p_tcp_hdr->th_sum = 0;
|
|
||||||
+
|
|
||||||
+ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
|
||||||
+ DPRINTF("+++ C+ mode TCP checksum %04x\n",
|
|
||||||
+ tcp_checksum);
|
|
||||||
+
|
|
||||||
+ p_tcp_hdr->th_sum = tcp_checksum;
|
|
||||||
+ }
|
|
||||||
+ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
|
|
||||||
+ {
|
|
||||||
+ DPRINTF("+++ C+ mode calculating UDP checksum for "
|
|
||||||
+ "packet with %d bytes data\n", ip_data_len);
|
|
||||||
+
|
|
||||||
+ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
|
|
||||||
+ p_udpip_hdr->zeros = 0;
|
|
||||||
+ p_udpip_hdr->ip_proto = IP_PROTO_UDP;
|
|
||||||
+ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
|
|
||||||
+
|
|
||||||
+ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
|
|
||||||
+
|
|
||||||
+ p_udp_hdr->uh_sum = 0;
|
|
||||||
+
|
|
||||||
+ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
|
|
||||||
+ DPRINTF("+++ C+ mode UDP checksum %04x\n",
|
|
||||||
+ udp_checksum);
|
|
||||||
+
|
|
||||||
+ p_udp_hdr->uh_sum = udp_checksum;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* restore IP header */
|
|
||||||
+ memcpy(eth_payload_data, saved_ip_header, hlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
From 043d28507ef7c5fdc34866f5e3b27a72bd0cd072 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:17:00 +0100
|
|
||||||
Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header
|
|
||||||
|
|
||||||
Transmit offload features access Ethernet and IP headers the packet. If
|
|
||||||
the packet is too short we must not attempt to access header fields:
|
|
||||||
|
|
||||||
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
|
||||||
...
|
|
||||||
eth_payload_data = saved_buffer + ETH_HLEN;
|
|
||||||
...
|
|
||||||
ip = (ip_header*)eth_payload_data;
|
|
||||||
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 5 +++++
|
|
||||||
1 file changed, 5 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index 2f12d42..d377b6b 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2164,6 +2164,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
{
|
|
||||||
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
|
||||||
|
|
||||||
+ /* Large enough for Ethernet and IP headers? */
|
|
||||||
+ if (saved_size < ETH_HLEN + sizeof(ip_header)) {
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* ip packet header */
|
|
||||||
ip_header *ip = NULL;
|
|
||||||
int hlen = 0;
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
From 5a75d242fe019d05b46ef9bc330a6892525c84a7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:17:01 +0100
|
|
||||||
Subject: [PATCH 4/7] rtl8139: check IP Header Length field
|
|
||||||
|
|
||||||
The IP Header Length field was only checked in the IP checksum case, but
|
|
||||||
is used in other cases too.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 19 ++++++++-----------
|
|
||||||
1 file changed, 8 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index d377b6b..cd5ac05 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2200,6 +2200,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
}
|
|
||||||
|
|
||||||
hlen = IP_HEADER_LENGTH(ip);
|
|
||||||
+ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
ip_protocol = ip->ip_p;
|
|
||||||
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
|
|
||||||
@@ -2207,17 +2211,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
{
|
|
||||||
DPRINTF("+++ C+ mode need IP checksum\n");
|
|
||||||
|
|
||||||
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
|
|
||||||
- /* bad packet header len */
|
|
||||||
- /* or packet too short */
|
|
||||||
- }
|
|
||||||
- else
|
|
||||||
- {
|
|
||||||
- ip->ip_sum = 0;
|
|
||||||
- ip->ip_sum = ip_checksum(ip, hlen);
|
|
||||||
- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
|
||||||
- hlen, ip->ip_sum);
|
|
||||||
- }
|
|
||||||
+ ip->ip_sum = 0;
|
|
||||||
+ ip->ip_sum = ip_checksum(ip, hlen);
|
|
||||||
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
|
||||||
+ hlen, ip->ip_sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
From 6c79ea275d72bc1fd88bdcf1e7d231b2c9c865de Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:17:02 +0100
|
|
||||||
Subject: [PATCH 5/7] rtl8139: check IP Total Length field
|
|
||||||
|
|
||||||
The IP Total Length field includes the IP header and data. Make sure it
|
|
||||||
is valid and does not exceed the Ethernet payload size.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 7 ++++++-
|
|
||||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index cd5ac05..ed2b23b 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2205,7 +2205,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_protocol = ip->ip_p;
|
|
||||||
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
+
|
|
||||||
+ ip_data_len = be16_to_cpu(ip->ip_len);
|
|
||||||
+ if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+ ip_data_len -= hlen;
|
|
||||||
|
|
||||||
if (txdw0 & CP_TX_IPCS)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
From 30aa7be430e7c982e9163f3bcc745d3aa57b6aa4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:17:03 +0100
|
|
||||||
Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header
|
|
||||||
|
|
||||||
TCP Large Segment Offload accesses the TCP header in the packet. If the
|
|
||||||
packet is too short we must not attempt to access header fields:
|
|
||||||
|
|
||||||
tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
|
|
||||||
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 5 +++++
|
|
||||||
1 file changed, 5 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index ed2b23b..c8f0df9 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2224,6 +2224,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
|
|
||||||
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
|
||||||
{
|
|
||||||
+ /* Large enough for the TCP header? */
|
|
||||||
+ if (ip_data_len < sizeof(tcp_header)) {
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
|
||||||
|
|
||||||
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
From 9a084807bf6ca7c16d997a236d304111894a6539 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Wed, 15 Jul 2015 18:17:04 +0100
|
|
||||||
Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field
|
|
||||||
|
|
||||||
The TCP Data Offset field contains the length of the header. Make sure
|
|
||||||
it is valid and does not exceed the IP data length.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
hw/net/rtl8139.c | 5 +++++
|
|
||||||
1 file changed, 5 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
|
|
||||||
index c8f0df9..2df4a51 100644
|
|
||||||
--- a/hw/net/rtl8139.c
|
|
||||||
+++ b/hw/net/rtl8139.c
|
|
||||||
@@ -2253,6 +2253,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
|
||||||
|
|
||||||
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
|
||||||
|
|
||||||
+ /* Invalid TCP data offset? */
|
|
||||||
+ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
|
|
||||||
+ goto skip_offload;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* ETH_MTU = ip header len + tcp header len + payload */
|
|
||||||
int tcp_data_len = ip_data_len - tcp_hlen;
|
|
||||||
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
|
||||||
--
|
|
||||||
2.1.4
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
From 07ca00703f76ad392eda5ee52cce1197cf49c30a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
|
||||||
Subject: [PATCH v2.1 for-4.5] libxl: handle read-only drives with qemu-xen
|
|
||||||
|
|
||||||
The current libxl code doesn't deal with read-only drives at all.
|
|
||||||
|
|
||||||
Upstream QEMU and qemu-xen only support read-only cdrom drives: make
|
|
||||||
sure to specify "readonly=on" for cdrom drives and return error in case
|
|
||||||
the user requested a non-cdrom read-only drive.
|
|
||||||
|
|
||||||
This is XSA-142, discovered by Lin Liu
|
|
||||||
(https://bugzilla.redhat.com/show_bug.cgi?id=1257893).
|
|
||||||
|
|
||||||
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
|
||||||
|
|
||||||
Backport to Xen 4.5 and earlier, apropos of report and review from
|
|
||||||
Michael Young.
|
|
||||||
|
|
||||||
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
|
|
||||||
---
|
|
||||||
tools/libxl/libxl_dm.c | 13 +++++++++----
|
|
||||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
|
|
||||||
index b4ce523..d74fb14 100644
|
|
||||||
--- a/tools/libxl/libxl_dm.c
|
|
||||||
+++ b/tools/libxl/libxl_dm.c
|
|
||||||
@@ -797,13 +797,18 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
|
|
||||||
if (disks[i].is_cdrom) {
|
|
||||||
if (disks[i].format == LIBXL_DISK_FORMAT_EMPTY)
|
|
||||||
drive = libxl__sprintf
|
|
||||||
- (gc, "if=ide,index=%d,media=cdrom,cache=writeback,id=ide-%i",
|
|
||||||
- disk, dev_number);
|
|
||||||
+ (gc, "if=ide,index=%d,readonly=%s,media=cdrom,cache=writeback,id=ide-%i",
|
|
||||||
+ disk, disks[i].readwrite ? "off" : "on", dev_number);
|
|
||||||
else
|
|
||||||
drive = libxl__sprintf
|
|
||||||
- (gc, "file=%s,if=ide,index=%d,media=cdrom,format=%s,cache=writeback,id=ide-%i",
|
|
||||||
- disks[i].pdev_path, disk, format, dev_number);
|
|
||||||
+ (gc, "file=%s,if=ide,index=%d,readonly=%s,media=cdrom,format=%s,cache=writeback,id=ide-%i",
|
|
||||||
+ disks[i].pdev_path, disk, disks[i].readwrite ? "off" : "on", format, dev_number);
|
|
||||||
} else {
|
|
||||||
+ if (!disks[i].readwrite) {
|
|
||||||
+ LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "qemu-xen doesn't support read-only disk drivers");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (disks[i].format == LIBXL_DISK_FORMAT_EMPTY) {
|
|
||||||
LIBXL__LOG(ctx, LIBXL__LOG_WARNING, "cannot support"
|
|
||||||
" empty disk format for %s", disks[i].vdev);
|
|
||||||
--
|
|
||||||
1.7.10.4
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
From 27593ec62bdad8621df910931349d964a6dbaa8c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ian Jackson <ian.jackson@eu.citrix.com>
|
|
||||||
Date: Wed, 21 Oct 2015 16:18:30 +0100
|
|
||||||
Subject: [PATCH XSA-153 v3] libxl: adjust PoD target by memory fudge, too
|
|
||||||
|
|
||||||
PoD guests need to balloon at least as far as required by PoD, or risk
|
|
||||||
crashing. Currently they don't necessarily know what the right value
|
|
||||||
is, because our memory accounting is (at the very least) confusing.
|
|
||||||
|
|
||||||
Apply the memory limit fudge factor to the in-hypervisor PoD memory
|
|
||||||
target, too. This will increase the size of the guest's PoD cache by
|
|
||||||
the fudge factor LIBXL_MAXMEM_CONSTANT (currently 1Mby). This ensures
|
|
||||||
that even with a slightly-off balloon driver, the guest will be
|
|
||||||
stable even under memory pressure.
|
|
||||||
|
|
||||||
There are two call sites of xc_domain_set_pod_target that need fixing:
|
|
||||||
|
|
||||||
The one in libxl_set_memory_target is straightforward.
|
|
||||||
|
|
||||||
The one in xc_hvm_build_x86.c:setup_guest is more awkward. Simply
|
|
||||||
setting the PoD target differently does not work because the various
|
|
||||||
amounts of memory during domain construction no longer match up.
|
|
||||||
Instead, we adjust the guest memory target in xenstore (but only for
|
|
||||||
PoD guests).
|
|
||||||
|
|
||||||
This introduces a 1Mby discrepancy between the balloon target of a PoD
|
|
||||||
guest at boot, and the target set by an apparently-equivalent `xl
|
|
||||||
mem-set' (or similar) later. This approach is low-risk for a security
|
|
||||||
fix but we need to fix this up properly in xen.git#staging and
|
|
||||||
probably also in stable trees.
|
|
||||||
|
|
||||||
This is XSA-153.
|
|
||||||
|
|
||||||
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
|
|
||||||
---
|
|
||||||
tools/libxl/libxl.c | 2 +-
|
|
||||||
tools/libxl/libxl_dom.c | 9 ++++++++-
|
|
||||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
|
|
||||||
index d38d0c7..1366177 100644
|
|
||||||
--- a/tools/libxl/libxl.c
|
|
||||||
+++ b/tools/libxl/libxl.c
|
|
||||||
@@ -4815,7 +4815,7 @@ retry_transaction:
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = xc_domain_set_pod_target(ctx->xch, domid,
|
|
||||||
- new_target_memkb / 4, NULL, NULL, NULL);
|
|
||||||
+ (new_target_memkb + LIBXL_MAXMEM_CONSTANT) / 4, NULL, NULL, NULL);
|
|
||||||
if (rc != 0) {
|
|
||||||
LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
|
|
||||||
"xc_domain_set_pod_target domid=%d, memkb=%d "
|
|
||||||
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
|
|
||||||
index b514377..8019f4e 100644
|
|
||||||
--- a/tools/libxl/libxl_dom.c
|
|
||||||
+++ b/tools/libxl/libxl_dom.c
|
|
||||||
@@ -486,6 +486,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
|
|
||||||
xs_transaction_t t;
|
|
||||||
char **ents;
|
|
||||||
int i, rc;
|
|
||||||
+ int64_t mem_target_fudge;
|
|
||||||
|
|
||||||
if (info->num_vnuma_nodes && !info->num_vcpu_soft_affinity) {
|
|
||||||
rc = set_vnuma_affinity(gc, domid, info);
|
|
||||||
@@ -518,11 +519,17 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ mem_target_fudge =
|
|
||||||
+ (info->type == LIBXL_DOMAIN_TYPE_HVM &&
|
|
||||||
+ info->max_memkb > info->target_memkb)
|
|
||||||
+ ? LIBXL_MAXMEM_CONSTANT : 0;
|
|
||||||
+
|
|
||||||
ents = libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
|
|
||||||
ents[0] = "memory/static-max";
|
|
||||||
ents[1] = GCSPRINTF("%"PRId64, info->max_memkb);
|
|
||||||
ents[2] = "memory/target";
|
|
||||||
- ents[3] = GCSPRINTF("%"PRId64, info->target_memkb - info->video_memkb);
|
|
||||||
+ ents[3] = GCSPRINTF("%"PRId64, info->target_memkb - info->video_memkb
|
|
||||||
+ - mem_target_fudge);
|
|
||||||
ents[4] = "memory/videoram";
|
|
||||||
ents[5] = GCSPRINTF("%"PRId64, info->video_memkb);
|
|
||||||
ents[6] = "domid";
|
|
||||||
--
|
|
||||||
1.7.10.4
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue