|
Lines 532-573
static int proc_oom_score(struct task_st
|
Link Here
|
|---|
|
/************************************************************************/ | /************************************************************************/ |
| |
/* permission checks */ | /* permission checks */ |
|
static int proc_fd_access_allowed(struct inode *inode) |
/* If the process being read is separated by chroot from the reading process, |
|
* don't let the reader access the threads. |
|
*/ |
|
static int proc_check_chroot(struct dentry *de, struct vfsmount *mnt) |
|
{ | { |
struct dentry *base; |
struct task_struct *task; |
struct vfsmount *our_vfsmnt; |
int allowed = 0; |
int res = 0; |
/* Allow access to a task's file descriptors if either we may |
|
* use ptrace attach to the process and find out that |
read_lock(¤t->fs->lock); |
* information, or if the task cannot possibly be ptraced |
our_vfsmnt = mntget(current->fs->rootmnt); |
* allow access if we have the proper capability. |
base = dget(current->fs->root); |
*/ |
read_unlock(¤t->fs->lock); |
task = get_proc_task(inode); |
|
if (task == current) |
spin_lock(&vfsmount_lock); |
allowed = 1; |
|
if (task && !allowed) { |
|
int alive; |
| |
while (mnt != our_vfsmnt) { |
task_lock(task); |
if (mnt == mnt->mnt_parent) |
alive = !!task->mm; |
goto out; |
task_unlock(task); |
de = mnt->mnt_mountpoint; |
if (alive) |
mnt = mnt->mnt_parent; |
/* For a living task obey ptrace_may_attach */ |
|
allowed = ptrace_may_attach(task); |
|
else |
|
/* For a special task simply check the capability */ |
|
allowed = capable(CAP_SYS_PTRACE); |
} | } |
|
if (task) |
if (!is_subdir(de, base)) |
put_task_struct(task); |
goto out; |
return allowed; |
spin_unlock(&vfsmount_lock); |
|
|
|
exit: |
|
dput(base); |
|
mntput(our_vfsmnt); |
|
return res; |
|
out: |
|
spin_unlock(&vfsmount_lock); |
|
res = -EACCES; |
|
goto exit; |
|
} | } |
| |
extern struct seq_operations mounts_op; | extern struct seq_operations mounts_op; |
|
Lines 1062-1113
static struct file_operations proc_secco
|
Link Here
|
|---|
|
}; | }; |
#endif /* CONFIG_SECCOMP */ | #endif /* CONFIG_SECCOMP */ |
| |
static int proc_check_dentry_visible(struct inode *inode, |
|
struct dentry *dentry, struct vfsmount *mnt) |
|
{ |
|
/* Verify that the current process can already see the |
|
* file pointed at by the file descriptor. |
|
* This prevents /proc from being an accidental information leak. |
|
* |
|
* This prevents access to files that are not visible do to |
|
* being on the otherside of a chroot, in a different |
|
* namespace, or are simply process local (like pipes). |
|
*/ |
|
struct task_struct *task; |
|
int error = -EACCES; |
|
|
|
/* See if the the two tasks share a commone set of |
|
* file descriptors. If so everything is visible. |
|
*/ |
|
rcu_read_lock(); |
|
task = tref_task(proc_tref(inode)); |
|
if (task) { |
|
struct files_struct *task_files, *files; |
|
/* This test answeres the question: |
|
* Is there a point in time since we looked up the |
|
* file descriptor where the two tasks share the |
|
* same files struct? |
|
*/ |
|
rmb(); |
|
files = current->files; |
|
task_files = task->files; |
|
if (files && (files == task_files)) |
|
error = 0; |
|
} |
|
rcu_read_unlock(); |
|
if (!error) |
|
goto out; |
|
|
|
/* If the two tasks don't share a common set of file |
|
* descriptors see if the destination dentry is already |
|
* visible in the current tasks filesystem namespace. |
|
*/ |
|
error = proc_check_chroot(dentry, mnt); |
|
out: |
|
return error; |
|
|
|
} |
|
|
|
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) |
{ | { |
struct inode *inode = dentry->d_inode; | struct inode *inode = dentry->d_inode; |
|
Lines 1116-1133
static void *proc_pid_follow_link(struct
|
Link Here
|
|---|
|
/* We don't need a base pointer in the /proc filesystem */ | /* We don't need a base pointer in the /proc filesystem */ |
path_release(nd); | path_release(nd); |
| |
if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) |
/* Are we allowed to snoop on the tasks file descriptors? */ |
|
if (!proc_fd_access_allowed(inode)) |
goto out; | goto out; |
| |
error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); | error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); |
nd->last_type = LAST_BIND; | nd->last_type = LAST_BIND; |
if (error) |
|
goto out; |
|
|
|
/* Only return files this task can already see */ |
|
error = proc_check_dentry_visible(inode, nd->dentry, nd->mnt); |
|
if (error) |
|
path_release(nd); |
|
out: | out: |
return ERR_PTR(error); | return ERR_PTR(error); |
} | } |
|
Lines 1165-1185
static int proc_pid_readlink(struct dent
|
Link Here
|
|---|
|
struct dentry *de; | struct dentry *de; |
struct vfsmount *mnt = NULL; | struct vfsmount *mnt = NULL; |
| |
|
/* Are we allowed to snoop on the tasks file descriptors? */ |
if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) |
if (!proc_fd_access_allowed(inode)) |
goto out; | goto out; |
| |
error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); | error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); |
if (error) | if (error) |
goto out; | goto out; |
| |
/* Only return files this task can already see */ |
|
error = proc_check_dentry_visible(inode, de, mnt); |
|
if (error) |
|
goto out_put; |
|
|
|
error = do_proc_readlink(de, mnt, buffer, buflen); | error = do_proc_readlink(de, mnt, buffer, buflen); |
out_put: |
|
dput(de); | dput(de); |
mntput(mnt); | mntput(mnt); |
out: | out: |