aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c124
1 files changed, 29 insertions, 95 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index f0db7f616ac3..f38da6bda269 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -532,42 +532,34 @@ static int proc_oom_score(struct task_struct *task, char *buffer)
532/************************************************************************/ 532/************************************************************************/
533 533
534/* permission checks */ 534/* permission checks */
535 535static int proc_fd_access_allowed(struct inode *inode)
536/* If the process being read is separated by chroot from the reading process,
537 * don't let the reader access the threads.
538 */
539static int proc_check_chroot(struct dentry *de, struct vfsmount *mnt)
540{ 536{
541 struct dentry *base; 537 struct task_struct *task;
542 struct vfsmount *our_vfsmnt; 538 int allowed = 0;
543 int res = 0; 539 /* Allow access to a task's file descriptors if either we may
544 540 * use ptrace attach to the process and find out that
545 read_lock(&current->fs->lock); 541 * information, or if the task cannot possibly be ptraced
546 our_vfsmnt = mntget(current->fs->rootmnt); 542 * allow access if we have the proper capability.
547 base = dget(current->fs->root); 543 */
548 read_unlock(&current->fs->lock); 544 task = get_proc_task(inode);
549 545 if (task == current)
550 spin_lock(&vfsmount_lock); 546 allowed = 1;
547 if (task && !allowed) {
548 int alive;
551 549
552 while (mnt != our_vfsmnt) { 550 task_lock(task);
553 if (mnt == mnt->mnt_parent) 551 alive = !!task->mm;
554 goto out; 552 task_unlock(task);
555 de = mnt->mnt_mountpoint; 553 if (alive)
556 mnt = mnt->mnt_parent; 554 /* For a living task obey ptrace_may_attach */
555 allowed = ptrace_may_attach(task);
556 else
557 /* For a special task simply check the capability */
558 allowed = capable(CAP_SYS_PTRACE);
557 } 559 }
558 560 if (task)
559 if (!is_subdir(de, base)) 561 put_task_struct(task);
560 goto out; 562 return allowed;
561 spin_unlock(&vfsmount_lock);
562
563exit:
564 dput(base);
565 mntput(our_vfsmnt);
566 return res;
567out:
568 spin_unlock(&vfsmount_lock);
569 res = -EACCES;
570 goto exit;
571} 563}
572 564
573extern struct seq_operations mounts_op; 565extern struct seq_operations mounts_op;
@@ -1062,52 +1054,6 @@ static struct file_operations proc_seccomp_operations = {
1062}; 1054};
1063#endif /* CONFIG_SECCOMP */ 1055#endif /* CONFIG_SECCOMP */
1064 1056
1065static int proc_check_dentry_visible(struct inode *inode,
1066 struct dentry *dentry, struct vfsmount *mnt)
1067{
1068 /* Verify that the current process can already see the
1069 * file pointed at by the file descriptor.
1070 * This prevents /proc from being an accidental information leak.
1071 *
1072 * This prevents access to files that are not visible do to
1073 * being on the otherside of a chroot, in a different
1074 * namespace, or are simply process local (like pipes).
1075 */
1076 struct task_struct *task;
1077 int error = -EACCES;
1078
1079 /* See if the the two tasks share a commone set of
1080 * file descriptors. If so everything is visible.
1081 */
1082 rcu_read_lock();
1083 task = tref_task(proc_tref(inode));
1084 if (task) {
1085 struct files_struct *task_files, *files;
1086 /* This test answeres the question:
1087 * Is there a point in time since we looked up the
1088 * file descriptor where the two tasks share the
1089 * same files struct?
1090 */
1091 rmb();
1092 files = current->files;
1093 task_files = task->files;
1094 if (files && (files == task_files))
1095 error = 0;
1096 }
1097 rcu_read_unlock();
1098 if (!error)
1099 goto out;
1100
1101 /* If the two tasks don't share a common set of file
1102 * descriptors see if the destination dentry is already
1103 * visible in the current tasks filesystem namespace.
1104 */
1105 error = proc_check_chroot(dentry, mnt);
1106out:
1107 return error;
1108
1109}
1110
1111static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 1057static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1112{ 1058{
1113 struct inode *inode = dentry->d_inode; 1059 struct inode *inode = dentry->d_inode;
@@ -1116,18 +1062,12 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1116 /* We don't need a base pointer in the /proc filesystem */ 1062 /* We don't need a base pointer in the /proc filesystem */
1117 path_release(nd); 1063 path_release(nd);
1118 1064
1119 if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) 1065 /* Are we allowed to snoop on the tasks file descriptors? */
1066 if (!proc_fd_access_allowed(inode))
1120 goto out; 1067 goto out;
1121 1068
1122 error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); 1069 error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
1123 nd->last_type = LAST_BIND; 1070 nd->last_type = LAST_BIND;
1124 if (error)
1125 goto out;
1126
1127 /* Only return files this task can already see */
1128 error = proc_check_dentry_visible(inode, nd->dentry, nd->mnt);
1129 if (error)
1130 path_release(nd);
1131out: 1071out:
1132 return ERR_PTR(error); 1072 return ERR_PTR(error);
1133} 1073}
@@ -1165,21 +1105,15 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
1165 struct dentry *de; 1105 struct dentry *de;
1166 struct vfsmount *mnt = NULL; 1106 struct vfsmount *mnt = NULL;
1167 1107
1168 1108 /* Are we allowed to snoop on the tasks file descriptors? */
1169 if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) 1109 if (!proc_fd_access_allowed(inode))
1170 goto out; 1110 goto out;
1171 1111
1172 error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); 1112 error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt);
1173 if (error) 1113 if (error)
1174 goto out; 1114 goto out;
1175 1115
1176 /* Only return files this task can already see */
1177 error = proc_check_dentry_visible(inode, de, mnt);
1178 if (error)
1179 goto out_put;
1180
1181 error = do_proc_readlink(de, mnt, buffer, buflen); 1116 error = do_proc_readlink(de, mnt, buffer, buflen);
1182out_put:
1183 dput(de); 1117 dput(de);
1184 mntput(mnt); 1118 mntput(mnt);
1185out: 1119out: