debuggers.hg

changeset 21112:f42ff98a2cdc

VT-d: Sanity check ACPI DMAR struct lengths.

Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Mar 25 09:32:21 2010 +0000 (2010-03-25)
parents e362fab06d42
children 18f4db5f72d7
files xen/drivers/passthrough/vtd/dmar.c
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/dmar.c	Thu Mar 25 09:19:33 2010 +0000
     1.2 +++ b/xen/drivers/passthrough/vtd/dmar.c	Thu Mar 25 09:32:21 2010 +0000
     1.3 @@ -361,6 +361,17 @@ static int __init acpi_parse_dev_scope(v
     1.4      return 0;
     1.5  }
     1.6  
     1.7 +static int __init acpi_dmar_check_length(
     1.8 +    struct acpi_dmar_entry_header *h, unsigned int min_len)
     1.9 +{
    1.10 +    if ( h->length >= min_len )
    1.11 +        return 0;
    1.12 +    dprintk(XENLOG_ERR VTDPREFIX,
    1.13 +            "Invalid ACPI DMAR entry length: 0x%x\n",
    1.14 +            h->length);
    1.15 +    return -EINVAL;
    1.16 +}
    1.17 +
    1.18  static int __init
    1.19  acpi_parse_one_drhd(struct acpi_dmar_entry_header *header)
    1.20  {
    1.21 @@ -368,9 +379,12 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
    1.22      void *dev_scope_start, *dev_scope_end;
    1.23      struct acpi_drhd_unit *dmaru;
    1.24      void *addr;
    1.25 -    int ret = 0;
    1.26 +    int ret;
    1.27      static int include_all = 0;
    1.28  
    1.29 +    if ( (ret = acpi_dmar_check_length(header, sizeof(*drhd))) != 0 )
    1.30 +        return ret;
    1.31 +
    1.32      dmaru = xmalloc(struct acpi_drhd_unit);
    1.33      if ( !dmaru )
    1.34          return -ENOMEM;
    1.35 @@ -470,7 +484,10 @@ acpi_parse_one_rmrr(struct acpi_dmar_ent
    1.36      struct acpi_rmrr_unit *rmrru;
    1.37      void *dev_scope_start, *dev_scope_end;
    1.38      u64 base_addr = rmrr->base_address, end_addr = rmrr->end_address;
    1.39 -    int ret = 0;
    1.40 +    int ret;
    1.41 +
    1.42 +    if ( (ret = acpi_dmar_check_length(header, sizeof(*rmrr))) != 0 )
    1.43 +        return ret;
    1.44  
    1.45  #ifdef CONFIG_X86
    1.46      /* This check is here simply to detect when RMRR values are
    1.47 @@ -564,10 +581,13 @@ acpi_parse_one_atsr(struct acpi_dmar_ent
    1.48  {
    1.49      struct acpi_table_atsr *atsr = (struct acpi_table_atsr *)header;
    1.50      struct acpi_atsr_unit *atsru;
    1.51 -    int ret = 0;
    1.52 +    int ret;
    1.53      static int all_ports;
    1.54      void *dev_scope_start, *dev_scope_end;
    1.55  
    1.56 +    if ( (ret = acpi_dmar_check_length(header, sizeof(*atsr))) != 0 )
    1.57 +        return ret;
    1.58 +
    1.59      atsru = xmalloc(struct acpi_atsr_unit);
    1.60      if ( !atsru )
    1.61          return -ENOMEM;
    1.62 @@ -610,7 +630,10 @@ acpi_parse_one_rhsa(struct acpi_dmar_ent
    1.63  {
    1.64      struct acpi_table_rhsa *rhsa = (struct acpi_table_rhsa *)header;
    1.65      struct acpi_rhsa_unit *rhsau;
    1.66 -    int ret = 0;
    1.67 +    int ret;
    1.68 +
    1.69 +    if ( (ret = acpi_dmar_check_length(header, sizeof(*rhsa))) != 0 )
    1.70 +        return ret;
    1.71  
    1.72      rhsau = xmalloc(struct acpi_rhsa_unit);
    1.73      if ( !rhsau )
    1.74 @@ -659,6 +682,11 @@ static int __init acpi_parse_dmar(struct
    1.75      while ( ((unsigned long)entry_header) <
    1.76              (((unsigned long)dmar) + table->length) )
    1.77      {
    1.78 +        ret = acpi_dmar_check_length(
    1.79 +            entry_header, sizeof(struct acpi_dmar_entry_header));
    1.80 +        if ( ret )
    1.81 +            break;
    1.82 +
    1.83          switch ( entry_header->type )
    1.84          {
    1.85          case ACPI_DMAR_DRHD: