#include <linux/security.h>
#include <linux/mempolicy.h>
#include <linux/personality.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
static int
mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
- unsigned long start, unsigned long end, unsigned int newflags)
+ unsigned long start, unsigned long end, unsigned long newflags)
{
struct mm_struct * mm = vma->vm_mm;
+ unsigned long oldflags = vma->vm_flags;
+ long nrpages = (end - start) >> PAGE_SHIFT;
unsigned long charged = 0, old_end = vma->vm_end;
pgprot_t newprot;
- unsigned int oldflags;
pgoff_t pgoff;
int error;
- if (newflags == vma->vm_flags) {
+ if (newflags == oldflags) {
*pprev = vma;
return 0;
}
* a MAP_NORESERVE private mapping to writable will now reserve.
*/
if (newflags & VM_WRITE) {
- if (!(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) {
- charged = (end - start) >> PAGE_SHIFT;
+ if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) {
+ charged = nrpages;
if (security_vm_enough_memory(charged))
return -ENOMEM;
newflags |= VM_ACCOUNT;
* vm_flags and vm_page_prot are protected by the mmap_sem
* held in write mode.
*/
- vm_stat_unaccount(vma);
oldflags = vma->vm_flags;
vma->vm_flags = newflags;
vma->vm_page_prot = newprot;
if (oldflags & VM_EXEC)
arch_remove_exec_range(current->mm, old_end);
change_protection(vma, start, end, newprot);
- vm_stat_account(vma);
+ __vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
+ __vm_stat_account(mm, newflags, vma->vm_file, nrpages);
return 0;
fail:
prev = vma;
for (nstart = start ; ; ) {
- unsigned int newflags;
+ unsigned long newflags;
/* Here we know that vma->vm_start <= nstart < vma->vm_end. */