Commit 3b89dbbd authored by John Levon's avatar John Levon Committed by Linus Torvalds

[PATCH] consolidate task->mm code + fix

The patch below consolidates some duplicate code, reduces some
indentation, and adds a freeing of a page in mem_read() that could be left
unfreed, as far as I can see.
parent d4ea8ebe
...@@ -277,15 +277,11 @@ static inline char *task_cap(struct task_struct *p, char *buffer) ...@@ -277,15 +277,11 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
int proc_pid_status(struct task_struct *task, char * buffer) int proc_pid_status(struct task_struct *task, char * buffer)
{ {
char * orig = buffer; char * orig = buffer;
struct mm_struct *mm; struct mm_struct *mm = get_task_mm(task);
buffer = task_name(task, buffer); buffer = task_name(task, buffer);
buffer = task_state(task, buffer); buffer = task_state(task, buffer);
task_lock(task);
mm = task->mm;
if(mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
if (mm) { if (mm) {
buffer = task_mem(mm, buffer); buffer = task_mem(mm, buffer);
mmput(mm); mmput(mm);
...@@ -481,14 +477,9 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en ...@@ -481,14 +477,9 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en
int proc_pid_statm(struct task_struct *task, char * buffer) int proc_pid_statm(struct task_struct *task, char * buffer)
{ {
struct mm_struct *mm;
int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
struct mm_struct *mm = get_task_mm(task);
task_lock(task);
mm = task->mm;
if(mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
if (mm) { if (mm) {
struct vm_area_struct * vma; struct vm_area_struct * vma;
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
...@@ -626,11 +617,8 @@ ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * ...@@ -626,11 +617,8 @@ ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char *
if (!tmp) if (!tmp)
goto out_free1; goto out_free1;
task_lock(task); mm = get_task_mm(task);
mm = task->mm;
if (mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
retval = 0; retval = 0;
if (!mm) if (!mm)
goto out_free2; goto out_free2;
......
...@@ -131,16 +131,11 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm ...@@ -131,16 +131,11 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{ {
struct mm_struct * mm;
struct vm_area_struct * vma; struct vm_area_struct * vma;
int result = -ENOENT; int result = -ENOENT;
struct task_struct *task = proc_task(inode); struct task_struct *task = proc_task(inode);
struct mm_struct * mm = get_task_mm(task);
task_lock(task);
mm = task->mm;
if (mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
if (!mm) if (!mm)
goto out; goto out;
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
...@@ -203,13 +198,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf ...@@ -203,13 +198,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
static int proc_pid_environ(struct task_struct *task, char * buffer) static int proc_pid_environ(struct task_struct *task, char * buffer)
{ {
struct mm_struct *mm;
int res = 0; int res = 0;
task_lock(task); struct mm_struct *mm = get_task_mm(task);
mm = task->mm;
if (mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
if (mm) { if (mm) {
int len = mm->env_end - mm->env_start; int len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE) if (len > PAGE_SIZE)
...@@ -222,38 +212,36 @@ static int proc_pid_environ(struct task_struct *task, char * buffer) ...@@ -222,38 +212,36 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
static int proc_pid_cmdline(struct task_struct *task, char * buffer) static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{ {
struct mm_struct *mm;
int res = 0; int res = 0;
task_lock(task); int len;
mm = task->mm; struct mm_struct *mm = get_task_mm(task);
if (mm) if (!mm)
atomic_inc(&mm->mm_users); goto out;
task_unlock(task);
if (mm) { len = mm->arg_end - mm->arg_start;
int len = mm->arg_end - mm->arg_start;
if (len > PAGE_SIZE) if (len > PAGE_SIZE)
len = PAGE_SIZE; len = PAGE_SIZE;
res = access_process_vm(task, mm->arg_start, buffer, len, 0);
// If the nul at the end of args has been overwritten, then res = access_process_vm(task, mm->arg_start, buffer, len, 0);
// assume application is using setproctitle(3).
if ( res > 0 && buffer[res-1] != '\0' ) // If the nul at the end of args has been overwritten, then
{ // assume application is using setproctitle(3).
len = strnlen( buffer, res ); if (res > 0 && buffer[res-1] != '\0') {
if ( len < res ) len = strnlen(buffer, res);
{ if (len < res) {
res = len; res = len;
} } else {
else len = mm->env_end - mm->env_start;
{ if (len > PAGE_SIZE - res)
len = mm->env_end - mm->env_start; len = PAGE_SIZE - res;
if (len > PAGE_SIZE - res) res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
len = PAGE_SIZE - res; res = strnlen(buffer, res);
res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
res = strnlen( buffer, res );
}
} }
mmput(mm);
} }
mmput(mm);
out:
return res; return res;
} }
...@@ -421,54 +409,59 @@ static ssize_t mem_read(struct file * file, char * buf, ...@@ -421,54 +409,59 @@ static ssize_t mem_read(struct file * file, char * buf,
struct task_struct *task = proc_task(file->f_dentry->d_inode); struct task_struct *task = proc_task(file->f_dentry->d_inode);
char *page; char *page;
unsigned long src = *ppos; unsigned long src = *ppos;
int copied = 0; int ret = -ESRCH;
struct mm_struct *mm; struct mm_struct *mm;
if (!MAY_PTRACE(task)) if (!MAY_PTRACE(task))
return -ESRCH; goto out;
ret = -ENOMEM;
page = (char *)__get_free_page(GFP_USER); page = (char *)__get_free_page(GFP_USER);
if (!page) if (!page)
return -ENOMEM; goto out;
task_lock(task); ret = 0;
mm = task->mm;
if (mm) mm = get_task_mm(task);
atomic_inc(&mm->mm_users);
task_unlock(task);
if (!mm) if (!mm)
return 0; goto out_free;
if (file->private_data != (void*)((long)current->self_exec_id) ) { ret = -EIO;
mmput(mm);
return -EIO; if (file->private_data != (void*)((long)current->self_exec_id))
} goto out_put;
ret = 0;
while (count > 0) { while (count > 0) {
int this_len, retval; int this_len, retval;
this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
retval = access_process_vm(task, src, page, this_len, 0); retval = access_process_vm(task, src, page, this_len, 0);
if (!retval) { if (!retval) {
if (!copied) if (!ret)
copied = -EIO; ret = -EIO;
break; break;
} }
if (copy_to_user(buf, page, retval)) { if (copy_to_user(buf, page, retval)) {
copied = -EFAULT; ret = -EFAULT;
break; break;
} }
copied += retval;
ret += retval;
src += retval; src += retval;
buf += retval; buf += retval;
count -= retval; count -= retval;
} }
*ppos = src; *ppos = src;
out_put:
mmput(mm); mmput(mm);
out_free:
free_page((unsigned long) page); free_page((unsigned long) page);
return copied; out:
return ret;
} }
#define mem_write NULL #define mem_write NULL
......
...@@ -810,6 +810,27 @@ static inline char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt, ...@@ -810,6 +810,27 @@ static inline char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
return res; return res;
} }
/**
* get_task_mm - acquire a reference to the task's mm
*
* Returns %NULL if the task has no mm. User must release
* the mm via mmput() after use.
*/
static inline struct mm_struct * get_task_mm(struct task_struct * task)
{
struct mm_struct * mm;
task_lock(task);
mm = task->mm;
if (mm)
atomic_inc(&mm->mm_users);
task_unlock(task);
return mm;
}
/* set thread flags in other task's structures /* set thread flags in other task's structures
* - see asm/thread_info.h for TIF_xxxx flags available * - see asm/thread_info.h for TIF_xxxx flags available
*/ */
......
...@@ -124,12 +124,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in ...@@ -124,12 +124,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
struct page *page; struct page *page;
void *old_buf = buf; void *old_buf = buf;
/* Worry about races with exit() */ mm = get_task_mm(tsk);
task_lock(tsk);
mm = tsk->mm;
if (mm)
atomic_inc(&mm->mm_users);
task_unlock(tsk);
if (!mm) if (!mm)
return 0; return 0;
......
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