From 103b4a31567fbbea27a38dfbd5f8e1ca3a870869 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 30 Sep 2011 21:16:43 +0100 Subject: X86 MCE: Prevent malicious guest access broken page again To avoid recursive mce. Signed-off-by: Liu, Jinsong Committed-by: Keir Fraser --- xen/arch/x86/cpu/mcheck/mce_intel.c | 2 ++ xen/common/page_alloc.c | 14 ++++++++++++++ xen/include/public/sysctl.h | 1 + 3 files changed, 17 insertions(+) diff --git a/xen/arch/x86/cpu/mcheck/mce_intel.c b/xen/arch/x86/cpu/mcheck/mce_intel.c index bf75f6714c..86191ac2d5 100644 --- a/xen/arch/x86/cpu/mcheck/mce_intel.c +++ b/xen/arch/x86/cpu/mcheck/mce_intel.c @@ -657,6 +657,8 @@ static void intel_memerr_dhandler( /* This is free page */ if (status & PG_OFFLINE_OFFLINED) *result = MCER_RECOVERED; + else if (status & PG_OFFLINE_AGAIN) + *result = MCER_CONTINUE; else if (status & PG_OFFLINE_PENDING) { /* This page has owner */ if (status & PG_OFFLINE_OWNED) { diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index f38d1ff986..3ce34af440 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -708,6 +709,19 @@ int offline_page(unsigned long mfn, int broken, uint32_t *status) return -EINVAL; } + /* + * NB. When broken page belong to guest, usually hypervisor will + * notify the guest to handle the broken page. However, hypervisor + * need to prevent malicious guest access the broken page again. + * Under such case, hypervisor shutdown guest, preventing recursive mce. + */ + if ( (pg->count_info & PGC_broken) && (owner = page_get_owner(pg)) ) + { + *status = PG_OFFLINE_AGAIN; + domain_shutdown(owner, SHUTDOWN_crash); + return 0; + } + spin_lock(&heap_lock); old_info = mark_page_offline(pg, broken); diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index c10a85d1f8..88648c4286 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -399,6 +399,7 @@ struct xen_sysctl_page_offline_op { #define PG_OFFLINE_OFFLINED (0x1UL << 1) #define PG_OFFLINE_PENDING (0x1UL << 2) #define PG_OFFLINE_FAILED (0x1UL << 3) +#define PG_OFFLINE_AGAIN (0x1UL << 4) #define PG_ONLINE_FAILED PG_OFFLINE_FAILED #define PG_ONLINE_ONLINED PG_OFFLINE_OFFLINED -- cgit v1.2.3