From 224c7b61354065f6e39654a8740efbb3b28e87ee Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 31 Jan 2012 17:15:11 +0100 Subject: [PATCH] --- yaml --- r: 287094 b: refs/heads/master c: 6d08f2c7139790c268820a2e590795cb8333181a h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/proc/base.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 0857d60d7e87..87290743ae73 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 572d34b946bae070debd42db1143034d9687e13f +refs/heads/master: 6d08f2c7139790c268820a2e590795cb8333181a diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index be1909041685..d9512bd03e6c 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -711,6 +711,13 @@ static int mem_open(struct inode* inode, struct file* file) if (IS_ERR(mm)) return PTR_ERR(mm); + if (mm) { + /* ensure this mm_struct can't be freed */ + atomic_inc(&mm->mm_count); + /* but do not pin its memory */ + mmput(mm); + } + /* OK to pass negative loff_t, we can catch out-of-range */ file->f_mode |= FMODE_UNSIGNED_OFFSET; file->private_data = mm; @@ -734,6 +741,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf, return -ENOMEM; copied = 0; + if (!atomic_inc_not_zero(&mm->mm_users)) + goto free; + while (count > 0) { int this_len = min_t(int, count, PAGE_SIZE); @@ -761,6 +771,8 @@ static ssize_t mem_rw(struct file *file, char __user *buf, } *ppos = addr; + mmput(mm); +free: free_page((unsigned long) page); return copied; } @@ -797,7 +809,7 @@ static int mem_release(struct inode *inode, struct file *file) { struct mm_struct *mm = file->private_data; if (mm) - mmput(mm); + mmdrop(mm); return 0; }