diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 71 |
1 files changed, 48 insertions, 23 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index a17c26859074..7411bfb0b7cc 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -202,6 +202,26 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
202 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ | 202 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ |
203 | security_ptrace(current,task) == 0)) | 203 | security_ptrace(current,task) == 0)) |
204 | 204 | ||
205 | struct mm_struct *mm_for_maps(struct task_struct *task) | ||
206 | { | ||
207 | struct mm_struct *mm = get_task_mm(task); | ||
208 | if (!mm) | ||
209 | return NULL; | ||
210 | down_read(&mm->mmap_sem); | ||
211 | task_lock(task); | ||
212 | if (task->mm != mm) | ||
213 | goto out; | ||
214 | if (task->mm != current->mm && __ptrace_may_attach(task) < 0) | ||
215 | goto out; | ||
216 | task_unlock(task); | ||
217 | return mm; | ||
218 | out: | ||
219 | task_unlock(task); | ||
220 | up_read(&mm->mmap_sem); | ||
221 | mmput(mm); | ||
222 | return NULL; | ||
223 | } | ||
224 | |||
205 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 225 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
206 | { | 226 | { |
207 | int res = 0; | 227 | int res = 0; |
@@ -2411,19 +2431,23 @@ out: | |||
2411 | * Find the first task with tgid >= tgid | 2431 | * Find the first task with tgid >= tgid |
2412 | * | 2432 | * |
2413 | */ | 2433 | */ |
2414 | static struct task_struct *next_tgid(unsigned int tgid, | 2434 | struct tgid_iter { |
2415 | struct pid_namespace *ns) | 2435 | unsigned int tgid; |
2416 | { | ||
2417 | struct task_struct *task; | 2436 | struct task_struct *task; |
2437 | }; | ||
2438 | static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) | ||
2439 | { | ||
2418 | struct pid *pid; | 2440 | struct pid *pid; |
2419 | 2441 | ||
2442 | if (iter.task) | ||
2443 | put_task_struct(iter.task); | ||
2420 | rcu_read_lock(); | 2444 | rcu_read_lock(); |
2421 | retry: | 2445 | retry: |
2422 | task = NULL; | 2446 | iter.task = NULL; |
2423 | pid = find_ge_pid(tgid, ns); | 2447 | pid = find_ge_pid(iter.tgid, ns); |
2424 | if (pid) { | 2448 | if (pid) { |
2425 | tgid = pid_nr_ns(pid, ns) + 1; | 2449 | iter.tgid = pid_nr_ns(pid, ns); |
2426 | task = pid_task(pid, PIDTYPE_PID); | 2450 | iter.task = pid_task(pid, PIDTYPE_PID); |
2427 | /* What we to know is if the pid we have find is the | 2451 | /* What we to know is if the pid we have find is the |
2428 | * pid of a thread_group_leader. Testing for task | 2452 | * pid of a thread_group_leader. Testing for task |
2429 | * being a thread_group_leader is the obvious thing | 2453 | * being a thread_group_leader is the obvious thing |
@@ -2436,23 +2460,25 @@ retry: | |||
2436 | * found doesn't happen to be a thread group leader. | 2460 | * found doesn't happen to be a thread group leader. |
2437 | * As we don't care in the case of readdir. | 2461 | * As we don't care in the case of readdir. |
2438 | */ | 2462 | */ |
2439 | if (!task || !has_group_leader_pid(task)) | 2463 | if (!iter.task || !has_group_leader_pid(iter.task)) { |
2464 | iter.tgid += 1; | ||
2440 | goto retry; | 2465 | goto retry; |
2441 | get_task_struct(task); | 2466 | } |
2467 | get_task_struct(iter.task); | ||
2442 | } | 2468 | } |
2443 | rcu_read_unlock(); | 2469 | rcu_read_unlock(); |
2444 | return task; | 2470 | return iter; |
2445 | } | 2471 | } |
2446 | 2472 | ||
2447 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) | 2473 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) |
2448 | 2474 | ||
2449 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2475 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2450 | struct task_struct *task, int tgid) | 2476 | struct tgid_iter iter) |
2451 | { | 2477 | { |
2452 | char name[PROC_NUMBUF]; | 2478 | char name[PROC_NUMBUF]; |
2453 | int len = snprintf(name, sizeof(name), "%d", tgid); | 2479 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2454 | return proc_fill_cache(filp, dirent, filldir, name, len, | 2480 | return proc_fill_cache(filp, dirent, filldir, name, len, |
2455 | proc_pid_instantiate, task, NULL); | 2481 | proc_pid_instantiate, iter.task, NULL); |
2456 | } | 2482 | } |
2457 | 2483 | ||
2458 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2484 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
@@ -2460,8 +2486,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2460 | { | 2486 | { |
2461 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2487 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2462 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2488 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2463 | struct task_struct *task; | 2489 | struct tgid_iter iter; |
2464 | int tgid; | ||
2465 | struct pid_namespace *ns; | 2490 | struct pid_namespace *ns; |
2466 | 2491 | ||
2467 | if (!reaper) | 2492 | if (!reaper) |
@@ -2474,14 +2499,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2474 | } | 2499 | } |
2475 | 2500 | ||
2476 | ns = filp->f_dentry->d_sb->s_fs_info; | 2501 | ns = filp->f_dentry->d_sb->s_fs_info; |
2477 | tgid = filp->f_pos - TGID_OFFSET; | 2502 | iter.task = NULL; |
2478 | for (task = next_tgid(tgid, ns); | 2503 | iter.tgid = filp->f_pos - TGID_OFFSET; |
2479 | task; | 2504 | for (iter = next_tgid(ns, iter); |
2480 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { | 2505 | iter.task; |
2481 | tgid = task_pid_nr_ns(task, ns); | 2506 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2482 | filp->f_pos = tgid + TGID_OFFSET; | 2507 | filp->f_pos = iter.tgid + TGID_OFFSET; |
2483 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2508 | if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { |
2484 | put_task_struct(task); | 2509 | put_task_struct(iter.task); |
2485 | goto out; | 2510 | goto out; |
2486 | } | 2511 | } |
2487 | } | 2512 | } |