proc: clean up /proc/<pid>/environ handling
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v2 1/1 proc: clean up /proc/<pid>/environ handling
V2: Add similar fix with 6d08f2c7139790c268820a2e590795cb8333181a "proc: make sure mem_open() doesn't pin the target's memory", suggested by Oleg.
Similar to e268337dfe2 ("proc: clean up and fix /proc/<pid>/mem handling"), move the check of permission to open(), this will simplify read() code.
--- fs/proc/base.c | 65 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 46 insertions(+), 19 deletions(-)
fs/proc/base.c +46 -19
@@ -801,30 +801,50 @@ static const struct file_operations proc_mem_operations = { .release = mem_release, }; +static int environ_open (struct inode *inode,struct file *file) +{ +struct task_struct *task =get_proc_task (file->f_path.dentry->d_inode); +struct mm_struct *mm; + +if (!task) +return -ESRCH ; + + mm =mm_for_maps (task); +put_task_struct (task); + +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); + } + + file->private_data = mm; + +return 0 ; +} +static ssize_t environ_read (struct file *file,char __user *buf,size_t count,loff_t *ppos) { -struct task_struct *task =get_proc_task (file->f_dentry->d_inode);char *page;unsigned long src = *ppos; -int ret = -ESRCH ; -struct mm_struct *mm; +int ret =0 ; +struct mm_struct *mm = file->private_data; -if (!task) - goto out_no_task; +if (!mm) +return 0 ; - ret = -ENOMEM ; page = (char *)__get_free_page (GFP_TEMPORARY );if (!page) - goto out; - - - mm =mm_for_maps (task); - ret =PTR_ERR (mm); -if (!mm ||IS_ERR (mm)) - goto out_free; +return -ENOMEM ; ret =0 ; +if (!atomic_inc_not_zero (&mm->mm_users)) + goto free;while (count >0 ) {int this_len, retval, max_len;
@@ -836,7 +856,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, max_len = (count >PAGE_SIZE ) ?PAGE_SIZE : count; this_len = (this_len > max_len) ? max_len : this_len; - retval =access_process_vm (task, (mm->env_start + src), + retval =access_remote_vm (mm, (mm->env_start + src), page, this_len,0 );if (retval <=0 ) {
@@ -855,19 +875,26 @@ static ssize_t environ_read(struct file *file, char __user *buf, count -= retval; } *ppos = src; -mmput (mm); -out_free: + +free:free_page ((unsigned long ) page); -out: -put_task_struct (task); -out_no_task:return ret; } +static int environ_release (struct inode *inode,struct file *file) +{ +struct mm_struct *mm = file->private_data; +if (mm) +mmdrop (mm); +return 0 ; +} +static const struct file_operations proc_environ_operations = { + .open = environ_open, .read = environ_read, .llseek = generic_file_llseek, + .release = environ_release, }; static ssize_t oom_adjust_read(struct file *file, char __user *buf,
Quoted 16 lines · Cong Wang
fs/proc/base.c +15
-0+static int environ_open (struct inode *inode,struct file *file) +{ +struct task_struct *task =get_proc_task (file->f_path.dentry->d_inode); +struct mm_struct *mm; + +if (!task) +return -ESRCH ; + + mm =mm_for_maps (task); +put_task_struct (task); + +if (IS_ERR (mm)) +return PTR_ERR (mm); + +if (mm) {
fs/proc/base.c static const struct file_operations proc_mem_operations = { · line 828
Quoted 10 lines
fs/proc/base.c +10
-0+/* ensure this mm_struct can't be freed */ +atomic_inc (&mm->mm_count); +/* but do not pin its memory */ +mmput (mm); + } + + file->private_data = mm; + +return 0 ; +}
Well, can we unify this code with mem_open() ? Say, let it be __mem_open() or whatever, then mem_open() can use the common helper and add FMODE_UNSIGNED_OFFSET. Just we need another argument for mm_access.
fs/proc/base.c static ssize_t environ_read(struct file *file, char __user *buf, · line 891
Quoted 7 lines
fs/proc/base.c +7
-0+static int environ_release (struct inode *inode,struct file *file) +{ +struct mm_struct *mm = file->private_data; +if (mm) +mmdrop (mm); +return 0 ; +}
Again, this is identical with mem_release(), proc_environ_operations can simply use it instead.
Oleg.
Quoted 4 lines · Oleg Nesterov
Again, this is identical with
mem_release(),proc_environ_operationscan simply use it instead.
Yeah, I noticed that, just not sure about it is worth effort to unify 2 functions... :-/ As you prefer, I will do that.
Thanks.