diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 316 |
1 files changed, 246 insertions, 70 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 19489b0d5554..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: |
@@ -199,27 +202,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
199 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ | 202 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ |
200 | security_ptrace(current,task) == 0)) | 203 | security_ptrace(current,task) == 0)) |
201 | 204 | ||
202 | static int proc_pid_environ(struct task_struct *task, char * buffer) | ||
203 | { | ||
204 | int res = 0; | ||
205 | struct mm_struct *mm = get_task_mm(task); | ||
206 | if (mm) { | ||
207 | unsigned int len; | ||
208 | |||
209 | res = -ESRCH; | ||
210 | if (!ptrace_may_attach(task)) | ||
211 | goto out; | ||
212 | |||
213 | len = mm->env_end - mm->env_start; | ||
214 | if (len > PAGE_SIZE) | ||
215 | len = PAGE_SIZE; | ||
216 | res = access_process_vm(task, mm->env_start, buffer, len, 0); | ||
217 | out: | ||
218 | mmput(mm); | ||
219 | } | ||
220 | return res; | ||
221 | } | ||
222 | |||
223 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 205 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
224 | { | 206 | { |
225 | int res = 0; | 207 | int res = 0; |
@@ -304,7 +286,7 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer) | |||
304 | return sprintf(buffer, "%llu %llu %lu\n", | 286 | return sprintf(buffer, "%llu %llu %lu\n", |
305 | task->sched_info.cpu_time, | 287 | task->sched_info.cpu_time, |
306 | task->sched_info.run_delay, | 288 | task->sched_info.run_delay, |
307 | task->sched_info.pcnt); | 289 | task->sched_info.pcount); |
308 | } | 290 | } |
309 | #endif | 291 | #endif |
310 | 292 | ||
@@ -322,6 +304,78 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
322 | return sprintf(buffer, "%lu\n", points); | 304 | return sprintf(buffer, "%lu\n", points); |
323 | } | 305 | } |
324 | 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 | |||
325 | /************************************************************************/ | 379 | /************************************************************************/ |
326 | /* Here the fs part begins */ | 380 | /* Here the fs part begins */ |
327 | /************************************************************************/ | 381 | /************************************************************************/ |
@@ -370,18 +424,21 @@ struct proc_mounts { | |||
370 | static int mounts_open(struct inode *inode, struct file *file) | 424 | static int mounts_open(struct inode *inode, struct file *file) |
371 | { | 425 | { |
372 | struct task_struct *task = get_proc_task(inode); | 426 | struct task_struct *task = get_proc_task(inode); |
427 | struct nsproxy *nsp; | ||
373 | struct mnt_namespace *ns = NULL; | 428 | struct mnt_namespace *ns = NULL; |
374 | struct proc_mounts *p; | 429 | struct proc_mounts *p; |
375 | int ret = -EINVAL; | 430 | int ret = -EINVAL; |
376 | 431 | ||
377 | if (task) { | 432 | if (task) { |
378 | task_lock(task); | 433 | rcu_read_lock(); |
379 | if (task->nsproxy) { | 434 | nsp = task_nsproxy(task); |
380 | ns = task->nsproxy->mnt_ns; | 435 | if (nsp) { |
436 | ns = nsp->mnt_ns; | ||
381 | if (ns) | 437 | if (ns) |
382 | get_mnt_ns(ns); | 438 | get_mnt_ns(ns); |
383 | } | 439 | } |
384 | task_unlock(task); | 440 | rcu_read_unlock(); |
441 | |||
385 | put_task_struct(task); | 442 | put_task_struct(task); |
386 | } | 443 | } |
387 | 444 | ||
@@ -444,16 +501,20 @@ static int mountstats_open(struct inode *inode, struct file *file) | |||
444 | 501 | ||
445 | if (!ret) { | 502 | if (!ret) { |
446 | struct seq_file *m = file->private_data; | 503 | struct seq_file *m = file->private_data; |
504 | struct nsproxy *nsp; | ||
447 | struct mnt_namespace *mnt_ns = NULL; | 505 | struct mnt_namespace *mnt_ns = NULL; |
448 | struct task_struct *task = get_proc_task(inode); | 506 | struct task_struct *task = get_proc_task(inode); |
449 | 507 | ||
450 | if (task) { | 508 | if (task) { |
451 | task_lock(task); | 509 | rcu_read_lock(); |
452 | if (task->nsproxy) | 510 | nsp = task_nsproxy(task); |
453 | mnt_ns = task->nsproxy->mnt_ns; | 511 | if (nsp) { |
454 | if (mnt_ns) | 512 | mnt_ns = nsp->mnt_ns; |
455 | get_mnt_ns(mnt_ns); | 513 | if (mnt_ns) |
456 | task_unlock(task); | 514 | get_mnt_ns(mnt_ns); |
515 | } | ||
516 | rcu_read_unlock(); | ||
517 | |||
457 | put_task_struct(task); | 518 | put_task_struct(task); |
458 | } | 519 | } |
459 | 520 | ||
@@ -492,7 +553,7 @@ static ssize_t proc_info_read(struct file * file, char __user * buf, | |||
492 | count = PROC_BLOCK_SIZE; | 553 | count = PROC_BLOCK_SIZE; |
493 | 554 | ||
494 | length = -ENOMEM; | 555 | length = -ENOMEM; |
495 | if (!(page = __get_free_page(GFP_KERNEL))) | 556 | if (!(page = __get_free_page(GFP_TEMPORARY))) |
496 | goto out; | 557 | goto out; |
497 | 558 | ||
498 | length = PROC_I(inode)->op.proc_read(task, (char*)page); | 559 | length = PROC_I(inode)->op.proc_read(task, (char*)page); |
@@ -532,7 +593,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, | |||
532 | goto out; | 593 | goto out; |
533 | 594 | ||
534 | ret = -ENOMEM; | 595 | ret = -ENOMEM; |
535 | page = (char *)__get_free_page(GFP_USER); | 596 | page = (char *)__get_free_page(GFP_TEMPORARY); |
536 | if (!page) | 597 | if (!page) |
537 | goto out; | 598 | goto out; |
538 | 599 | ||
@@ -602,7 +663,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
602 | goto out; | 663 | goto out; |
603 | 664 | ||
604 | copied = -ENOMEM; | 665 | copied = -ENOMEM; |
605 | page = (char *)__get_free_page(GFP_USER); | 666 | page = (char *)__get_free_page(GFP_TEMPORARY); |
606 | if (!page) | 667 | if (!page) |
607 | goto out; | 668 | goto out; |
608 | 669 | ||
@@ -658,6 +719,76 @@ static const struct file_operations proc_mem_operations = { | |||
658 | .open = mem_open, | 719 | .open = mem_open, |
659 | }; | 720 | }; |
660 | 721 | ||
722 | static ssize_t environ_read(struct file *file, char __user *buf, | ||
723 | size_t count, loff_t *ppos) | ||
724 | { | ||
725 | struct task_struct *task = get_proc_task(file->f_dentry->d_inode); | ||
726 | char *page; | ||
727 | unsigned long src = *ppos; | ||
728 | int ret = -ESRCH; | ||
729 | struct mm_struct *mm; | ||
730 | |||
731 | if (!task) | ||
732 | goto out_no_task; | ||
733 | |||
734 | if (!ptrace_may_attach(task)) | ||
735 | goto out; | ||
736 | |||
737 | ret = -ENOMEM; | ||
738 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
739 | if (!page) | ||
740 | goto out; | ||
741 | |||
742 | ret = 0; | ||
743 | |||
744 | mm = get_task_mm(task); | ||
745 | if (!mm) | ||
746 | goto out_free; | ||
747 | |||
748 | while (count > 0) { | ||
749 | int this_len, retval, max_len; | ||
750 | |||
751 | this_len = mm->env_end - (mm->env_start + src); | ||
752 | |||
753 | if (this_len <= 0) | ||
754 | break; | ||
755 | |||
756 | max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | ||
757 | this_len = (this_len > max_len) ? max_len : this_len; | ||
758 | |||
759 | retval = access_process_vm(task, (mm->env_start + src), | ||
760 | page, this_len, 0); | ||
761 | |||
762 | if (retval <= 0) { | ||
763 | ret = retval; | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | if (copy_to_user(buf, page, retval)) { | ||
768 | ret = -EFAULT; | ||
769 | break; | ||
770 | } | ||
771 | |||
772 | ret += retval; | ||
773 | src += retval; | ||
774 | buf += retval; | ||
775 | count -= retval; | ||
776 | } | ||
777 | *ppos = src; | ||
778 | |||
779 | mmput(mm); | ||
780 | out_free: | ||
781 | free_page((unsigned long) page); | ||
782 | out: | ||
783 | put_task_struct(task); | ||
784 | out_no_task: | ||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | static const struct file_operations proc_environ_operations = { | ||
789 | .read = environ_read, | ||
790 | }; | ||
791 | |||
661 | static ssize_t oom_adjust_read(struct file *file, char __user *buf, | 792 | static ssize_t oom_adjust_read(struct file *file, char __user *buf, |
662 | size_t count, loff_t *ppos) | 793 | size_t count, loff_t *ppos) |
663 | { | 794 | { |
@@ -788,7 +919,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, | |||
788 | /* No partial writes. */ | 919 | /* No partial writes. */ |
789 | return -EINVAL; | 920 | return -EINVAL; |
790 | } | 921 | } |
791 | page = (char*)__get_free_page(GFP_USER); | 922 | page = (char*)__get_free_page(GFP_TEMPORARY); |
792 | if (!page) | 923 | if (!page) |
793 | return -ENOMEM; | 924 | return -ENOMEM; |
794 | length = -EFAULT; | 925 | length = -EFAULT; |
@@ -954,7 +1085,8 @@ static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, | |||
954 | char __user *buffer, int buflen) | 1085 | char __user *buffer, int buflen) |
955 | { | 1086 | { |
956 | struct inode * inode; | 1087 | struct inode * inode; |
957 | char *tmp = (char*)__get_free_page(GFP_KERNEL), *path; | 1088 | char *tmp = (char*)__get_free_page(GFP_TEMPORARY); |
1089 | char *path; | ||
958 | int len; | 1090 | int len; |
959 | 1091 | ||
960 | if (!tmp) | 1092 | if (!tmp) |
@@ -1387,7 +1519,7 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1387 | struct dentry *dentry = filp->f_path.dentry; | 1519 | struct dentry *dentry = filp->f_path.dentry; |
1388 | struct inode *inode = dentry->d_inode; | 1520 | struct inode *inode = dentry->d_inode; |
1389 | struct task_struct *p = get_proc_task(inode); | 1521 | struct task_struct *p = get_proc_task(inode); |
1390 | unsigned int fd, tid, ino; | 1522 | unsigned int fd, ino; |
1391 | int retval; | 1523 | int retval; |
1392 | struct files_struct * files; | 1524 | struct files_struct * files; |
1393 | struct fdtable *fdt; | 1525 | struct fdtable *fdt; |
@@ -1396,7 +1528,6 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
1396 | if (!p) | 1528 | if (!p) |
1397 | goto out_no_task; | 1529 | goto out_no_task; |
1398 | retval = 0; | 1530 | retval = 0; |
1399 | tid = p->pid; | ||
1400 | 1531 | ||
1401 | fd = filp->f_pos; | 1532 | fd = filp->f_pos; |
1402 | switch (fd) { | 1533 | switch (fd) { |
@@ -1631,7 +1762,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1631 | const struct pid_entry *ents, unsigned int nents) | 1762 | const struct pid_entry *ents, unsigned int nents) |
1632 | { | 1763 | { |
1633 | int i; | 1764 | int i; |
1634 | int pid; | ||
1635 | struct dentry *dentry = filp->f_path.dentry; | 1765 | struct dentry *dentry = filp->f_path.dentry; |
1636 | struct inode *inode = dentry->d_inode; | 1766 | struct inode *inode = dentry->d_inode; |
1637 | struct task_struct *task = get_proc_task(inode); | 1767 | struct task_struct *task = get_proc_task(inode); |
@@ -1644,7 +1774,6 @@ static int proc_pident_readdir(struct file *filp, | |||
1644 | goto out_no_task; | 1774 | goto out_no_task; |
1645 | 1775 | ||
1646 | ret = 0; | 1776 | ret = 0; |
1647 | pid = task->pid; | ||
1648 | i = filp->f_pos; | 1777 | i = filp->f_pos; |
1649 | switch (i) { | 1778 | switch (i) { |
1650 | case 0: | 1779 | case 0: |
@@ -1726,7 +1855,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, | |||
1726 | goto out; | 1855 | goto out; |
1727 | 1856 | ||
1728 | length = -ENOMEM; | 1857 | length = -ENOMEM; |
1729 | page = (char*)__get_free_page(GFP_USER); | 1858 | page = (char*)__get_free_page(GFP_TEMPORARY); |
1730 | if (!page) | 1859 | if (!page) |
1731 | goto out; | 1860 | goto out; |
1732 | 1861 | ||
@@ -1878,14 +2007,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
1878 | int buflen) | 2007 | int buflen) |
1879 | { | 2008 | { |
1880 | char tmp[PROC_NUMBUF]; | 2009 | char tmp[PROC_NUMBUF]; |
1881 | sprintf(tmp, "%d", current->tgid); | 2010 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1882 | return vfs_readlink(dentry,buffer,buflen,tmp); | 2011 | return vfs_readlink(dentry,buffer,buflen,tmp); |
1883 | } | 2012 | } |
1884 | 2013 | ||
1885 | 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) |
1886 | { | 2015 | { |
1887 | char tmp[PROC_NUMBUF]; | 2016 | char tmp[PROC_NUMBUF]; |
1888 | sprintf(tmp, "%d", current->tgid); | 2017 | sprintf(tmp, "%d", task_tgid_vnr(current)); |
1889 | return ERR_PTR(vfs_follow_link(nd,tmp)); | 2018 | return ERR_PTR(vfs_follow_link(nd,tmp)); |
1890 | } | 2019 | } |
1891 | 2020 | ||
@@ -2048,9 +2177,10 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2048 | DIR("task", S_IRUGO|S_IXUGO, task), | 2177 | DIR("task", S_IRUGO|S_IXUGO, task), |
2049 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2178 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2050 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2179 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), |
2051 | INF("environ", S_IRUSR, pid_environ), | 2180 | REG("environ", S_IRUSR, environ), |
2052 | INF("auxv", S_IRUSR, pid_auxv), | 2181 | INF("auxv", S_IRUSR, pid_auxv), |
2053 | INF("status", S_IRUGO, pid_status), | 2182 | INF("status", S_IRUGO, pid_status), |
2183 | INF("limits", S_IRUSR, pid_limits), | ||
2054 | #ifdef CONFIG_SCHED_DEBUG | 2184 | #ifdef CONFIG_SCHED_DEBUG |
2055 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2185 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2056 | #endif | 2186 | #endif |
@@ -2080,9 +2210,12 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2080 | #ifdef CONFIG_SCHEDSTATS | 2210 | #ifdef CONFIG_SCHEDSTATS |
2081 | INF("schedstat", S_IRUGO, pid_schedstat), | 2211 | INF("schedstat", S_IRUGO, pid_schedstat), |
2082 | #endif | 2212 | #endif |
2083 | #ifdef CONFIG_CPUSETS | 2213 | #ifdef CONFIG_PROC_PID_CPUSET |
2084 | REG("cpuset", S_IRUGO, cpuset), | 2214 | REG("cpuset", S_IRUGO, cpuset), |
2085 | #endif | 2215 | #endif |
2216 | #ifdef CONFIG_CGROUPS | ||
2217 | REG("cgroup", S_IRUGO, cgroup), | ||
2218 | #endif | ||
2086 | INF("oom_score", S_IRUGO, oom_score), | 2219 | INF("oom_score", S_IRUGO, oom_score), |
2087 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2220 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2088 | #ifdef CONFIG_AUDITSYSCALL | 2221 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2143,27 +2276,27 @@ static const struct inode_operations proc_tgid_base_inode_operations = { | |||
2143 | * that no dcache entries will exist at process exit time it | 2276 | * that no dcache entries will exist at process exit time it |
2144 | * just makes it very unlikely that any will persist. | 2277 | * just makes it very unlikely that any will persist. |
2145 | */ | 2278 | */ |
2146 | void proc_flush_task(struct task_struct *task) | 2279 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) |
2147 | { | 2280 | { |
2148 | struct dentry *dentry, *leader, *dir; | 2281 | struct dentry *dentry, *leader, *dir; |
2149 | char buf[PROC_NUMBUF]; | 2282 | char buf[PROC_NUMBUF]; |
2150 | struct qstr name; | 2283 | struct qstr name; |
2151 | 2284 | ||
2152 | name.name = buf; | 2285 | name.name = buf; |
2153 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2286 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2154 | dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2287 | dentry = d_hash_and_lookup(mnt->mnt_root, &name); |
2155 | if (dentry) { | 2288 | if (dentry) { |
2156 | shrink_dcache_parent(dentry); | 2289 | shrink_dcache_parent(dentry); |
2157 | d_drop(dentry); | 2290 | d_drop(dentry); |
2158 | dput(dentry); | 2291 | dput(dentry); |
2159 | } | 2292 | } |
2160 | 2293 | ||
2161 | if (thread_group_leader(task)) | 2294 | if (tgid == 0) |
2162 | goto out; | 2295 | goto out; |
2163 | 2296 | ||
2164 | name.name = buf; | 2297 | name.name = buf; |
2165 | name.len = snprintf(buf, sizeof(buf), "%d", task->tgid); | 2298 | name.len = snprintf(buf, sizeof(buf), "%d", tgid); |
2166 | leader = d_hash_and_lookup(proc_mnt->mnt_root, &name); | 2299 | leader = d_hash_and_lookup(mnt->mnt_root, &name); |
2167 | if (!leader) | 2300 | if (!leader) |
2168 | goto out; | 2301 | goto out; |
2169 | 2302 | ||
@@ -2174,7 +2307,7 @@ void proc_flush_task(struct task_struct *task) | |||
2174 | goto out_put_leader; | 2307 | goto out_put_leader; |
2175 | 2308 | ||
2176 | name.name = buf; | 2309 | name.name = buf; |
2177 | name.len = snprintf(buf, sizeof(buf), "%d", task->pid); | 2310 | name.len = snprintf(buf, sizeof(buf), "%d", pid); |
2178 | dentry = d_hash_and_lookup(dir, &name); | 2311 | dentry = d_hash_and_lookup(dir, &name); |
2179 | if (dentry) { | 2312 | if (dentry) { |
2180 | shrink_dcache_parent(dentry); | 2313 | shrink_dcache_parent(dentry); |
@@ -2189,6 +2322,36 @@ out: | |||
2189 | return; | 2322 | return; |
2190 | } | 2323 | } |
2191 | 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 | |||
2192 | static struct dentry *proc_pid_instantiate(struct inode *dir, | 2355 | static struct dentry *proc_pid_instantiate(struct inode *dir, |
2193 | struct dentry * dentry, | 2356 | struct dentry * dentry, |
2194 | struct task_struct *task, const void *ptr) | 2357 | struct task_struct *task, const void *ptr) |
@@ -2224,6 +2387,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2224 | struct dentry *result = ERR_PTR(-ENOENT); | 2387 | struct dentry *result = ERR_PTR(-ENOENT); |
2225 | struct task_struct *task; | 2388 | struct task_struct *task; |
2226 | unsigned tgid; | 2389 | unsigned tgid; |
2390 | struct pid_namespace *ns; | ||
2227 | 2391 | ||
2228 | result = proc_base_lookup(dir, dentry); | 2392 | result = proc_base_lookup(dir, dentry); |
2229 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) | 2393 | if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT) |
@@ -2233,8 +2397,9 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct | |||
2233 | if (tgid == ~0U) | 2397 | if (tgid == ~0U) |
2234 | goto out; | 2398 | goto out; |
2235 | 2399 | ||
2400 | ns = dentry->d_sb->s_fs_info; | ||
2236 | rcu_read_lock(); | 2401 | rcu_read_lock(); |
2237 | task = find_task_by_pid(tgid); | 2402 | task = find_task_by_pid_ns(tgid, ns); |
2238 | if (task) | 2403 | if (task) |
2239 | get_task_struct(task); | 2404 | get_task_struct(task); |
2240 | rcu_read_unlock(); | 2405 | rcu_read_unlock(); |
@@ -2251,7 +2416,8 @@ out: | |||
2251 | * Find the first task with tgid >= tgid | 2416 | * Find the first task with tgid >= tgid |
2252 | * | 2417 | * |
2253 | */ | 2418 | */ |
2254 | static struct task_struct *next_tgid(unsigned int tgid) | 2419 | static struct task_struct *next_tgid(unsigned int tgid, |
2420 | struct pid_namespace *ns) | ||
2255 | { | 2421 | { |
2256 | struct task_struct *task; | 2422 | struct task_struct *task; |
2257 | struct pid *pid; | 2423 | struct pid *pid; |
@@ -2259,9 +2425,9 @@ static struct task_struct *next_tgid(unsigned int tgid) | |||
2259 | rcu_read_lock(); | 2425 | rcu_read_lock(); |
2260 | retry: | 2426 | retry: |
2261 | task = NULL; | 2427 | task = NULL; |
2262 | pid = find_ge_pid(tgid); | 2428 | pid = find_ge_pid(tgid, ns); |
2263 | if (pid) { | 2429 | if (pid) { |
2264 | tgid = pid->nr + 1; | 2430 | tgid = pid_nr_ns(pid, ns) + 1; |
2265 | task = pid_task(pid, PIDTYPE_PID); | 2431 | task = pid_task(pid, PIDTYPE_PID); |
2266 | /* 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 |
2267 | * pid of a thread_group_leader. Testing for task | 2433 | * pid of a thread_group_leader. Testing for task |
@@ -2301,6 +2467,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2301 | 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); |
2302 | struct task_struct *task; | 2468 | struct task_struct *task; |
2303 | int tgid; | 2469 | int tgid; |
2470 | struct pid_namespace *ns; | ||
2304 | 2471 | ||
2305 | if (!reaper) | 2472 | if (!reaper) |
2306 | goto out_no_task; | 2473 | goto out_no_task; |
@@ -2311,11 +2478,12 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2311 | goto out; | 2478 | goto out; |
2312 | } | 2479 | } |
2313 | 2480 | ||
2481 | ns = filp->f_dentry->d_sb->s_fs_info; | ||
2314 | tgid = filp->f_pos - TGID_OFFSET; | 2482 | tgid = filp->f_pos - TGID_OFFSET; |
2315 | for (task = next_tgid(tgid); | 2483 | for (task = next_tgid(tgid, ns); |
2316 | task; | 2484 | task; |
2317 | put_task_struct(task), task = next_tgid(tgid + 1)) { | 2485 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { |
2318 | tgid = task->pid; | 2486 | tgid = task_pid_nr_ns(task, ns); |
2319 | filp->f_pos = tgid + TGID_OFFSET; | 2487 | filp->f_pos = tgid + TGID_OFFSET; |
2320 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2488 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { |
2321 | put_task_struct(task); | 2489 | put_task_struct(task); |
@@ -2335,9 +2503,10 @@ out_no_task: | |||
2335 | static const struct pid_entry tid_base_stuff[] = { | 2503 | static const struct pid_entry tid_base_stuff[] = { |
2336 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2504 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2337 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2505 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), |
2338 | INF("environ", S_IRUSR, pid_environ), | 2506 | REG("environ", S_IRUSR, environ), |
2339 | INF("auxv", S_IRUSR, pid_auxv), | 2507 | INF("auxv", S_IRUSR, pid_auxv), |
2340 | INF("status", S_IRUGO, pid_status), | 2508 | INF("status", S_IRUGO, pid_status), |
2509 | INF("limits", S_IRUSR, pid_limits), | ||
2341 | #ifdef CONFIG_SCHED_DEBUG | 2510 | #ifdef CONFIG_SCHED_DEBUG |
2342 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), | 2511 | REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
2343 | #endif | 2512 | #endif |
@@ -2366,9 +2535,12 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2366 | #ifdef CONFIG_SCHEDSTATS | 2535 | #ifdef CONFIG_SCHEDSTATS |
2367 | INF("schedstat", S_IRUGO, pid_schedstat), | 2536 | INF("schedstat", S_IRUGO, pid_schedstat), |
2368 | #endif | 2537 | #endif |
2369 | #ifdef CONFIG_CPUSETS | 2538 | #ifdef CONFIG_PROC_PID_CPUSET |
2370 | REG("cpuset", S_IRUGO, cpuset), | 2539 | REG("cpuset", S_IRUGO, cpuset), |
2371 | #endif | 2540 | #endif |
2541 | #ifdef CONFIG_CGROUPS | ||
2542 | REG("cgroup", S_IRUGO, cgroup), | ||
2543 | #endif | ||
2372 | INF("oom_score", S_IRUGO, oom_score), | 2544 | INF("oom_score", S_IRUGO, oom_score), |
2373 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), | 2545 | REG("oom_adj", S_IRUGO|S_IWUSR, oom_adjust), |
2374 | #ifdef CONFIG_AUDITSYSCALL | 2546 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2436,6 +2608,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2436 | struct task_struct *task; | 2608 | struct task_struct *task; |
2437 | struct task_struct *leader = get_proc_task(dir); | 2609 | struct task_struct *leader = get_proc_task(dir); |
2438 | unsigned tid; | 2610 | unsigned tid; |
2611 | struct pid_namespace *ns; | ||
2439 | 2612 | ||
2440 | if (!leader) | 2613 | if (!leader) |
2441 | goto out_no_task; | 2614 | goto out_no_task; |
@@ -2444,14 +2617,15 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
2444 | if (tid == ~0U) | 2617 | if (tid == ~0U) |
2445 | goto out; | 2618 | goto out; |
2446 | 2619 | ||
2620 | ns = dentry->d_sb->s_fs_info; | ||
2447 | rcu_read_lock(); | 2621 | rcu_read_lock(); |
2448 | task = find_task_by_pid(tid); | 2622 | task = find_task_by_pid_ns(tid, ns); |
2449 | if (task) | 2623 | if (task) |
2450 | get_task_struct(task); | 2624 | get_task_struct(task); |
2451 | rcu_read_unlock(); | 2625 | rcu_read_unlock(); |
2452 | if (!task) | 2626 | if (!task) |
2453 | goto out; | 2627 | goto out; |
2454 | if (leader->tgid != task->tgid) | 2628 | if (!same_thread_group(leader, task)) |
2455 | goto out_drop_task; | 2629 | goto out_drop_task; |
2456 | 2630 | ||
2457 | result = proc_task_instantiate(dir, dentry, task, NULL); | 2631 | result = proc_task_instantiate(dir, dentry, task, NULL); |
@@ -2476,14 +2650,14 @@ out_no_task: | |||
2476 | * threads past it. | 2650 | * threads past it. |
2477 | */ | 2651 | */ |
2478 | static struct task_struct *first_tid(struct task_struct *leader, | 2652 | static struct task_struct *first_tid(struct task_struct *leader, |
2479 | int tid, int nr) | 2653 | int tid, int nr, struct pid_namespace *ns) |
2480 | { | 2654 | { |
2481 | struct task_struct *pos; | 2655 | struct task_struct *pos; |
2482 | 2656 | ||
2483 | rcu_read_lock(); | 2657 | rcu_read_lock(); |
2484 | /* Attempt to start with the pid of a thread */ | 2658 | /* Attempt to start with the pid of a thread */ |
2485 | if (tid && (nr > 0)) { | 2659 | if (tid && (nr > 0)) { |
2486 | pos = find_task_by_pid(tid); | 2660 | pos = find_task_by_pid_ns(tid, ns); |
2487 | if (pos && (pos->group_leader == leader)) | 2661 | if (pos && (pos->group_leader == leader)) |
2488 | goto found; | 2662 | goto found; |
2489 | } | 2663 | } |
@@ -2552,6 +2726,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2552 | ino_t ino; | 2726 | ino_t ino; |
2553 | int tid; | 2727 | int tid; |
2554 | 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; | ||
2555 | 2730 | ||
2556 | task = get_proc_task(inode); | 2731 | task = get_proc_task(inode); |
2557 | if (!task) | 2732 | if (!task) |
@@ -2585,16 +2760,17 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi | |||
2585 | /* 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 |
2586 | * return. lseek aka telldir automagically resets f_version to 0. | 2761 | * return. lseek aka telldir automagically resets f_version to 0. |
2587 | */ | 2762 | */ |
2588 | tid = filp->f_version; | 2763 | ns = filp->f_dentry->d_sb->s_fs_info; |
2764 | tid = (int)filp->f_version; | ||
2589 | filp->f_version = 0; | 2765 | filp->f_version = 0; |
2590 | for (task = first_tid(leader, tid, pos - 2); | 2766 | for (task = first_tid(leader, tid, pos - 2, ns); |
2591 | task; | 2767 | task; |
2592 | task = next_tid(task), pos++) { | 2768 | task = next_tid(task), pos++) { |
2593 | tid = task->pid; | 2769 | tid = task_pid_nr_ns(task, ns); |
2594 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { | 2770 | if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) { |
2595 | /* returning this tgid failed, save it as the first | 2771 | /* returning this tgid failed, save it as the first |
2596 | * pid for the next readir call */ | 2772 | * pid for the next readir call */ |
2597 | filp->f_version = tid; | 2773 | filp->f_version = (u64)tid; |
2598 | put_task_struct(task); | 2774 | put_task_struct(task); |
2599 | break; | 2775 | break; |
2600 | } | 2776 | } |