Messages in this thread Patch in this message | | | Date | Thu, 30 Oct 1997 13:45:17 -0500 | From | Bill Hawes <> | Subject | minor patch for mm/mmap.c (repost) |
| |
If we're going to have a code-slush, I'll have to get all of my patches ready to send in ...
The attached minor patch adds some error checking for unmap operations in mm/mmap.c. It was originally posted for 2.1.53 but still applies cleanly to 2.1.60.
Regards, Bill--- mm/mmap.c.old Wed Sep 3 17:57:51 1997 +++ mm/mmap.c Fri Sep 5 09:35:21 1997 @@ -92,25 +92,21 @@ struct mm_struct *mm = current->mm; lock_kernel(); - retval = mm->brk; if (brk < mm->end_code) goto out; newbrk = PAGE_ALIGN(brk); oldbrk = PAGE_ALIGN(mm->brk); - if (oldbrk == newbrk) { - retval = mm->brk = brk; - goto out; - } + if (oldbrk == newbrk) + goto set_brk; /* Always allow shrinking brk. */ if (brk <= mm->brk) { - retval = mm->brk = brk; - do_munmap(newbrk, oldbrk-newbrk); + if (!do_munmap(newbrk, oldbrk-newbrk)) + goto set_brk; goto out; } /* Check against rlimit and stack.. */ - retval = mm->brk; rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; @@ -126,12 +122,14 @@ goto out; /* Ok, looks good - let it rip. */ - if(do_mmap(NULL, oldbrk, newbrk-oldbrk, + if (do_mmap(NULL, oldbrk, newbrk-oldbrk, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0) == oldbrk) - mm->brk = brk; - retval = mm->brk; + MAP_FIXED|MAP_PRIVATE, 0) != oldbrk) + goto out; +set_brk: + mm->brk = brk; out: + retval = mm->brk; unlock_kernel(); return retval; } @@ -163,7 +161,7 @@ { struct mm_struct * mm = current->mm; struct vm_area_struct * vma; - int correct_wcount = 0; + int correct_wcount = 0, error; if ((len = PAGE_ALIGN(len)) == 0) return addr; @@ -262,26 +260,24 @@ vma->vm_dentry = NULL; vma->vm_pte = 0; - do_munmap(addr, len); /* Clear old maps */ + /* Clear old maps */ + error = -ENOMEM; + if (do_munmap(addr, len)) + goto free_vma; /* Check against address space limit. */ if ((mm->total_vm << PAGE_SHIFT) + len - > current->rlim[RLIMIT_AS].rlim_cur) { - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } + > current->rlim[RLIMIT_AS].rlim_cur) + goto free_vma; /* Private writable mapping? Check memory availability.. */ - if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) { - if (!(flags & MAP_NORESERVE) && - !vm_enough_memory(len >> PAGE_SHIFT)) { - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } - } + if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE && + !(flags & MAP_NORESERVE) && + !vm_enough_memory(len >> PAGE_SHIFT)) + goto free_vma; + error = 0; if (file) { - int error = 0; if (vma->vm_flags & VM_DENYWRITE) { if (file->f_dentry->d_inode->i_writecount > 0) error = -ETXTBSY; @@ -298,23 +294,22 @@ if (!error) error = file->f_op->mmap(file->f_dentry->d_inode, file, vma); - if (error) { - if (correct_wcount) - file->f_dentry->d_inode->i_writecount++; - kmem_cache_free(vm_area_cachep, vma); - return error; - } } + /* Fix up the count if necessary, then check for an error */ + if (correct_wcount) + file->f_dentry->d_inode->i_writecount++; + if (error) + goto free_vma; + /* + * merge_segments may merge our vma, so we can't refer to it + * after the call. Save the values we need now ... + */ flags = vma->vm_flags; + addr = vma->vm_start; /* can addr have changed?? */ insert_vm_struct(mm, vma); - if (correct_wcount) - file->f_dentry->d_inode->i_writecount++; merge_segments(mm, vma->vm_start, vma->vm_end); - addr = vma->vm_start; - - /* merge_segments might have merged our vma, so we can't use it any more */ mm->total_vm += len >> PAGE_SHIFT; if ((flags & VM_LOCKED) && !(flags & VM_IO)) { unsigned long start = addr; @@ -328,6 +323,10 @@ } while (len > 0); } return addr; + +free_vma: + kmem_cache_free(vm_area_cachep, vma); + return error; } /* Get an address range which is currently unmapped. | |