diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 30 | ||||
-rw-r--r-- | fs/proc/base.c | 202 | ||||
-rw-r--r-- | fs/proc/inode.c | 2 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 3 | ||||
-rw-r--r-- | fs/proc/root.c | 83 |
5 files changed, 266 insertions, 54 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index b9be6e355cc6..63c95afb561f 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> |
@@ -145,8 +146,7 @@ static inline const char *get_task_state(struct task_struct *tsk) | |||
145 | TASK_UNINTERRUPTIBLE | | 146 | TASK_UNINTERRUPTIBLE | |
146 | TASK_STOPPED | | 147 | TASK_STOPPED | |
147 | TASK_TRACED)) | | 148 | TASK_TRACED)) | |
148 | (tsk->exit_state & (EXIT_ZOMBIE | | 149 | tsk->exit_state; |
149 | EXIT_DEAD)); | ||
150 | const char **p = &task_state_array[0]; | 150 | const char **p = &task_state_array[0]; |
151 | 151 | ||
152 | while (state) { | 152 | while (state) { |
@@ -161,8 +161,15 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
161 | struct group_info *group_info; | 161 | struct group_info *group_info; |
162 | int g; | 162 | int g; |
163 | struct fdtable *fdt = NULL; | 163 | struct fdtable *fdt = NULL; |
164 | struct pid_namespace *ns; | ||
165 | pid_t ppid, tpid; | ||
164 | 166 | ||
167 | ns = current->nsproxy->pid_ns; | ||
165 | rcu_read_lock(); | 168 | rcu_read_lock(); |
169 | ppid = pid_alive(p) ? | ||
170 | task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; | ||
171 | tpid = pid_alive(p) && p->ptrace ? | ||
172 | task_ppid_nr_ns(rcu_dereference(p->parent), ns) : 0; | ||
166 | buffer += sprintf(buffer, | 173 | buffer += sprintf(buffer, |
167 | "State:\t%s\n" | 174 | "State:\t%s\n" |
168 | "Tgid:\t%d\n" | 175 | "Tgid:\t%d\n" |
@@ -172,9 +179,9 @@ static inline char *task_state(struct task_struct *p, char *buffer) | |||
172 | "Uid:\t%d\t%d\t%d\t%d\n" | 179 | "Uid:\t%d\t%d\t%d\t%d\n" |
173 | "Gid:\t%d\t%d\t%d\t%d\n", | 180 | "Gid:\t%d\t%d\t%d\t%d\n", |
174 | get_task_state(p), | 181 | get_task_state(p), |
175 | p->tgid, p->pid, | 182 | task_tgid_nr_ns(p, ns), |
176 | pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, | 183 | task_pid_nr_ns(p, ns), |
177 | pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, | 184 | ppid, tpid, |
178 | p->uid, p->euid, p->suid, p->fsuid, | 185 | p->uid, p->euid, p->suid, p->fsuid, |
179 | p->gid, p->egid, p->sgid, p->fsgid); | 186 | p->gid, p->egid, p->sgid, p->fsgid); |
180 | 187 | ||
@@ -394,6 +401,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
394 | unsigned long rsslim = 0; | 401 | unsigned long rsslim = 0; |
395 | char tcomm[sizeof(task->comm)]; | 402 | char tcomm[sizeof(task->comm)]; |
396 | unsigned long flags; | 403 | unsigned long flags; |
404 | struct pid_namespace *ns; | ||
405 | |||
406 | ns = current->nsproxy->pid_ns; | ||
397 | 407 | ||
398 | state = *get_task_state(task); | 408 | state = *get_task_state(task); |
399 | vsize = eip = esp = 0; | 409 | vsize = eip = esp = 0; |
@@ -416,7 +426,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
416 | struct signal_struct *sig = task->signal; | 426 | struct signal_struct *sig = task->signal; |
417 | 427 | ||
418 | if (sig->tty) { | 428 | if (sig->tty) { |
419 | tty_pgrp = pid_nr(sig->tty->pgrp); | 429 | tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns); |
420 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); | 430 | tty_nr = new_encode_dev(tty_devnum(sig->tty)); |
421 | } | 431 | } |
422 | 432 | ||
@@ -449,9 +459,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) | |||
449 | gtime = cputime_add(gtime, sig->gtime); | 459 | gtime = cputime_add(gtime, sig->gtime); |
450 | } | 460 | } |
451 | 461 | ||
452 | sid = signal_session(sig); | 462 | sid = task_session_nr_ns(task, ns); |
453 | pgid = process_group(task); | 463 | pgid = task_pgrp_nr_ns(task, ns); |
454 | ppid = rcu_dereference(task->real_parent)->tgid; | 464 | ppid = task_ppid_nr_ns(task, ns); |
455 | 465 | ||
456 | unlock_task_sighand(task, &flags); | 466 | unlock_task_sighand(task, &flags); |
457 | } | 467 | } |
@@ -483,7 +493,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 \ | 493 | 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 \ | 494 | %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", | 495 | %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", |
486 | task->pid, | 496 | task_pid_nr_ns(task, ns), |
487 | tcomm, | 497 | tcomm, |
488 | state, | 498 | state, |
489 | ppid, | 499 | ppid, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 4fe74d156416..39a3d7c969c5 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -63,16 +63,19 @@ | |||
63 | #include <linux/mm.h> | 63 | #include <linux/mm.h> |
64 | #include <linux/rcupdate.h> | 64 | #include <linux/rcupdate.h> |
65 | #include <linux/kallsyms.h> | 65 | #include <linux/kallsyms.h> |
66 | #include <linux/resource.h> | ||
66 | #include <linux/module.h> | 67 | #include <linux/module.h> |
67 | #include <linux/mount.h> | 68 | #include <linux/mount.h> |
68 | #include <linux/security.h> | 69 | #include <linux/security.h> |
69 | #include <linux/ptrace.h> | 70 | #include <linux/ptrace.h> |
71 | #include <linux/cgroup.h> | ||
70 | #include <linux/cpuset.h> | 72 | #include <linux/cpuset.h> |
71 | #include <linux/audit.h> | 73 | #include <linux/audit.h> |
72 | #include <linux/poll.h> | 74 | #include <linux/poll.h> |
73 | #include <linux/nsproxy.h> | 75 | #include <linux/nsproxy.h> |
74 | #include <linux/oom.h> | 76 | #include <linux/oom.h> |
75 | #include <linux/elf.h> | 77 | #include <linux/elf.h> |
78 | #include <linux/pid_namespace.h> | ||
76 | #include "internal.h" | 79 | #include "internal.h" |
77 | 80 | ||
78 | /* NOTE: | 81 | /* NOTE: |
@@ -301,6 +304,78 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
301 | return sprintf(buffer, "%lu\n", points); | 304 | return sprintf(buffer, "%lu\n", points); |
302 | } | 305 | } |
303 | 306 | ||
307 | struct limit_names { | ||
308 | char *name; | ||
309 | char *unit; | ||
310 | }; | ||
311 | |||
312 | static const struct limit_names lnames[RLIM_NLIMITS] = { | ||
313 | [RLIMIT_CPU] = {"Max cpu time", "ms"}, | ||
314 | [RLIMIT_FSIZE] = {"Max file size", "bytes"}, | ||
315 | [RLIMIT_DATA] = {"Max data size", "bytes"}, | ||
316 | [RLIMIT_STACK] = {"Max stack size", "bytes"}, | ||
317 | [RLIMIT_CORE] = {"Max core file size", "bytes"}, | ||
318 | [RLIMIT_RSS] = {"Max resident set", "bytes"}, | ||
319 | [RLIMIT_NPROC] = {"Max processes", "processes"}, | ||
320 | [RLIMIT_NOFILE] = {"Max open files", "files"}, | ||
321 | [RLIMIT_MEMLOCK] = {"Max locked memory", "bytes"}, | ||
322 | [RLIMIT_AS] = {"Max address space", "bytes"}, | ||
323 | [RLIMIT_LOCKS] = {"Max file locks", "locks"}, | ||
324 | [RLIMIT_SIGPENDING] = {"Max pending signals", "signals"}, | ||
325 | [RLIMIT_MSGQUEUE] = {"Max msgqueue size", "bytes"}, | ||
326 | [RLIMIT_NICE] = {"Max nice priority", NULL}, | ||
327 | [RLIMIT_RTPRIO] = {"Max realtime priority", NULL}, | ||
328 | }; | ||
329 | |||
330 | /* Display limits for a process */ | ||
331 | static int proc_pid_limits(struct task_struct *task, char *buffer) | ||
332 | { | ||
333 | unsigned int i; | ||
334 | int count = 0; | ||
335 | unsigned long flags; | ||
336 | char *bufptr = buffer; | ||
337 | |||
338 | struct rlimit rlim[RLIM_NLIMITS]; | ||
339 | |||
340 | rcu_read_lock(); | ||
341 | if (!lock_task_sighand(task,&flags)) { | ||
342 | rcu_read_unlock(); | ||
343 | return 0; | ||
344 | } | ||
345 | memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS); | ||
346 | unlock_task_sighand(task, &flags); | ||
347 | rcu_read_unlock(); | ||
348 | |||
349 | /* | ||
350 | * print the file header | ||
351 | */ | ||
352 | count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n", | ||
353 | "Limit", "Soft Limit", "Hard Limit", "Units"); | ||
354 | |||
355 | for (i = 0; i < RLIM_NLIMITS; i++) { | ||
356 | if (rlim[i].rlim_cur == RLIM_INFINITY) | ||
357 | count += sprintf(&bufptr[count], "%-25s %-20s ", | ||
358 | lnames[i].name, "unlimited"); | ||
359 | else | ||
360 | count += sprintf(&bufptr[count], "%-25s %-20lu ", | ||
361 | lnames[i].name, rlim[i].rlim_cur); | ||
362 | |||
363 | if (rlim[i].rlim_max == RLIM_INFINITY) | ||
364 | count += sprintf(&bufptr[count], "%-20s ", "unlimited"); | ||
365 | else | ||
366 | count += sprintf(&bufptr[count], "%-20lu ", | ||
367 | rlim[i].rlim_max); | ||
368 | |||
369 | if (lnames[i].unit) | ||
370 | count += sprintf(&bufptr[count], "%-10s\n", | ||
371 | lnames[i].unit); | ||
372 | else | ||
373 | count += sprintf(&bufptr[count], "\n"); | ||
374 | } | ||
375 | |||
376 | return count; | ||
377 | } | ||
378 | |||
304 | /************************************************************************/ | 379 | /************************************************************************/ |
305 | /* Here the fs part begins */ | 380 | /* Here the fs part begins */ |
306 | /************************************************************************/ | 381 | /************************************************************************/ |
@@ -349,18 +424,21 @@ struct proc_mounts { | |||
349 | static int mounts_open(struct inode *inode, struct file *file) | 424 | static int mounts_open(struct inode *inode, struct file *file) |
350 | { | 425 | { |
351 | struct task_struct *task = get_proc_task(inode); | 426 | struct task_struct *task = get_proc_task(inode); |
427 | struct nsproxy *nsp; | ||
352 | struct mnt_namespace *ns = NULL; | 428 | struct mnt_namespace *ns = NULL; |
353 | struct proc_mounts *p; | 429 | struct proc_mounts *p; |
354 | int ret = -EINVAL; | 430 | int ret = -EINVAL; |
355 | 431 | ||
356 | if (task) { | 432 | if (task) { |
357 | task_lock(task); | 433 | rcu_read_lock(); |
358 | if (task->nsproxy) { | 434 | nsp = task_nsproxy(task); |
359 | ns = task->nsproxy->mnt_ns; | 435 | if (nsp) { |
436 | ns = nsp->mnt_ns; | ||
360 | if (ns) | 437 | if (ns) |
361 | get_mnt_ns(ns); | 438 | get_mnt_ns(ns); |
362 | } | 439 | } |
363 | task_unlock(task); | 440 | rcu_read_unlock(); |
441 | |||
364 | put_task_struct(task); | 442 | put_task_struct(task); |
365 | } | 443 | } |
366 | 444 | ||
@@ -423,16 +501,20 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
423 | 501 | ||
424 | if (!ret) { | 502 | if (!ret) { |
425 | struct seq_file *m = file->private_data; | 503 | struct seq_file *m = file->private_data; |
504 | struct nsproxy *nsp; | ||
426 | struct mnt_namespace *mnt_ns = NULL; | 505 | struct mnt_namespace *mnt_ns = NULL; |
427 | struct task_struct *task = get_proc_task(inode); | 506 | struct task_struct *task = get_proc_task(inode); |
428 | 507 | ||
429 | if (task) { | 508 | if (task) { |
430 | task_lock(task); | 509 | rcu_read_lock(); |
431 | if (task->nsproxy) | 510 | nsp = task_nsproxy(task); |
432 | mnt_ns = task->nsproxy->mnt_ns; | 511 | if (nsp) { |
433 | if (mnt_ns) | 512 | mnt_ns = nsp->mnt_ns; |
434 | get_mnt_ns(mnt_ns); | 513 | if (mnt_ns) |
435 | task_unlock(task); | 514 | get_mnt_ns(mnt_ns); |
515 | } | ||
516 | rcu_read_unlock(); | ||
517 | |||
436 | put_task_struct(task); | 518 | put_task_struct(task); |
437 | } | 519 | } |
438 | 520 | ||
@@ -1437,7 +1519,7 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1437 | struct dentry *dentry = filp->f_path.dentry; | 1519 | struct dentry *dentry = filp->f_path.dentry; |
1438 | struct inode *inode = dentry->d_inode; | 1520 | struct inode *inode = dentry->d_inode; |
1439 | struct task_struct *p = get_proc_task(inode); | 1521 | struct task_struct *p = get_proc_task(inode); |
1440 | unsigned int fd, tid, ino; | 1522 | unsigned int fd, ino; |
1441 | int retval; | 1523 | int retval; |
1442 | struct files_struct * files; | 1524 | struct files_struct * files; |
1443 | struct fdtable *fdt; | 1525 | struct fdtable *fdt; |
@@ -1446,7 +1528,6 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1446 | if (!p) | 1528 | if (!p) |
1447 | goto out_no_task; | 1529 | goto out_no_task; |
1448 | retval = 0; | 1530 | retval = 0; |
1449 | tid = p->pid; | ||
1450 | 1531 | ||
1451 | fd = filp->f_pos; | 1532 | fd = filp->f_pos; |
1452 | switch (fd) { | 1533 | switch (fd) { |
@@ -1681,7 +1762,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1681 | const struct pid_entry *ents, unsigned int nents) | 1762 | const struct pid_entry *ents, unsigned int nents) |
1682 | { | 1763 | { |
1683 | int i; | 1764 | int i; |
1684 | int pid; | ||
1685 | struct dentry *dentry = filp->f_path.dentry; | 1765 | struct dentry *dentry = filp->f_path.dentry; |
1686 | struct inode *inode = dentry->d_inode; | 1766 | struct inode *inode = dentry->d_inode; |
1687 | struct task_struct *task = get_proc_task(inode); | 1767 | struct task_struct *task = get_proc_task(inode); |
@@ -1694,7 +1774,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1694 | goto out_no_task; | 1774 | goto out_no_task; |
1695 | 1775 | ||
1696 | ret = 0; | 1776 | ret = 0; |
1697 | pid = task->pid; | ||
1698 | i = filp->f_pos; | 1777 | i = filp->f_pos; |
1699 | switch (i) { | 1778 | switch (i) { |
1700 | case 0: | 1779 | case 0: |
@@ -1928,14 +2007,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
1928 | int buflen) | 2007 | int buflen) |
1929 | { | 2008 | { |
1930 | char tmp[PROC_NUMBUF]; | 2009 | char tmp[PROC_NUMBUF]; |
1931 | sprintf(tmp, "%d", current->tgid); | 2010 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1932 | return vfs_readlink(dentry,buffer,buflen,tmp); | 2011 | return vfs_readlink(dentry,buffer,buflen,tmp); |
1933 | } | 2012 | } |
1934 | 2013 | ||
1935 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | 2014 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) |
1936 | { | 2015 | { |
1937 | char tmp[PROC_NUMBUF]; | 2016 | char tmp[PROC_NUMBUF]; |
1938 | sprintf(tmp, "%d", current->tgid); | 2017 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1939 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 2018 | return ERR_PTR(vfs_follow_link(nd,tmp)); |
1940 | } | 2019 | } |
1941 | 2020 | ||
@@ -2101,6 +2180,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2101 | REG("environ", S_IRUSR, environ), | 2180 | REG("environ", S_IRUSR, environ), |
2102 | INF("auxv", S_IRUSR, pid_auxv), | 2181 | INF("auxv", S_IRUSR, pid_auxv), |
2103 | INF("status", S_IRUGO, pid_status), | 2182 | INF("status", S_IRUGO, pid_status), |
2183 | INF("limits", S_IRUSR, pid_limits), | ||
2104 | #ifdef CONFIG_SCHED_DEBUG | 2184 | #ifdef CONFIG_SCHED_DEBUG |
2105 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2185 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2106 | #endif | 2186 | #endif |
@@ -2130,9 +2210,12 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2130 | #ifdef CONFIG_SCHEDSTATS | 2210 | #ifdef CONFIG_SCHEDSTATS |
2131 | INF("schedstat", S_IRUGO, pid_schedstat), | 2211 | INF("schedstat", S_IRUGO, pid_schedstat), |
2132 | #endif | 2212 | #endif |
2133 | #ifdef CONFIG_CPUSETS | 2213 | #ifdef CONFIG_PROC_PID_CPUSET |
2134 | REG("cpuset", S_IRUGO, cpuset), | 2214 | REG("cpuset", S_IRUGO, cpuset), |
2135 | #endif | 2215 | #endif |
2216 | #ifdef CONFIG_CGROUPS | ||
2217 | REG("cgroup", S_IRUGO, cgroup), | ||
2218 | #endif | ||
2136 | INF("oom_score", S_IRUGO, oom_score), | 2219 | INF("oom_score", S_IRUGO, oom_score), |
2137 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2220 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2138 | #ifdef CONFIG_AUDITSYSCALL | 2221 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2193,27 +2276,27 @@ static const struct inode_operations proc_tgid_base_inode_operations = { | |||
2193 | * that no dcache entries will exist at process exit time it | 2276 | * that no dcache entries will exist at process exit time it |
2194 | * just makes it very unlikely that any will persist. | 2277 | * just makes it very unlikely that any will persist. |
2195 | */ | 2278 | */ |
2196 | void proc_flush_task(struct task_struct *task) | 2279 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) |
2197 | { | 2280 | { |
2198 | struct dentry *dentry, *leader, *dir; | 2281 | struct dentry *dentry, *leader, *dir; |
2199 | char buf[PROC_NUMBUF]; | 2282 | char buf[PROC_NUMBUF]; |
2200 | struct qstr name; | 2283 | struct qstr name; |
2201 | 2284 | ||
2202 | name.name = buf; | 2285 | name.name = buf; |
2203 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2286 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2204 | dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2287 | dentry = d_hash_and_lookup(mnt->mnt_root, &name); |
2205 | if (dentry) { | 2288 | if (dentry) { |
2206 | shrink_dcache_parent(dentry); | 2289 | shrink_dcache_parent(dentry); |
2207 | d_drop(dentry); | 2290 | d_drop(dentry); |
2208 | dput(dentry); | 2291 | dput(dentry); |
2209 | } | 2292 | } |
2210 | 2293 | ||
2211 | if (thread_group_leader(task)) | 2294 | if (tgid == 0) |
2212 | goto out; | 2295 | goto out; |
2213 | 2296 | ||
2214 | name.name = buf; | 2297 | name.name = buf; |
2215 | name.len = snprintf(buf, sizeof(buf), "%d", task->tgid); | 2298 | name.len = snprintf(buf, sizeof(buf), "%d", tgid); |
2216 | leader = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2299 | leader = d_hash_and_lookup(mnt->mnt_root, &name); |
2217 | if (!leader) | 2300 | if (!leader) |
2218 | goto out; | 2301 | goto out; |
2219 | 2302 | ||
@@ -2224,7 +2307,7 @@ void proc_flush_task(struct task_struct *task) | |||
2224 | goto out_put_leader; | 2307 | goto out_put_leader; |
2225 | 2308 | ||
2226 | name.name = buf; | 2309 | name.name = buf; |
2227 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2310 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2228 | dentry = d_hash_and_lookup(dir, &name); | 2311 | dentry = d_hash_and_lookup(dir, &name); |
2229 | if (dentry) { | 2312 | if (dentry) { |
2230 | shrink_dcache_parent(dentry); | 2313 | shrink_dcache_parent(dentry); |
@@ -2239,6 +2322,36 @@ out: | |||
2239 | return; | 2322 | return; |
2240 | } | 2323 | } |
2241 | 2324 | ||
2325 | /* | ||
2326 | * when flushing dentries from proc one need to flush them from global | ||
2327 | * proc (proc_mnt) and from all the namespaces' procs this task was seen | ||
2328 | * in. this call is supposed to make all this job. | ||
2329 | */ | ||
2330 | |||
2331 | void proc_flush_task(struct task_struct *task) | ||
2332 | { | ||
2333 | int i, leader; | ||
2334 | struct pid *pid, *tgid; | ||
2335 | struct upid *upid; | ||
2336 | |||
2337 | leader = thread_group_leader(task); | ||
2338 | proc_flush_task_mnt(proc_mnt, task->pid, leader ? task->tgid : 0); | ||
2339 | pid = task_pid(task); | ||
2340 | if (pid->level == 0) | ||
2341 | return; | ||
2342 | |||
2343 | tgid = task_tgid(task); | ||
2344 | for (i = 1; i <= pid->level; i++) { | ||
2345 | upid = &pid->numbers[i]; | ||
2346 | proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr, | ||
2347 | leader ? 0 : tgid->numbers[i].nr); | ||
2348 | } | ||
2349 | |||
2350 | upid = &pid->numbers[pid->level]; | ||
2351 | if (upid->nr == 1) | ||
2352 | pid_ns_release_proc(upid->ns); | ||
2353 | } | ||
2354 | |||
2242 | static struct dentry *proc_pid_instantiate(struct inode *dir, | 2355 | static struct dentry *proc_pid_instantiate(struct inode *dir, |
2243 | struct dentry * dentry, | 2356 | struct dentry * dentry, |
2244 | struct task_struct *task, const void *ptr) | 2357 | struct task_struct *task, const void *ptr) |
@@ -2274,6 +2387,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2274 | struct dentry *result = ERR_PTR(-ENOENT); | 2387 | struct dentry *result = ERR_PTR(-ENOENT); |
2275 | struct task_struct *task; | 2388 | struct task_struct *task; |
2276 | unsigned tgid; | 2389 | unsigned tgid; |
2390 | struct pid_namespace *ns; | ||
2277 | 2391 | ||
2278 | result = proc_base_lookup(dir, dentry); | 2392 | result = proc_base_lookup(dir, dentry); |
2279 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) | 2393 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) |
@@ -2283,8 +2397,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2283 | if (tgid == ~0U) | 2397 | if (tgid == ~0U) |
2284 | goto out; | 2398 | goto out; |
2285 | 2399 | ||
2400 | ns = dentry->d_sb->s_fs_info; | ||
2286 | rcu_read_lock(); | 2401 | rcu_read_lock(); |
2287 | task = find_task_by_pid(tgid); | 2402 | task = find_task_by_pid_ns(tgid, ns); |
2288 | if (task) | 2403 | if (task) |
2289 | get_task_struct(task); | 2404 | get_task_struct(task); |
2290 | rcu_read_unlock(); | 2405 | rcu_read_unlock(); |
@@ -2301,7 +2416,8 @@ out: | |||
2301 | * Find the first task with tgid >= tgid | 2416 | * Find the first task with tgid >= tgid |
2302 | * | 2417 | * |
2303 | */ | 2418 | */ |
2304 | static struct task_struct *next_tgid(unsigned int tgid) | 2419 | static struct task_struct *next_tgid(unsigned int tgid, |
2420 | struct pid_namespace *ns) | ||
2305 | { | 2421 | { |
2306 | struct task_struct *task; | 2422 | struct task_struct *task; |
2307 | struct pid *pid; | 2423 | struct pid *pid; |
@@ -2309,9 +2425,9 @@ static struct task_struct *next_tgid(unsigned int tgid) | |||
2309 | rcu_read_lock(); | 2425 | rcu_read_lock(); |
2310 | retry: | 2426 | retry: |
2311 | task = NULL; | 2427 | task = NULL; |
2312 | pid = find_ge_pid(tgid); | 2428 | pid = find_ge_pid(tgid, ns); |
2313 | if (pid) { | 2429 | if (pid) { |
2314 | tgid = pid->nr + 1; | 2430 | tgid = pid_nr_ns(pid, ns) + 1; |
2315 | task = pid_task(pid, PIDTYPE_PID); | 2431 | task = pid_task(pid, PIDTYPE_PID); |
2316 | /* What we to know is if the pid we have find is the | 2432 | /* What we to know is if the pid we have find is the |
2317 | * pid of a thread_group_leader. Testing for task | 2433 | * pid of a thread_group_leader. Testing for task |
@@ -2351,6 +2467,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2351 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2467 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2352 | struct task_struct *task; | 2468 | struct task_struct *task; |
2353 | int tgid; | 2469 | int tgid; |
2470 | struct pid_namespace *ns; | ||
2354 | 2471 | ||
2355 | if (!reaper) | 2472 | if (!reaper) |
2356 | goto out_no_task; | 2473 | goto out_no_task; |
@@ -2361,11 +2478,12 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2361 | goto out; | 2478 | goto out; |
2362 | } | 2479 | } |
2363 | 2480 | ||
2481 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2364 | tgid = filp->f_pos - TGID_OFFSET; | 2482 | tgid = filp->f_pos - TGID_OFFSET; |
2365 | for (task = next_tgid(tgid); | 2483 | for (task = next_tgid(tgid, ns); |
2366 | task; | 2484 | task; |
2367 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2485 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { |
2368 | tgid = task->pid; | 2486 | tgid = task_pid_nr_ns(task, ns); |
2369 | filp->f_pos = tgid + TGID_OFFSET; | 2487 | filp->f_pos = tgid + TGID_OFFSET; |
2370 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2488 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2371 | put_task_struct(task); | 2489 | put_task_struct(task); |
@@ -2388,6 +2506,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2388 | REG("environ", S_IRUSR, environ), | 2506 | REG("environ", S_IRUSR, environ), |
2389 | INF("auxv", S_IRUSR, pid_auxv), | 2507 | INF("auxv", S_IRUSR, pid_auxv), |
2390 | INF("status", S_IRUGO, pid_status), | 2508 | INF("status", S_IRUGO, pid_status), |
2509 | INF("limits", S_IRUSR, pid_limits), | ||
2391 | #ifdef CONFIG_SCHED_DEBUG | 2510 | #ifdef CONFIG_SCHED_DEBUG |
2392 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2511 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2393 | #endif | 2512 | #endif |
@@ -2416,9 +2535,12 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2416 | #ifdef CONFIG_SCHEDSTATS | 2535 | #ifdef CONFIG_SCHEDSTATS |
2417 | INF("schedstat", S_IRUGO, pid_schedstat), | 2536 | INF("schedstat", S_IRUGO, pid_schedstat), |
2418 | #endif | 2537 | #endif |
2419 | #ifdef CONFIG_CPUSETS | 2538 | #ifdef CONFIG_PROC_PID_CPUSET |
2420 | REG("cpuset", S_IRUGO, cpuset), | 2539 | REG("cpuset", S_IRUGO, cpuset), |
2421 | #endif | 2540 | #endif |
2541 | #ifdef CONFIG_CGROUPS | ||
2542 | REG("cgroup", S_IRUGO, cgroup), | ||
2543 | #endif | ||
2422 | INF("oom_score", S_IRUGO, oom_score), | 2544 | INF("oom_score", S_IRUGO, oom_score), |
2423 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2545 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2424 | #ifdef CONFIG_AUDITSYSCALL | 2546 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2486,6 +2608,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2486 | struct task_struct *task; | 2608 | struct task_struct *task; |
2487 | struct task_struct *leader = get_proc_task(dir); | 2609 | struct task_struct *leader = get_proc_task(dir); |
2488 | unsigned tid; | 2610 | unsigned tid; |
2611 | struct pid_namespace *ns; | ||
2489 | 2612 | ||
2490 | if (!leader) | 2613 | if (!leader) |
2491 | goto out_no_task; | 2614 | goto out_no_task; |
@@ -2494,14 +2617,15 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2494 | if (tid == ~0U) | 2617 | if (tid == ~0U) |
2495 | goto out; | 2618 | goto out; |
2496 | 2619 | ||
2620 | ns = dentry->d_sb->s_fs_info; | ||
2497 | rcu_read_lock(); | 2621 | rcu_read_lock(); |
2498 | task = find_task_by_pid(tid); | 2622 | task = find_task_by_pid_ns(tid, ns); |
2499 | if (task) | 2623 | if (task) |
2500 | get_task_struct(task); | 2624 | get_task_struct(task); |
2501 | rcu_read_unlock(); | 2625 | rcu_read_unlock(); |
2502 | if (!task) | 2626 | if (!task) |
2503 | goto out; | 2627 | goto out; |
2504 | if (leader->tgid != task->tgid) | 2628 | if (!same_thread_group(leader, task)) |
2505 | goto out_drop_task; | 2629 | goto out_drop_task; |
2506 | 2630 | ||
2507 | result = proc_task_instantiate(dir, dentry, task, NULL); | 2631 | result = proc_task_instantiate(dir, dentry, task, NULL); |
@@ -2526,14 +2650,14 @@ out_no_task: | |||
2526 | * threads past it. | 2650 | * threads past it. |
2527 | */ | 2651 | */ |
2528 | static struct task_struct *first_tid(struct task_struct *leader, | 2652 | static struct task_struct *first_tid(struct task_struct *leader, |
2529 | int tid, int nr) | 2653 | int tid, int nr, struct pid_namespace *ns) |
2530 | { | 2654 | { |
2531 | struct task_struct *pos; | 2655 | struct task_struct *pos; |
2532 | 2656 | ||
2533 | rcu_read_lock(); | 2657 | rcu_read_lock(); |
2534 | /* Attempt to start with the pid of a thread */ | 2658 | /* Attempt to start with the pid of a thread */ |
2535 | if (tid && (nr > 0)) { | 2659 | if (tid && (nr > 0)) { |
2536 | pos = find_task_by_pid(tid); | 2660 | pos = find_task_by_pid_ns(tid, ns); |
2537 | if (pos && (pos->group_leader == leader)) | 2661 | if (pos && (pos->group_leader == leader)) |
2538 | goto found; | 2662 | goto found; |
2539 | } | 2663 | } |
@@ -2602,6 +2726,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2602 | ino_t ino; | 2726 | ino_t ino; |
2603 | int tid; | 2727 | int tid; |
2604 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ | 2728 | unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ |
2729 | struct pid_namespace *ns; | ||
2605 | 2730 | ||
2606 | task = get_proc_task(inode); | 2731 | task = get_proc_task(inode); |
2607 | if (!task) | 2732 | if (!task) |
@@ -2635,12 +2760,13 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2635 | /* f_version caches the tgid value that the last readdir call couldn't | 2760 | /* f_version caches the tgid value that the last readdir call couldn't |
2636 | * return. lseek aka telldir automagically resets f_version to 0. | 2761 | * return. lseek aka telldir automagically resets f_version to 0. |
2637 | */ | 2762 | */ |
2763 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2638 | tid = (int)filp->f_version; | 2764 | tid = (int)filp->f_version; |
2639 | filp->f_version = 0; | 2765 | filp->f_version = 0; |
2640 | for (task = first_tid(leader, tid, pos - 2); | 2766 | for (task = first_tid(leader, tid, pos - 2, ns); |
2641 | task; | 2767 | task; |
2642 | task = next_tid(task), pos++) { | 2768 | task = next_tid(task), pos++) { |
2643 | tid = task->pid; | 2769 | tid = task_pid_nr_ns(task, ns); |
2644 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 2770 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2645 | /* returning this tgid failed, save it as the first | 2771 | /* returning this tgid failed, save it as the first |
2646 | * pid for the next readir call */ | 2772 | * pid for the next readir call */ |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 99ca00485fc3..abe6a3f04368 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -448,7 +448,7 @@ out_mod: | |||
448 | return NULL; | 448 | return NULL; |
449 | } | 449 | } |
450 | 450 | ||
451 | int proc_fill_super(struct super_block *s, void *data, int silent) | 451 | int proc_fill_super(struct super_block *s) |
452 | { | 452 | { |
453 | struct inode * root_inode; | 453 | struct inode * root_inode; |
454 | 454 | ||
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index d6dc72c78bc1..e0d064e9764e 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -91,7 +91,8 @@ static int loadavg_read_proc(char *page, char **start, off_t off, | |||
91 | LOAD_INT(a), LOAD_FRAC(a), | 91 | LOAD_INT(a), LOAD_FRAC(a), |
92 | LOAD_INT(b), LOAD_FRAC(b), | 92 | LOAD_INT(b), LOAD_FRAC(b), |
93 | LOAD_INT(c), LOAD_FRAC(c), | 93 | LOAD_INT(c), LOAD_FRAC(c), |
94 | nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid); | 94 | nr_running(), nr_threads, |
95 | task_active_pid_ns(current)->last_pid); | ||
95 | return proc_calc_metrics(page, start, off, count, eof, len); | 96 | return proc_calc_metrics(page, start, off, count, eof, len); |
96 | } | 97 | } |
97 | 98 | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index cf3046638b09..ec9cb3b6c93b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -18,32 +18,90 @@ | |||
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
20 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
21 | #include <linux/pid_namespace.h> | ||
21 | 22 | ||
22 | #include "internal.h" | 23 | #include "internal.h" |
23 | 24 | ||
24 | struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver; | 25 | struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver; |
25 | 26 | ||
27 | static int proc_test_super(struct super_block *sb, void *data) | ||
28 | { | ||
29 | return sb->s_fs_info == data; | ||
30 | } | ||
31 | |||
32 | static int proc_set_super(struct super_block *sb, void *data) | ||
33 | { | ||
34 | struct pid_namespace *ns; | ||
35 | |||
36 | ns = (struct pid_namespace *)data; | ||
37 | sb->s_fs_info = get_pid_ns(ns); | ||
38 | return set_anon_super(sb, NULL); | ||
39 | } | ||
40 | |||
26 | static int proc_get_sb(struct file_system_type *fs_type, | 41 | static int proc_get_sb(struct file_system_type *fs_type, |
27 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 42 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
28 | { | 43 | { |
44 | int err; | ||
45 | struct super_block *sb; | ||
46 | struct pid_namespace *ns; | ||
47 | struct proc_inode *ei; | ||
48 | |||
29 | if (proc_mnt) { | 49 | if (proc_mnt) { |
30 | /* Seed the root directory with a pid so it doesn't need | 50 | /* Seed the root directory with a pid so it doesn't need |
31 | * to be special in base.c. I would do this earlier but | 51 | * to be special in base.c. I would do this earlier but |
32 | * the only task alive when /proc is mounted the first time | 52 | * the only task alive when /proc is mounted the first time |
33 | * is the init_task and it doesn't have any pids. | 53 | * is the init_task and it doesn't have any pids. |
34 | */ | 54 | */ |
35 | struct proc_inode *ei; | ||
36 | ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); | 55 | ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); |
37 | if (!ei->pid) | 56 | if (!ei->pid) |
38 | ei->pid = find_get_pid(1); | 57 | ei->pid = find_get_pid(1); |
39 | } | 58 | } |
40 | return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); | 59 | |
60 | if (flags & MS_KERNMOUNT) | ||
61 | ns = (struct pid_namespace *)data; | ||
62 | else | ||
63 | ns = current->nsproxy->pid_ns; | ||
64 | |||
65 | sb = sget(fs_type, proc_test_super, proc_set_super, ns); | ||
66 | if (IS_ERR(sb)) | ||
67 | return PTR_ERR(sb); | ||
68 | |||
69 | if (!sb->s_root) { | ||
70 | sb->s_flags = flags; | ||
71 | err = proc_fill_super(sb); | ||
72 | if (err) { | ||
73 | up_write(&sb->s_umount); | ||
74 | deactivate_super(sb); | ||
75 | return err; | ||
76 | } | ||
77 | |||
78 | ei = PROC_I(sb->s_root->d_inode); | ||
79 | if (!ei->pid) { | ||
80 | rcu_read_lock(); | ||
81 | ei->pid = get_pid(find_pid_ns(1, ns)); | ||
82 | rcu_read_unlock(); | ||
83 | } | ||
84 | |||
85 | sb->s_flags |= MS_ACTIVE; | ||
86 | ns->proc_mnt = mnt; | ||
87 | } | ||
88 | |||
89 | return simple_set_mnt(mnt, sb); | ||
90 | } | ||
91 | |||
92 | static void proc_kill_sb(struct super_block *sb) | ||
93 | { | ||
94 | struct pid_namespace *ns; | ||
95 | |||
96 | ns = (struct pid_namespace *)sb->s_fs_info; | ||
97 | kill_anon_super(sb); | ||
98 | put_pid_ns(ns); | ||
41 | } | 99 | } |
42 | 100 | ||
43 | static struct file_system_type proc_fs_type = { | 101 | static struct file_system_type proc_fs_type = { |
44 | .name = "proc", | 102 | .name = "proc", |
45 | .get_sb = proc_get_sb, | 103 | .get_sb = proc_get_sb, |
46 | .kill_sb = kill_anon_super, | 104 | .kill_sb = proc_kill_sb, |
47 | }; | 105 | }; |
48 | 106 | ||
49 | void __init proc_root_init(void) | 107 | void __init proc_root_init(void) |
@@ -54,12 +112,13 @@ void __init proc_root_init(void) | |||
54 | err = register_filesystem(&proc_fs_type); | 112 | err = register_filesystem(&proc_fs_type); |
55 | if (err) | 113 | if (err) |
56 | return; | 114 | return; |
57 | proc_mnt = kern_mount(&proc_fs_type); | 115 | proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); |
58 | err = PTR_ERR(proc_mnt); | 116 | err = PTR_ERR(proc_mnt); |
59 | if (IS_ERR(proc_mnt)) { | 117 | if (IS_ERR(proc_mnt)) { |
60 | unregister_filesystem(&proc_fs_type); | 118 | unregister_filesystem(&proc_fs_type); |
61 | return; | 119 | return; |
62 | } | 120 | } |
121 | |||
63 | proc_misc_init(); | 122 | proc_misc_init(); |
64 | 123 | ||
65 | proc_net_init(); | 124 | proc_net_init(); |
@@ -153,6 +212,22 @@ struct proc_dir_entry proc_root = { | |||
153 | .parent = &proc_root, | 212 | .parent = &proc_root, |
154 | }; | 213 | }; |
155 | 214 | ||
215 | int pid_ns_prepare_proc(struct pid_namespace *ns) | ||
216 | { | ||
217 | struct vfsmount *mnt; | ||
218 | |||
219 | mnt = kern_mount_data(&proc_fs_type, ns); | ||
220 | if (IS_ERR(mnt)) | ||
221 | return PTR_ERR(mnt); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | void pid_ns_release_proc(struct pid_namespace *ns) | ||
227 | { | ||
228 | mntput(ns->proc_mnt); | ||
229 | } | ||
230 | |||
156 | EXPORT_SYMBOL(proc_symlink); | 231 | EXPORT_SYMBOL(proc_symlink); |
157 | EXPORT_SYMBOL(proc_mkdir); | 232 | EXPORT_SYMBOL(proc_mkdir); |
158 | EXPORT_SYMBOL(create_proc_entry); | 233 | EXPORT_SYMBOL(create_proc_entry); |