aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-10-06 05:51:07 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-06 05:51:07 -0400
commit012e060c95e547eceea4a12c6f58592473bf4011 (patch)
treeb57d3eafb50ce517577d2cf366c9ef0b4b286589 /fs/proc
parent923f122573851d18a3832ca808269fa2d5046fb1 (diff)
parented39f731ab2e77e58122232f6e27333331d7793d (diff)
Merge branch 'master'
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c3
-rw-r--r--fs/proc/base.c86
2 files changed, 82 insertions, 7 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d88d518d30f6..d84eecacbeaf 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 23db452ab428..3b33f94020db 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -340,6 +340,54 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
340 return result; 340 return result;
341} 341}
342 342
343
344/* Same as proc_root_link, but this addionally tries to get fs from other
345 * threads in the group */
346static int proc_task_root_link(struct inode *inode, struct dentry **dentry,
347 struct vfsmount **mnt)
348{
349 struct fs_struct *fs;
350 int result = -ENOENT;
351 struct task_struct *leader = proc_task(inode);
352
353 task_lock(leader);
354 fs = leader->fs;
355 if (fs) {
356 atomic_inc(&fs->count);
357 task_unlock(leader);
358 } else {
359 /* Try to get fs from other threads */
360 task_unlock(leader);
361 read_lock(&tasklist_lock);
362 if (pid_alive(leader)) {
363 struct task_struct *task = leader;
364
365 while ((task = next_thread(task)) != leader) {
366 task_lock(task);
367 fs = task->fs;
368 if (fs) {
369 atomic_inc(&fs->count);
370 task_unlock(task);
371 break;
372 }
373 task_unlock(task);
374 }
375 }
376 read_unlock(&tasklist_lock);
377 }
378
379 if (fs) {
380 read_lock(&fs->lock);
381 *mnt = mntget(fs->rootmnt);
382 *dentry = dget(fs->root);
383 read_unlock(&fs->lock);
384 result = 0;
385 put_fs_struct(fs);
386 }
387 return result;
388}
389
390
343#define MAY_PTRACE(task) \ 391#define MAY_PTRACE(task) \
344 (task == current || \ 392 (task == current || \
345 (task->parent == current && \ 393 (task->parent == current && \
@@ -471,14 +519,14 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
471 519
472/* permission checks */ 520/* permission checks */
473 521
474static int proc_check_root(struct inode *inode) 522/* If the process being read is separated by chroot from the reading process,
523 * don't let the reader access the threads.
524 */
525static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
475{ 526{
476 struct dentry *de, *base, *root; 527 struct dentry *de, *base;
477 struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; 528 struct vfsmount *our_vfsmnt, *mnt;
478 int res = 0; 529 int res = 0;
479
480 if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
481 return -ENOENT;
482 read_lock(&current->fs->lock); 530 read_lock(&current->fs->lock);
483 our_vfsmnt = mntget(current->fs->rootmnt); 531 our_vfsmnt = mntget(current->fs->rootmnt);
484 base = dget(current->fs->root); 532 base = dget(current->fs->root);
@@ -511,6 +559,16 @@ out:
511 goto exit; 559 goto exit;
512} 560}
513 561
562static int proc_check_root(struct inode *inode)
563{
564 struct dentry *root;
565 struct vfsmount *vfsmnt;
566
567 if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
568 return -ENOENT;
569 return proc_check_chroot(root, vfsmnt);
570}
571
514static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) 572static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
515{ 573{
516 if (generic_permission(inode, mask, NULL) != 0) 574 if (generic_permission(inode, mask, NULL) != 0)
@@ -518,6 +576,20 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
518 return proc_check_root(inode); 576 return proc_check_root(inode);
519} 577}
520 578
579static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
580{
581 struct dentry *root;
582 struct vfsmount *vfsmnt;
583
584 if (generic_permission(inode, mask, NULL) != 0)
585 return -EACCES;
586
587 if (proc_task_root_link(inode, &root, &vfsmnt))
588 return -ENOENT;
589
590 return proc_check_chroot(root, vfsmnt);
591}
592
521extern struct seq_operations proc_pid_maps_op; 593extern struct seq_operations proc_pid_maps_op;
522static int maps_open(struct inode *inode, struct file *file) 594static int maps_open(struct inode *inode, struct file *file)
523{ 595{
@@ -1419,7 +1491,7 @@ static struct inode_operations proc_fd_inode_operations = {
1419 1491
1420static struct inode_operations proc_task_inode_operations = { 1492static struct inode_operations proc_task_inode_operations = {
1421 .lookup = proc_task_lookup, 1493 .lookup = proc_task_lookup,
1422 .permission = proc_permission, 1494 .permission = proc_task_permission,
1423}; 1495};
1424 1496
1425#ifdef CONFIG_SECURITY 1497#ifdef CONFIG_SECURITY