diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-19 02:40:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:40 -0400 |
commit | b488893a390edfe027bae7a46e9af8083e740668 (patch) | |
tree | c469a7f99ad01005a73011c029eb5e5d15454559 /fs/proc | |
parent | 3eb07c8c8adb6f0572baba844ba2d9e501654316 (diff) |
pid namespaces: changes to show virtual ids to user
This is the largest patch in the set. Make all (I hope) the places where
the pid is shown to or get from user operate on the virtual pids.
The idea is:
- all in-kernel data structures must store either struct pid itself
or the pid's global nr, obtained with pid_nr() call;
- when seeking the task from kernel code with the stored id one
should use find_task_by_pid() call that works with global pids;
- when showing pid's numerical value to the user the virtual one
should be used, but however when one shows task's pid outside this
task's namespace the global one is to be used;
- when getting the pid from userspace one need to consider this as
the virtual one and use appropriate task/pid-searching functions.
[akpm@linux-foundation.org: build fix]
[akpm@linux-foundation.org: nuther build fix]
[akpm@linux-foundation.org: yet nuther build fix]
[akpm@linux-foundation.org: remove unneeded casts]
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Paul Menage <menage@google.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 27 | ||||
-rw-r--r-- | fs/proc/base.c | 37 |
2 files changed, 42 insertions, 22 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 24f7f9f6684d..04b689f3288f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <linux/cpuset.h> | 77 | #include <linux/cpuset.h> |
78 | #include <linux/rcupdate.h> | 78 | #include <linux/rcupdate.h> |
79 | #include <linux/delayacct.h> | 79 | #include <linux/delayacct.h> |
80 | #include <linux/pid_namespace.h> | ||
80 | 81 | ||
81 | #include <asm/pgtable.h> | 82 | #include <asm/pgtable.h> |
82 | #include <asm/processor.h> | 83 | #include <asm/processor.h> |
@@ -161,8 +162,15 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
161 | struct group_info *group_info; | 162 | struct group_info *group_info; |
162 | int g; | 163 | int g; |
163 | struct fdtable *fdt = NULL; | 164 | struct fdtable *fdt = NULL; |
165 | struct pid_namespace *ns; | ||
166 | pid_t ppid, tpid; | ||
164 | 167 | ||
168 | ns = current->nsproxy->pid_ns; | ||
165 | rcu_read_lock(); | 169 | rcu_read_lock(); |
170 | ppid = pid_alive(p) ? | ||
171 | task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; | ||
172 | tpid = pid_alive(p) && p->ptrace ? | ||
173 | task_ppid_nr_ns(rcu_dereference(p->parent), ns) : 0; | ||
166 | buffer += sprintf(buffer, | 174 | buffer += sprintf(buffer, |
167 | "State:\t%s\n" | 175 | "State:\t%s\n" |
168 | "Tgid:\t%d\n" | 176 | "Tgid:\t%d\n" |
@@ -172,9 +180,9 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
172 | "Uid:\t%d\t%d\t%d\t%d\n" | 180 | "Uid:\t%d\t%d\t%d\t%d\n" |
173 | "Gid:\t%d\t%d\t%d\t%d\n", | 181 | "Gid:\t%d\t%d\t%d\t%d\n", |
174 | get_task_state(p), | 182 | get_task_state(p), |
175 | p->tgid, p->pid, | 183 | task_tgid_nr_ns(p, ns), |
176 | pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, | 184 | task_pid_nr_ns(p, ns), |
177 | pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, | 185 | ppid, tpid, |
178 | p->uid, p->euid, p->suid, p->fsuid, | 186 | p->uid, p->euid, p->suid, p->fsuid, |
179 | p->gid, p->egid, p->sgid, p->fsgid); | 187 | p->gid, p->egid, p->sgid, p->fsgid); |
180 | 188 | ||
@@ -394,6 +402,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
394 | unsigned long rsslim = 0; | 402 | unsigned long rsslim = 0; |
395 | char tcomm[sizeof(task->comm)]; | 403 | char tcomm[sizeof(task->comm)]; |
396 | unsigned long flags; | 404 | unsigned long flags; |
405 | struct pid_namespace *ns; | ||
406 | |||
407 | ns = current->nsproxy->pid_ns; | ||
397 | 408 | ||
398 | state = *get_task_state(task); | 409 | state = *get_task_state(task); |
399 | vsize = eip = esp = 0; | 410 | vsize = eip = esp = 0; |
@@ -416,7 +427,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
416 | struct signal_struct *sig = task->signal; | 427 | struct signal_struct *sig = task->signal; |
417 | 428 | ||
418 | if (sig->tty) { | 429 | if (sig->tty) { |
419 | tty_pgrp = pid_nr(sig->tty->pgrp); | 430 | tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns); |
420 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); | 431 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); |
421 | } | 432 | } |
422 | 433 | ||
@@ -449,9 +460,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
449 | gtime += cputime_add(gtime, sig->gtime); | 460 | gtime += cputime_add(gtime, sig->gtime); |
450 | } | 461 | } |
451 | 462 | ||
452 | sid = task_session_nr(task); | 463 | sid = task_session_nr_ns(task, ns); |
453 | pgid = task_pgrp_nr(task); | 464 | pgid = task_pgrp_nr_ns(task, ns); |
454 | ppid = rcu_dereference(task->real_parent)->tgid; | 465 | ppid = task_ppid_nr_ns(task, ns); |
455 | 466 | ||
456 | unlock_task_sighand(task, &flags); | 467 | unlock_task_sighand(task, &flags); |
457 | } | 468 | } |
@@ -483,7 +494,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
483 | res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ | 494 | res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ |
484 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ | 495 | %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ |
485 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", | 496 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", |
486 | task->pid, | 497 | task_pid_nr_ns(task, ns), |
487 | tcomm, | 498 | tcomm, |
488 | state, | 499 | state, |
489 | ppid, | 500 | ppid, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 21510c9aa89c..db7636041c10 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1937,14 +1937,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
1937 | int buflen) | 1937 | int buflen) |
1938 | { | 1938 | { |
1939 | char tmp[PROC_NUMBUF]; | 1939 | char tmp[PROC_NUMBUF]; |
1940 | sprintf(tmp, "%d", current->tgid); | 1940 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1941 | return vfs_readlink(dentry,buffer,buflen,tmp); | 1941 | return vfs_readlink(dentry,buffer,buflen,tmp); |
1942 | } | 1942 | } |
1943 | 1943 | ||
1944 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | 1944 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) |
1945 | { | 1945 | { |
1946 | char tmp[PROC_NUMBUF]; | 1946 | char tmp[PROC_NUMBUF]; |
1947 | sprintf(tmp, "%d", current->tgid); | 1947 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1948 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 1948 | return ERR_PTR(vfs_follow_link(nd,tmp)); |
1949 | } | 1949 | } |
1950 | 1950 | ||
@@ -2316,6 +2316,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2316 | struct dentry *result = ERR_PTR(-ENOENT); | 2316 | struct dentry *result = ERR_PTR(-ENOENT); |
2317 | struct task_struct *task; | 2317 | struct task_struct *task; |
2318 | unsigned tgid; | 2318 | unsigned tgid; |
2319 | struct pid_namespace *ns; | ||
2319 | 2320 | ||
2320 | result = proc_base_lookup(dir, dentry); | 2321 | result = proc_base_lookup(dir, dentry); |
2321 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) | 2322 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) |
@@ -2325,8 +2326,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2325 | if (tgid == ~0U) | 2326 | if (tgid == ~0U) |
2326 | goto out; | 2327 | goto out; |
2327 | 2328 | ||
2329 | ns = dentry->d_sb->s_fs_info; | ||
2328 | rcu_read_lock(); | 2330 | rcu_read_lock(); |
2329 | task = find_task_by_pid(tgid); | 2331 | task = find_task_by_pid_ns(tgid, ns); |
2330 | if (task) | 2332 | if (task) |
2331 | get_task_struct(task); | 2333 | get_task_struct(task); |
2332 | rcu_read_unlock(); | 2334 | rcu_read_unlock(); |
@@ -2343,7 +2345,8 @@ out: | |||
2343 | * Find the first task with tgid >= tgid | 2345 | * Find the first task with tgid >= tgid |
2344 | * | 2346 | * |
2345 | */ | 2347 | */ |
2346 | static struct task_struct *next_tgid(unsigned int tgid) | 2348 | static struct task_struct *next_tgid(unsigned int tgid, |
2349 | struct pid_namespace *ns) | ||
2347 | { | 2350 | { |
2348 | struct task_struct *task; | 2351 | struct task_struct *task; |
2349 | struct pid *pid; | 2352 | struct pid *pid; |
@@ -2351,9 +2354,9 @@ static struct task_struct *next_tgid(unsigned int tgid) | |||
2351 | rcu_read_lock(); | 2354 | rcu_read_lock(); |
2352 | retry: | 2355 | retry: |
2353 | task = NULL; | 2356 | task = NULL; |
2354 | pid = find_ge_pid(tgid, &init_pid_ns); | 2357 | pid = find_ge_pid(tgid, ns); |
2355 | if (pid) { | 2358 | if (pid) { |
2356 | tgid = pid->nr + 1; | 2359 | tgid = pid_nr_ns(pid, ns) + 1; |
2357 | task = pid_task(pid, PIDTYPE_PID); | 2360 | task = pid_task(pid, PIDTYPE_PID); |
2358 | /* What we to know is if the pid we have find is the | 2361 | /* What we to know is if the pid we have find is the |
2359 | * pid of a thread_group_leader. Testing for task | 2362 | * pid of a thread_group_leader. Testing for task |
@@ -2393,6 +2396,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2393 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2396 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2394 | struct task_struct *task; | 2397 | struct task_struct *task; |
2395 | int tgid; | 2398 | int tgid; |
2399 | struct pid_namespace *ns; | ||
2396 | 2400 | ||
2397 | if (!reaper) | 2401 | if (!reaper) |
2398 | goto out_no_task; | 2402 | goto out_no_task; |
@@ -2403,11 +2407,12 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2403 | goto out; | 2407 | goto out; |
2404 | } | 2408 | } |
2405 | 2409 | ||
2410 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2406 | tgid = filp->f_pos - TGID_OFFSET; | 2411 | tgid = filp->f_pos - TGID_OFFSET; |
2407 | for (task = next_tgid(tgid); | 2412 | for (task = next_tgid(tgid, ns); |
2408 | task; | 2413 | task; |
2409 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2414 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { |
2410 | tgid = task->pid; | 2415 | tgid = task_pid_nr_ns(task, ns); |
2411 | filp->f_pos = tgid + TGID_OFFSET; | 2416 | filp->f_pos = tgid + TGID_OFFSET; |
2412 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2417 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2413 | put_task_struct(task); | 2418 | put_task_struct(task); |
@@ -2531,6 +2536,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2531 | struct task_struct *task; | 2536 | struct task_struct *task; |
2532 | struct task_struct *leader = get_proc_task(dir); | 2537 | struct task_struct *leader = get_proc_task(dir); |
2533 | unsigned tid; | 2538 | unsigned tid; |
2539 | struct pid_namespace *ns; | ||
2534 | 2540 | ||
2535 | if (!leader) | 2541 | if (!leader) |
2536 | goto out_no_task; | 2542 | goto out_no_task; |
@@ -2539,8 +2545,9 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2539 | if (tid == ~0U) | 2545 | if (tid == ~0U) |
2540 | goto out; | 2546 | goto out; |
2541 | 2547 | ||
2548 | ns = dentry->d_sb->s_fs_info; | ||
2542 | rcu_read_lock(); | 2549 | rcu_read_lock(); |
2543 | task = find_task_by_pid(tid); | 2550 | task = find_task_by_pid_ns(tid, ns); |
2544 | if (task) | 2551 | if (task) |
2545 | get_task_struct(task); | 2552 | get_task_struct(task); |
2546 | rcu_read_unlock(); | 2553 | rcu_read_unlock(); |
@@ -2571,14 +2578,14 @@ out_no_task: | |||
2571 | * threads past it. | 2578 | * threads past it. |
2572 | */ | 2579 | */ |
2573 | static struct task_struct *first_tid(struct task_struct *leader, | 2580 | static struct task_struct *first_tid(struct task_struct *leader, |
2574 | int tid, int nr) | 2581 | int tid, int nr, struct pid_namespace *ns) |
2575 | { | 2582 | { |
2576 | struct task_struct *pos; | 2583 | struct task_struct *pos; |
2577 | 2584 | ||
2578 | rcu_read_lock(); | 2585 | rcu_read_lock(); |
2579 | /* Attempt to start with the pid of a thread */ | 2586 | /* Attempt to start with the pid of a thread */ |
2580 | if (tid && (nr > 0)) { | 2587 | if (tid && (nr > 0)) { |
2581 | pos = find_task_by_pid(tid); | 2588 | pos = find_task_by_pid_ns(tid, ns); |
2582 | if (pos && (pos->group_leader == leader)) | 2589 | if (pos && (pos->group_leader == leader)) |
2583 | goto found; | 2590 | goto found; |
2584 | } | 2591 | } |
@@ -2647,6 +2654,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2647 | ino_t ino; | 2654 | ino_t ino; |
2648 | int tid; | 2655 | int tid; |
2649 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ | 2656 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ |
2657 | struct pid_namespace *ns; | ||
2650 | 2658 | ||
2651 | task = get_proc_task(inode); | 2659 | task = get_proc_task(inode); |
2652 | if (!task) | 2660 | if (!task) |
@@ -2680,12 +2688,13 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2680 | /* f_version caches the tgid value that the last readdir call couldn't | 2688 | /* f_version caches the tgid value that the last readdir call couldn't |
2681 | * return. lseek aka telldir automagically resets f_version to 0. | 2689 | * return. lseek aka telldir automagically resets f_version to 0. |
2682 | */ | 2690 | */ |
2691 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2683 | tid = (int)filp->f_version; | 2692 | tid = (int)filp->f_version; |
2684 | filp->f_version = 0; | 2693 | filp->f_version = 0; |
2685 | for (task = first_tid(leader, tid, pos - 2); | 2694 | for (task = first_tid(leader, tid, pos - 2, ns); |
2686 | task; | 2695 | task; |
2687 | task = next_tid(task), pos++) { | 2696 | task = next_tid(task), pos++) { |
2688 | tid = task->pid; | 2697 | tid = task_pid_nr_ns(task, ns); |
2689 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 2698 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2690 | /* returning this tgid failed, save it as the first | 2699 | /* returning this tgid failed, save it as the first |
2691 | * pid for the next readir call */ | 2700 | * pid for the next readir call */ |