diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 202 |
1 files changed, 164 insertions, 38 deletions
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 */ |