From mboxrd@z Thu Jan 1 00:00:00 1970 From: Weidong Han Subject: Re: Xen 4.0.0-rc7 problem/hang with vt-d DMAR parsing Date: Wed, 24 Mar 2010 19:00:17 +0800 Message-ID: <4BA9F0C1.7080809@intel.com> References: <20100323193748.GW1878@reaktio.net> <20100323200515.GZ1878@reaktio.net> <4BA9DA400200007800036ABB@vpn.id2.novell.com> <4BA9D512.9090902@intel.com> <4BA9ED8D0200007800036B3F@vpn.id2.novell.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <4BA9ED8D0200007800036B3F@vpn.id2.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Jan Beulich Cc: "xen-devel@lists.xensource.com" , Keir Fraser , "Cui, Dexuan" List-Id: xen-devel@lists.xenproject.org Jan Beulich wrote: >>>> Weidong Han 24.03.10 10:02 >>> >>>> >> it cannot check entry_header->length < sizeof(struct acpi_table_XXX), >> which is not the actual size in acpi table. >> > > I don't follow here: Minimally checking against > sizeof(struct acpi_dmar_entry_header) should be possible. But I can't > even see why checking for sizeof(struct acpi_table_XXX) in the > individual case statements can't be done. > > Jan > Re-checked the code. You're right. Updated the patch to check with sizeof(struct acpi_table_XXX). Idea-by: Jan Beulich > Signed-off-by: Weidong Han diff -r a4eac162dcb9 xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Thu Mar 25 01:05:03 2010 +0800 +++ b/xen/drivers/passthrough/vtd/dmar.c Thu Mar 25 03:53:21 2010 +0800 @@ -659,6 +659,23 @@ static int __init acpi_parse_dmar(struct while ( ((unsigned long)entry_header) < (((unsigned long)dmar) + table->length) ) { + /* + * entry_header length should not smaller than size of + * any acpi dmar structures. also avoid endless looping + * when the lenght is 0 on some bad BIOSs + */ + if ( entry_header->length < sizeof(struct acpi_table_drhd) && + entry_header->length < sizeof(struct acpi_table_rmrr) && + entry_header->length < sizeof(struct acpi_table_atsr) && + entry_header->length < sizeof(struct acpi_table_rhsa) ) + { + dprintk(XENLOG_WARNING VTDPREFIX, + "Invalid entry_header length: 0x%x\n", + entry_header->length); + ret = -EINVAL; + break; + } + switch ( entry_header->type ) { case ACPI_DMAR_DRHD: