Commit 2e4a4d4e authored by Linus Torvalds's avatar Linus Torvalds

Fix ptrace and fork interaction

parent 967fe243
...@@ -213,7 +213,7 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src, ...@@ -213,7 +213,7 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
pgd_t * src_pgd, * dst_pgd; pgd_t * src_pgd, * dst_pgd;
unsigned long address = vma->vm_start; unsigned long address = vma->vm_start;
unsigned long end = vma->vm_end; unsigned long end = vma->vm_end;
unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE; unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
src_pgd = pgd_offset(src, address)-1; src_pgd = pgd_offset(src, address)-1;
dst_pgd = pgd_offset(dst, address)-1; dst_pgd = pgd_offset(dst, address)-1;
...@@ -280,7 +280,7 @@ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK; ...@@ -280,7 +280,7 @@ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
goto cont_copy_pte_range; goto cont_copy_pte_range;
/* If it's a COW mapping, write protect it both in the parent and the child */ /* If it's a COW mapping, write protect it both in the parent and the child */
if (cow) { if (cow && pte_write(pte)) {
ptep_set_wrprotect(src_pte); ptep_set_wrprotect(src_pte);
pte = *src_pte; pte = *src_pte;
} }
...@@ -492,20 +492,25 @@ static inline struct page * get_page_map(struct page *page) ...@@ -492,20 +492,25 @@ static inline struct page * get_page_map(struct page *page)
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, 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 len, int write, int force, struct page **pages, struct vm_area_struct **vmas)
{ {
int i = 0; int i;
unsigned int flags;
/*
* Require read or write permissions.
* If 'force' is set, we only require the "MAY" flags.
*/
flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
i = 0;
do { do {
struct vm_area_struct * vma; struct vm_area_struct * vma;
vma = find_extend_vma(mm, start); vma = find_extend_vma(mm, start);
if ( !vma || if ( !vma || !(flags & vma->vm_flags) )
(!force && return i ? : -EFAULT;
((write && (!(vma->vm_flags & VM_WRITE))) ||
(!write && (!(vma->vm_flags & VM_READ))) ) )) {
if (i) return i;
return -EFAULT;
}
spin_lock(&mm->page_table_lock); spin_lock(&mm->page_table_lock);
do { do {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment