| From: Takashi Iwai <tiwai@suse.de> |
| Date: Fri, 13 Apr 2018 15:35:13 -0700 |
| Subject: resource: fix integer overflow at reallocation |
| |
| commit 60bb83b81169820c691fbfa33a6a4aef32aa4b0b upstream. |
| |
| We've got a bug report indicating a kernel panic at booting on an x86-32 |
| system, and it turned out to be the invalid PCI resource assigned after |
| reallocation. __find_resource() first aligns the resource start address |
| and resets the end address with start+size-1 accordingly, then checks |
| whether it's contained. Here the end address may overflow the integer, |
| although resource_contains() still returns true because the function |
| validates only start and end address. So this ends up with returning an |
| invalid resource (start > end). |
| |
| There was already an attempt to cover such a problem in the commit |
| 47ea91b4052d ("Resource: fix wrong resource window calculation"), but |
| this case is an overseen one. |
| |
| This patch adds the validity check of the newly calculated resource for |
| avoiding the integer overflow problem. |
| |
| Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1086739 |
| Link: http://lkml.kernel.org/r/s5hpo37d5l8.wl-tiwai@suse.de |
| Fixes: 23c570a67448 ("resource: ability to resize an allocated resource") |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Reported-by: Michael Henders <hendersm@shaw.ca> |
| Tested-by: Michael Henders <hendersm@shaw.ca> |
| Reviewed-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Ram Pai <linuxram@us.ibm.com> |
| Cc: Bjorn Helgaas <bhelgaas@google.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| kernel/resource.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/resource.c |
| +++ b/kernel/resource.c |
| @@ -474,7 +474,8 @@ static int __find_resource(struct resour |
| alloc.start = constraint->alignf(constraint->alignf_data, &avail, |
| size, constraint->align); |
| alloc.end = alloc.start + size - 1; |
| - if (resource_contains(&avail, &alloc)) { |
| + if (alloc.start <= alloc.end && |
| + resource_contains(&avail, &alloc)) { |
| new->start = alloc.start; |
| new->end = alloc.end; |
| return 0; |