ACPI: Implement proper length checks for mem resources
authorThomas Gleixner <tglx@linutronix.de>
Mon, 2 Feb 2015 02:42:48 +0000 (10:42 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 3 Feb 2015 21:27:16 +0000 (22:27 +0100)
Check whether the resulting length is the same as the given
length. Check for start <= end as well.

We need to hand in the resource for this, so we can apply the flags
directly.

[Jiang] Remove enforcement that resource starting address must be
non-zero.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/resource.c

index 1c616a56e007575df66620ad9256762533e750bb..3e7d9f6eb875f24c062131325aaa1d290a0aef9e 100644 (file)
 #define valid_IRQ(i) (true)
 #endif
 
-static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
-                                               bool window)
+static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
 {
-       unsigned long flags = IORESOURCE_MEM;
+       u64 reslen = end - start + 1;
 
-       if (len == 0)
-               flags |= IORESOURCE_DISABLED;
+       /*
+        * CHECKME: len might be required to check versus a minimum
+        * length as well. 1 for io is fine, but for memory it does
+        * not make any sense at all.
+        */
+       if (len && reslen && reslen == len && start <= end)
+               return true;
+
+       pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+               io ? "io" : "mem", start, end, len);
+
+       return false;
+}
+
+static void acpi_dev_memresource_flags(struct resource *res, u64 len,
+                                      u8 write_protect, bool window)
+{
+       res->flags = IORESOURCE_MEM;
+
+       if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
+               res->flags |= IORESOURCE_DISABLED;
 
        if (write_protect == ACPI_READ_WRITE_MEMORY)
-               flags |= IORESOURCE_MEM_WRITEABLE;
+               res->flags |= IORESOURCE_MEM_WRITEABLE;
 
        if (window)
-               flags |= IORESOURCE_WINDOW;
-
-       return flags;
+               res->flags |= IORESOURCE_WINDOW;
 }
 
 static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
@@ -56,7 +72,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
 {
        res->start = start;
        res->end = start + len - 1;
-       res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+       acpi_dev_memresource_flags(res, len, write_protect, false);
 }
 
 /**
@@ -77,24 +93,18 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
        switch (ares->type) {
        case ACPI_RESOURCE_TYPE_MEMORY24:
                memory24 = &ares->data.memory24;
-               if (!memory24->minimum && !memory24->address_length)
-                       return false;
                acpi_dev_get_memresource(res, memory24->minimum,
                                         memory24->address_length,
                                         memory24->write_protect);
                break;
        case ACPI_RESOURCE_TYPE_MEMORY32:
                memory32 = &ares->data.memory32;
-               if (!memory32->minimum && !memory32->address_length)
-                       return false;
                acpi_dev_get_memresource(res, memory32->minimum,
                                         memory32->address_length,
                                         memory32->write_protect);
                break;
        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
                fixed_memory32 = &ares->data.fixed_memory32;
-               if (!fixed_memory32->address && !fixed_memory32->address_length)
-                       return false;
                acpi_dev_get_memresource(res, fixed_memory32->address,
                                         fixed_memory32->address_length,
                                         fixed_memory32->write_protect);
@@ -102,7 +112,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
        default:
                return false;
        }
-       return true;
+
+       return !(res->flags & IORESOURCE_DISABLED);
 }
 EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
 
@@ -186,7 +197,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
        acpi_status status;
        struct acpi_resource_address64 addr;
        bool window;
-       u64 len;
        u8 io_decode;
 
        status = acpi_resource_to_address64(ares, &addr);
@@ -199,10 +209,9 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
 
        switch(addr.resource_type) {
        case ACPI_MEMORY_RANGE:
-               len = addr.address.maximum - addr.address.minimum + 1;
-               res->flags = acpi_dev_memresource_flags(len,
-                                               addr.info.mem.write_protect,
-                                               window);
+               acpi_dev_memresource_flags(res, addr.address.address_length,
+                                          addr.info.mem.write_protect,
+                                          window);
                break;
        case ACPI_IO_RANGE:
                io_decode = addr.address.granularity == 0xfff ?
@@ -236,7 +245,6 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
 {
        struct acpi_resource_extended_address64 *ext_addr;
        bool window;
-       u64 len;
        u8 io_decode;
 
        if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
@@ -250,10 +258,10 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
 
        switch(ext_addr->resource_type) {
        case ACPI_MEMORY_RANGE:
-               len = ext_addr->address.maximum - ext_addr->address.minimum + 1;
-               res->flags = acpi_dev_memresource_flags(len,
-                                       ext_addr->info.mem.write_protect,
-                                       window);
+               acpi_dev_memresource_flags(res,
+                                          ext_addr->address.address_length,
+                                          ext_addr->info.mem.write_protect,
+                                          window);
                break;
        case ACPI_IO_RANGE:
                io_decode = ext_addr->address.granularity == 0xfff ?