aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c3
-rw-r--r--fs/proc/base.c98
-rw-r--r--fs/proc/nommu.c1
3 files changed, 95 insertions, 7 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d88d518d30f..d84eecacbea 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -74,6 +74,7 @@
74#include <linux/file.h> 74#include <linux/file.h>
75#include <linux/times.h> 75#include <linux/times.h>
76#include <linux/cpuset.h> 76#include <linux/cpuset.h>
77#include <linux/rcupdate.h>
77 78
78#include <asm/uaccess.h> 79#include <asm/uaccess.h>
79#include <asm/pgtable.h> 80#include <asm/pgtable.h>
@@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer)
180 p->gid, p->egid, p->sgid, p->fsgid); 181 p->gid, p->egid, p->sgid, p->fsgid);
181 read_unlock(&tasklist_lock); 182 read_unlock(&tasklist_lock);
182 task_lock(p); 183 task_lock(p);
184 rcu_read_lock();
183 if (p->files) 185 if (p->files)
184 fdt = files_fdtable(p->files); 186 fdt = files_fdtable(p->files);
185 buffer += sprintf(buffer, 187 buffer += sprintf(buffer,
186 "FDSize:\t%d\n" 188 "FDSize:\t%d\n"
187 "Groups:\t", 189 "Groups:\t",
188 fdt ? fdt->max_fds : 0); 190 fdt ? fdt->max_fds : 0);
191 rcu_read_unlock();
189 192
190 group_info = p->group_info; 193 group_info = p->group_info;
191 get_group_info(group_info); 194 get_group_info(group_info);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 23db452ab42..a170450aadb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -103,7 +103,9 @@ enum pid_directory_inos {
103 PROC_TGID_NUMA_MAPS, 103 PROC_TGID_NUMA_MAPS,
104 PROC_TGID_MOUNTS, 104 PROC_TGID_MOUNTS,
105 PROC_TGID_WCHAN, 105 PROC_TGID_WCHAN,
106#ifdef CONFIG_MMU
106 PROC_TGID_SMAPS, 107 PROC_TGID_SMAPS,
108#endif
107#ifdef CONFIG_SCHEDSTATS 109#ifdef CONFIG_SCHEDSTATS
108 PROC_TGID_SCHEDSTAT, 110 PROC_TGID_SCHEDSTAT,
109#endif 111#endif
@@ -141,7 +143,9 @@ enum pid_directory_inos {
141 PROC_TID_NUMA_MAPS, 143 PROC_TID_NUMA_MAPS,
142 PROC_TID_MOUNTS, 144 PROC_TID_MOUNTS,
143 PROC_TID_WCHAN, 145 PROC_TID_WCHAN,
146#ifdef CONFIG_MMU
144 PROC_TID_SMAPS, 147 PROC_TID_SMAPS,
148#endif
145#ifdef CONFIG_SCHEDSTATS 149#ifdef CONFIG_SCHEDSTATS
146 PROC_TID_SCHEDSTAT, 150 PROC_TID_SCHEDSTAT,
147#endif 151#endif
@@ -195,7 +199,9 @@ static struct pid_entry tgid_base_stuff[] = {
195 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), 199 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
196 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), 200 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
197 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 201 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
202#ifdef CONFIG_MMU
198 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), 203 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
204#endif
199#ifdef CONFIG_SECURITY 205#ifdef CONFIG_SECURITY
200 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 206 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
201#endif 207#endif
@@ -235,7 +241,9 @@ static struct pid_entry tid_base_stuff[] = {
235 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), 241 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
236 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), 242 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
237 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 243 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
244#ifdef CONFIG_MMU
238 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), 245 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
246#endif
239#ifdef CONFIG_SECURITY 247#ifdef CONFIG_SECURITY
240 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 248 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
241#endif 249#endif
@@ -340,6 +348,54 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
340 return result; 348 return result;
341} 349}
342 350
351
352/* Same as proc_root_link, but this addionally tries to get fs from other
353 * threads in the group */
354static int proc_task_root_link(struct inode *inode, struct dentry **dentry,
355 struct vfsmount **mnt)
356{
357 struct fs_struct *fs;
358 int result = -ENOENT;
359 struct task_struct *leader = proc_task(inode);
360
361 task_lock(leader);
362 fs = leader->fs;
363 if (fs) {
364 atomic_inc(&fs->count);
365 task_unlock(leader);
366 } else {
367 /* Try to get fs from other threads */
368 task_unlock(leader);
369 read_lock(&tasklist_lock);
370 if (pid_alive(leader)) {
371 struct task_struct *task = leader;
372
373 while ((task = next_thread(task)) != leader) {
374 task_lock(task);
375 fs = task->fs;
376 if (fs) {
377 atomic_inc(&fs->count);
378 task_unlock(task);
379 break;
380 }
381 task_unlock(task);
382 }
383 }
384 read_unlock(&tasklist_lock);
385 }
386
387 if (fs) {
388 read_lock(&fs->lock);
389 *mnt = mntget(fs->rootmnt);
390 *dentry = dget(fs->root);
391 read_unlock(&fs->lock);
392 result = 0;
393 put_fs_struct(fs);
394 }
395 return result;
396}
397
398
343#define MAY_PTRACE(task) \ 399#define MAY_PTRACE(task) \
344 (task == current || \ 400 (task == current || \
345 (task->parent == current && \ 401 (task->parent == current && \
@@ -471,14 +527,14 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
471 527
472/* permission checks */ 528/* permission checks */
473 529
474static int proc_check_root(struct inode *inode) 530/* If the process being read is separated by chroot from the reading process,
531 * don't let the reader access the threads.
532 */
533static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
475{ 534{
476 struct dentry *de, *base, *root; 535 struct dentry *de, *base;
477 struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; 536 struct vfsmount *our_vfsmnt, *mnt;
478 int res = 0; 537 int res = 0;
479
480 if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
481 return -ENOENT;
482 read_lock(&current->fs->lock); 538 read_lock(&current->fs->lock);
483 our_vfsmnt = mntget(current->fs->rootmnt); 539 our_vfsmnt = mntget(current->fs->rootmnt);
484 base = dget(current->fs->root); 540 base = dget(current->fs->root);
@@ -511,6 +567,16 @@ out:
511 goto exit; 567 goto exit;
512} 568}
513 569
570static int proc_check_root(struct inode *inode)
571{
572 struct dentry *root;
573 struct vfsmount *vfsmnt;
574
575 if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
576 return -ENOENT;
577 return proc_check_chroot(root, vfsmnt);
578}
579
514static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) 580static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
515{ 581{
516 if (generic_permission(inode, mask, NULL) != 0) 582 if (generic_permission(inode, mask, NULL) != 0)
@@ -518,6 +584,20 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
518 return proc_check_root(inode); 584 return proc_check_root(inode);
519} 585}
520 586
587static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
588{
589 struct dentry *root;
590 struct vfsmount *vfsmnt;
591
592 if (generic_permission(inode, mask, NULL) != 0)
593 return -EACCES;
594
595 if (proc_task_root_link(inode, &root, &vfsmnt))
596 return -ENOENT;
597
598 return proc_check_chroot(root, vfsmnt);
599}
600
521extern struct seq_operations proc_pid_maps_op; 601extern struct seq_operations proc_pid_maps_op;
522static int maps_open(struct inode *inode, struct file *file) 602static int maps_open(struct inode *inode, struct file *file)
523{ 603{
@@ -558,6 +638,7 @@ static struct file_operations proc_numa_maps_operations = {
558}; 638};
559#endif 639#endif
560 640
641#ifdef CONFIG_MMU
561extern struct seq_operations proc_pid_smaps_op; 642extern struct seq_operations proc_pid_smaps_op;
562static int smaps_open(struct inode *inode, struct file *file) 643static int smaps_open(struct inode *inode, struct file *file)
563{ 644{
@@ -576,6 +657,7 @@ static struct file_operations proc_smaps_operations = {
576 .llseek = seq_lseek, 657 .llseek = seq_lseek,
577 .release = seq_release, 658 .release = seq_release,
578}; 659};
660#endif
579 661
580extern struct seq_operations mounts_op; 662extern struct seq_operations mounts_op;
581static int mounts_open(struct inode *inode, struct file *file) 663static int mounts_open(struct inode *inode, struct file *file)
@@ -1419,7 +1501,7 @@ static struct inode_operations proc_fd_inode_operations = {
1419 1501
1420static struct inode_operations proc_task_inode_operations = { 1502static struct inode_operations proc_task_inode_operations = {
1421 .lookup = proc_task_lookup, 1503 .lookup = proc_task_lookup,
1422 .permission = proc_permission, 1504 .permission = proc_task_permission,
1423}; 1505};
1424 1506
1425#ifdef CONFIG_SECURITY 1507#ifdef CONFIG_SECURITY
@@ -1609,10 +1691,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1609 case PROC_TGID_MOUNTS: 1691 case PROC_TGID_MOUNTS:
1610 inode->i_fop = &proc_mounts_operations; 1692 inode->i_fop = &proc_mounts_operations;
1611 break; 1693 break;
1694#ifdef CONFIG_MMU
1612 case PROC_TID_SMAPS: 1695 case PROC_TID_SMAPS:
1613 case PROC_TGID_SMAPS: 1696 case PROC_TGID_SMAPS:
1614 inode->i_fop = &proc_smaps_operations; 1697 inode->i_fop = &proc_smaps_operations;
1615 break; 1698 break;
1699#endif
1616#ifdef CONFIG_SECURITY 1700#ifdef CONFIG_SECURITY
1617 case PROC_TID_ATTR: 1701 case PROC_TID_ATTR:
1618 inode->i_nlink = 2; 1702 inode->i_nlink = 2;
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index f3bf016d5ee..cff10ab1af6 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -91,6 +91,7 @@ static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos)
91 next = _rb; 91 next = _rb;
92 break; 92 break;
93 } 93 }
94 pos--;
94 } 95 }
95 96
96 return next; 97 return next;