PATCH - bug in vfree

Neil Booth
1999-02-20T11:44:54Z

[-- Attachment #1: Type: text/plain, Size: 1150 bytes --]

Linus,

I posted this bug on the kernel mailing list last year, but it never got
fixed, probably as I didn't include a patch. I attach a patch this time
against kernel 2.2.1. The bug is rare, but can lead to kernel virtual
memory corruption.

Quick description:- vfree forgets to subtract the extra cushion page
from the size of each virtual memory area stored in vmlist when it calls
vmfree_area_pages. This means that only the vmalloc-requested size is
allocated by vmalloc_area_pages, but the requested size PLUS the cushion
page is freed by vmfree_area_pages.

More deeply:- Close inspection of get_vm_area reveals that
(intentionally?) it does NOT insist there be a cushion page behind a VMA
that is placed in front of a previously-allocated VMA, it ONLY
guarantees that a cushion page lies in front of newly-allocated VMAs.
Thus two VMAs could be immediately adjacent without a cushion page, and
coupled with the vfree bug means that vfree-ing the first VMA also frees
the first page of the second VMA, with dire consequences.

I have described this as clearly as I can, I hope it makes sense. Alan,
this same bug also exists in 2.0.36.

Neil.

[-- Attachment #2: vfree-patch --]
[-- Type: text/plain, Size: 384 bytes --]

--- linux/mm/vmalloc.c~ Sun Jan 24 19:21:06 1999
+++ linux/mm/vmalloc.c Sat Feb 20 20:17:11 1999
@@ -187,7 +187,7 @@
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
- vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+ vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size - PAGE_SIZE);
kfree(tmp);
return;
}