/* read ahead limits */
extern int vm_min_readahead;
extern int vm_max_readahead;
+extern unsigned long mmap_min_addr;
/*
* mapping from the currently active vm_flags protection bits (the
* page_table_lock lock to serialize against concurrent expand_stacks.
*/
address &= PAGE_MASK;
+
+ /* ensure a non-privileged process is not trying to mmap lower pages */
+ if (address < mmap_min_addr && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
spin_lock(&vma->vm_mm->page_table_lock);
/* already expanded while we were spinning? */
VM_LAPTOP_MODE=21, /* kernel in laptop flush mode */
VM_BLOCK_DUMP=22, /* dump fs activity to log */
VM_ANON_LRU=23, /* immediatly insert anon pages in the vm page lru */
+ VM_MMAP_MIN_ADDR=24, /* prevent mapping of low addresses by mmap() */
};
&laptop_mode, sizeof(int), 0644, NULL, &proc_dointvec},
{VM_BLOCK_DUMP, "block_dump",
&block_dump, sizeof(int), 0644, NULL, &proc_dointvec},
+ {VM_MMAP_MIN_ADDR, "mmap_min_addr",
+ &mmap_min_addr, sizeof(unsigned long), 0644, NULL, &proc_doulongvec_minmax},
{0}
};
};
int sysctl_overcommit_memory;
+unsigned long mmap_min_addr; /* defaults to 0 = no protection */
+
int max_map_count = DEFAULT_MAX_MAP_COUNT;
/* Check that a process has enough memory to allocate a
return -ENOMEM;
if (addr & ~PAGE_MASK)
return -EINVAL;
+
+ /* Ensure a non-privileged process is not trying to map
+ * lower pages.
+ */
+ if (addr < mmap_min_addr && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
return addr;
}
if (file && file->f_op && file->f_op->get_unmapped_area)
- return file->f_op->get_unmapped_area(file, addr, len, pgoff, flags);
+ addr = file->f_op->get_unmapped_area(file, addr, len, pgoff, flags);
+ else
+ addr = arch_get_unmapped_area(file, addr, len, pgoff, flags);
+
+ if (addr < mmap_min_addr && !capable(CAP_SYS_RAWIO))
+ return -ENOMEM;
- return arch_get_unmapped_area(file, addr, len, pgoff, flags);
+ return addr;
}
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
if ((addr <= new_addr) && (addr+old_len) > new_addr)
goto out;
+ /* Ensure a non-privileged process is not trying to map
+ * lower pages.
+ */
+ if (new_addr < mmap_min_addr && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
ret = do_munmap(current->mm, new_addr, new_len);
if (ret && new_len)
goto out;