aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-05-17 16:04:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-05-17 16:04:17 -0400
commite4b4e441323b7988a344f88d7ee3f8fcb17db048 (patch)
treec2495479973ef3db7ec11ec700977cc7924139dc
parent58ddfe6c3af91d320cf5d0aba33143e7c1d8dc35 (diff)
fs/proc: re-factor proc_pid_cmdline_read() a bit
This is a pure refactoring of the function, preparing for some further cleanups. The thing was pretty illegible, and the core functionality still is, but now the core loop is a bit more isolated from the thing that goes on around it. This was "inspired" by the confluence of kworker workqueue name cleanups by Tejun, currently scheduled for 4.18, and commit 7f7ccc2ccc2e ("proc: do not access cmdline nor environ from file-backed areas"). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/proc/base.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1a76d751cf3c..c4d963a12162 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -205,11 +205,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
205 return result; 205 return result;
206} 206}
207 207
208static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, 208static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
209 size_t _count, loff_t *pos) 209 size_t _count, loff_t *pos)
210{ 210{
211 struct task_struct *tsk;
212 struct mm_struct *mm;
213 char *page; 211 char *page;
214 unsigned long count = _count; 212 unsigned long count = _count;
215 unsigned long arg_start, arg_end, env_start, env_end; 213 unsigned long arg_start, arg_end, env_start, env_end;
@@ -218,26 +216,13 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
218 char c; 216 char c;
219 ssize_t rv; 217 ssize_t rv;
220 218
221 BUG_ON(*pos < 0);
222
223 tsk = get_proc_task(file_inode(file));
224 if (!tsk)
225 return -ESRCH;
226 mm = get_task_mm(tsk);
227 put_task_struct(tsk);
228 if (!mm)
229 return 0;
230 /* Check if process spawned far enough to have cmdline. */ 219 /* Check if process spawned far enough to have cmdline. */
231 if (!mm->env_end) { 220 if (!mm->env_end)
232 rv = 0; 221 return 0;
233 goto out_mmput;
234 }
235 222
236 page = (char *)__get_free_page(GFP_KERNEL); 223 page = (char *)__get_free_page(GFP_KERNEL);
237 if (!page) { 224 if (!page)
238 rv = -ENOMEM; 225 return -ENOMEM;
239 goto out_mmput;
240 }
241 226
242 down_read(&mm->mmap_sem); 227 down_read(&mm->mmap_sem);
243 arg_start = mm->arg_start; 228 arg_start = mm->arg_start;
@@ -365,13 +350,42 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
365 350
366out_free_page: 351out_free_page:
367 free_page((unsigned long)page); 352 free_page((unsigned long)page);
368out_mmput:
369 mmput(mm);
370 if (rv > 0)
371 *pos += rv;
372 return rv; 353 return rv;
373} 354}
374 355
356static ssize_t get_task_cmdline(struct task_struct *tsk, char __user *buf,
357 size_t count, loff_t *pos)
358{
359 struct mm_struct *mm;
360 ssize_t ret;
361
362 mm = get_task_mm(tsk);
363 if (!mm)
364 return 0;
365
366 ret = get_mm_cmdline(mm, buf, count, pos);
367 mmput(mm);
368 return ret;
369}
370
371static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
372 size_t count, loff_t *pos)
373{
374 struct task_struct *tsk;
375 ssize_t ret;
376
377 BUG_ON(*pos < 0);
378
379 tsk = get_proc_task(file_inode(file));
380 if (!tsk)
381 return -ESRCH;
382 ret = get_task_cmdline(tsk, buf, count, pos);
383 put_task_struct(tsk);
384 if (ret > 0)
385 *pos += ret;
386 return ret;
387}
388
375static const struct file_operations proc_pid_cmdline_ops = { 389static const struct file_operations proc_pid_cmdline_ops = {
376 .read = proc_pid_cmdline_read, 390 .read = proc_pid_cmdline_read,
377 .llseek = generic_file_llseek, 391 .llseek = generic_file_llseek,