mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
[PATCH] NOMMU: Check VMA protections
Check the VMA protections in get_user_pages() against what's being asked. This checks to see that we don't accidentally write on a non-writable VMA or permit an I/O mapping VMA to be accessed (which may lack page structs). Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
910e46da4b
commit
7b4d5b8b39
30
mm/nommu.c
30
mm/nommu.c
@ -122,19 +122,35 @@ unsigned int kobjsize(const void *objp)
|
||||
}
|
||||
|
||||
/*
|
||||
* The nommu dodgy version :-)
|
||||
* get a list of pages in an address range belonging to the specified process
|
||||
* and indicate the VMA that covers each page
|
||||
* - this is potentially dodgy as we may end incrementing the page count of a
|
||||
* slab page or a secondary page from a compound page
|
||||
* - don't permit access to VMAs that don't support it, such as I/O mappings
|
||||
*/
|
||||
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, int len, int write, int force,
|
||||
struct page **pages, struct vm_area_struct **vmas)
|
||||
{
|
||||
int i;
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long vm_flags;
|
||||
int i;
|
||||
|
||||
/* calculate required read or write permissions.
|
||||
* - if 'force' is set, we only require the "MAY" flags.
|
||||
*/
|
||||
vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
|
||||
vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
vma = find_vma(mm, start);
|
||||
if(!vma)
|
||||
return i ? : -EFAULT;
|
||||
if (!vma)
|
||||
goto finish_or_fault;
|
||||
|
||||
/* protect what we can, including chardevs */
|
||||
if (vma->vm_flags & (VM_IO | VM_PFNMAP) ||
|
||||
!(vm_flags & vma->vm_flags))
|
||||
goto finish_or_fault;
|
||||
|
||||
if (pages) {
|
||||
pages[i] = virt_to_page(start);
|
||||
@ -145,7 +161,11 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
||||
vmas[i] = vma;
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
return(i);
|
||||
|
||||
return i;
|
||||
|
||||
finish_or_fault:
|
||||
return i ? : -EFAULT;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_user_pages);
|
||||
|
Loading…
Reference in New Issue
Block a user