Commit d2f21286 authored by Andrew Morton's avatar Andrew Morton Committed by Patrick Mochel

[PATCH] pass the stack protection flags into put_dirty_page()

put_dirty_page() currently assumes PAGE_COPY for the stack page's ptes.  But
for x86_64 (at least) this is not the case.

The patch adds the extra arg to put_dirty_page(), updates all callers and fixes
x86_64.
parent a397214b
......@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <asm/param.h>
#include <asm/signal.h>
......@@ -40,7 +41,6 @@
#define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC
extern void ia64_elf32_init (struct pt_regs *regs);
extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address);
static void elf32_set_personality (void);
......@@ -200,7 +200,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm)
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
put_dirty_page(current, page, stack_base);
put_dirty_page(current, page, stack_base, PAGE_COPY);
}
stack_base += PAGE_SIZE;
}
......
......@@ -18,6 +18,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/binfmts.h>
......@@ -32,8 +33,6 @@
#endif
extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);
#undef STACK_TOP
#define STACK_TOP TASK31_SIZE
......@@ -81,7 +80,7 @@ int setup_arg_pages32(struct linux_binprm *bprm)
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
put_dirty_page(current,page,stack_base);
put_dirty_page(current,page,stack_base,PAGE_COPY);
}
stack_base += PAGE_SIZE;
}
......
......@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/binfmts.h>
#include <linux/mm.h>
#include <asm/segment.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
......@@ -272,9 +273,6 @@ static void elf32_init(struct pt_regs *regs)
set_thread_flag(TIF_IA32);
}
extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);
int setup_arg_pages(struct linux_binprm *bprm)
{
unsigned long stack_base;
......@@ -319,7 +317,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
put_dirty_page(current,page,stack_base);
put_dirty_page(current,page,stack_base,PAGE_COPY_EXEC);
}
stack_base += PAGE_SIZE;
}
......
......@@ -287,7 +287,8 @@ int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm)
*
* tsk->mmap_sem is held for writing.
*/
void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address)
void put_dirty_page(struct task_struct *tsk, struct page *page,
unsigned long address, pgprot_t prot)
{
pgd_t * pgd;
pmd_t * pmd;
......@@ -295,7 +296,8 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
struct pte_chain *pte_chain;
if (page_count(page) != 1)
printk(KERN_ERR "mem_map disagrees with %p at %08lx\n", page, address);
printk(KERN_ERR "mem_map disagrees with %p at %08lx\n",
page, address);
pgd = pgd_offset(tsk->mm, address);
pte_chain = pte_chain_alloc(GFP_KERNEL);
......@@ -314,7 +316,7 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
}
lru_cache_add_active(page);
flush_dcache_page(page);
set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY))));
set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, prot))));
pte_chain = page_add_rmap(page, pte, pte_chain);
pte_unmap(pte);
tsk->mm->rss++;
......@@ -421,7 +423,8 @@ int setup_arg_pages(struct linux_binprm *bprm)
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
put_dirty_page(current,page,stack_base);
put_dirty_page(current, page, stack_base,
mpnt->vm_page_prot);
}
stack_base += PAGE_SIZE;
}
......@@ -434,8 +437,6 @@ int setup_arg_pages(struct linux_binprm *bprm)
#else
#define put_dirty_page(tsk, page, address)
#define setup_arg_pages(bprm) (0)
static inline void free_arg_pages(struct linux_binprm *bprm)
{
int i;
......
......@@ -426,7 +426,8 @@ extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsi
extern int make_pages_present(unsigned long addr, unsigned long end);
extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
extern long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long nonblock);
void put_dirty_page(struct task_struct *tsk, struct page *page,
unsigned long address, pgprot_t prot);
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);
......
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