aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-09-25 08:51:50 -0400
committerPaul Mackerras <paulus@samba.org>2005-09-25 08:51:50 -0400
commite5baa396af7560382d2cf3f0871d616b61fc284c (patch)
tree6afc166894b8c8b3b2cf6add72a726be14ae2443 /fs/proc
parentd6a4c847e43c851cc0ddf73087a730227223f989 (diff)
parentef6bd6eb90ad72ee8ee7ba8b271f27102e9a90c1 (diff)
Merge from Linus' tree.
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c86
1 files changed, 79 insertions, 7 deletions
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