mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
Revert "proc: fix races against execve() of /proc/PID/fd**"
This reverts commit aa6afca5bc
.
It escalates of some of the google-chrome SELinux problems with ptrace
("Check failed: pid_ > 0. Did not find zygote process"), and Andrew
says that it is also causing mystery lockdep reports.
Reported-by: Alex Villacís Lasso <a_villacis@palosanto.com>
Requested-by: James Morris <jmorris@namei.org>
Requested-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
19e0bafc36
commit
5e442a493f
1 changed files with 41 additions and 101 deletions
142
fs/proc/base.c
142
fs/proc/base.c
|
@ -1652,46 +1652,12 @@ out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
|
||||||
struct kstat *stat)
|
|
||||||
{
|
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
struct task_struct *task = get_proc_task(inode);
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (task == NULL)
|
|
||||||
return -ESRCH;
|
|
||||||
|
|
||||||
rc = -EACCES;
|
|
||||||
if (lock_trace(task))
|
|
||||||
goto out_task;
|
|
||||||
|
|
||||||
generic_fillattr(inode, stat);
|
|
||||||
unlock_trace(task);
|
|
||||||
rc = 0;
|
|
||||||
out_task:
|
|
||||||
put_task_struct(task);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct inode_operations proc_pid_link_inode_operations = {
|
static const struct inode_operations proc_pid_link_inode_operations = {
|
||||||
.readlink = proc_pid_readlink,
|
.readlink = proc_pid_readlink,
|
||||||
.follow_link = proc_pid_follow_link,
|
.follow_link = proc_pid_follow_link,
|
||||||
.setattr = proc_setattr,
|
.setattr = proc_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct inode_operations proc_fdinfo_link_inode_operations = {
|
|
||||||
.setattr = proc_setattr,
|
|
||||||
.getattr = proc_pid_fd_link_getattr,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct inode_operations proc_fd_link_inode_operations = {
|
|
||||||
.readlink = proc_pid_readlink,
|
|
||||||
.follow_link = proc_pid_follow_link,
|
|
||||||
.setattr = proc_setattr,
|
|
||||||
.getattr = proc_pid_fd_link_getattr,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* building an inode */
|
/* building an inode */
|
||||||
|
|
||||||
|
@ -1923,61 +1889,49 @@ out:
|
||||||
|
|
||||||
static int proc_fd_info(struct inode *inode, struct path *path, char *info)
|
static int proc_fd_info(struct inode *inode, struct path *path, char *info)
|
||||||
{
|
{
|
||||||
struct task_struct *task;
|
struct task_struct *task = get_proc_task(inode);
|
||||||
struct files_struct *files;
|
struct files_struct *files = NULL;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int fd = proc_fd(inode);
|
int fd = proc_fd(inode);
|
||||||
int rc;
|
|
||||||
|
|
||||||
task = get_proc_task(inode);
|
if (task) {
|
||||||
if (!task)
|
files = get_files_struct(task);
|
||||||
return -ENOENT;
|
put_task_struct(task);
|
||||||
|
}
|
||||||
|
if (files) {
|
||||||
|
/*
|
||||||
|
* We are not taking a ref to the file structure, so we must
|
||||||
|
* hold ->file_lock.
|
||||||
|
*/
|
||||||
|
spin_lock(&files->file_lock);
|
||||||
|
file = fcheck_files(files, fd);
|
||||||
|
if (file) {
|
||||||
|
unsigned int f_flags;
|
||||||
|
struct fdtable *fdt;
|
||||||
|
|
||||||
rc = -EACCES;
|
fdt = files_fdtable(files);
|
||||||
if (lock_trace(task))
|
f_flags = file->f_flags & ~O_CLOEXEC;
|
||||||
goto out_task;
|
if (FD_ISSET(fd, fdt->close_on_exec))
|
||||||
|
f_flags |= O_CLOEXEC;
|
||||||
|
|
||||||
rc = -ENOENT;
|
if (path) {
|
||||||
files = get_files_struct(task);
|
*path = file->f_path;
|
||||||
if (files == NULL)
|
path_get(&file->f_path);
|
||||||
goto out_unlock;
|
}
|
||||||
|
if (info)
|
||||||
/*
|
snprintf(info, PROC_FDINFO_MAX,
|
||||||
* We are not taking a ref to the file structure, so we must
|
"pos:\t%lli\n"
|
||||||
* hold ->file_lock.
|
"flags:\t0%o\n",
|
||||||
*/
|
(long long) file->f_pos,
|
||||||
spin_lock(&files->file_lock);
|
f_flags);
|
||||||
file = fcheck_files(files, fd);
|
spin_unlock(&files->file_lock);
|
||||||
if (file) {
|
put_files_struct(files);
|
||||||
unsigned int f_flags;
|
return 0;
|
||||||
struct fdtable *fdt;
|
|
||||||
|
|
||||||
fdt = files_fdtable(files);
|
|
||||||
f_flags = file->f_flags & ~O_CLOEXEC;
|
|
||||||
if (FD_ISSET(fd, fdt->close_on_exec))
|
|
||||||
f_flags |= O_CLOEXEC;
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
*path = file->f_path;
|
|
||||||
path_get(&file->f_path);
|
|
||||||
}
|
}
|
||||||
if (info)
|
spin_unlock(&files->file_lock);
|
||||||
snprintf(info, PROC_FDINFO_MAX,
|
put_files_struct(files);
|
||||||
"pos:\t%lli\n"
|
}
|
||||||
"flags:\t0%o\n",
|
return -ENOENT;
|
||||||
(long long) file->f_pos,
|
|
||||||
f_flags);
|
|
||||||
rc = 0;
|
|
||||||
} else
|
|
||||||
rc = -ENOENT;
|
|
||||||
spin_unlock(&files->file_lock);
|
|
||||||
put_files_struct(files);
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
unlock_trace(task);
|
|
||||||
out_task:
|
|
||||||
put_task_struct(task);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_fd_link(struct inode *inode, struct path *path)
|
static int proc_fd_link(struct inode *inode, struct path *path)
|
||||||
|
@ -2072,7 +2026,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
put_files_struct(files);
|
put_files_struct(files);
|
||||||
|
|
||||||
inode->i_op = &proc_fd_link_inode_operations;
|
inode->i_op = &proc_pid_link_inode_operations;
|
||||||
inode->i_size = 64;
|
inode->i_size = 64;
|
||||||
ei->op.proc_get_link = proc_fd_link;
|
ei->op.proc_get_link = proc_fd_link;
|
||||||
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
||||||
|
@ -2104,12 +2058,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
|
||||||
if (fd == ~0U)
|
if (fd == ~0U)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
result = ERR_PTR(-EACCES);
|
|
||||||
if (lock_trace(task))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
result = instantiate(dir, dentry, task, &fd);
|
result = instantiate(dir, dentry, task, &fd);
|
||||||
unlock_trace(task);
|
|
||||||
out:
|
out:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
|
@ -2129,28 +2078,23 @@ static int proc_readfd_common(struct file * filp, void * dirent,
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
if (!p)
|
if (!p)
|
||||||
goto out_no_task;
|
goto out_no_task;
|
||||||
|
|
||||||
retval = -EACCES;
|
|
||||||
if (lock_trace(p))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
fd = filp->f_pos;
|
fd = filp->f_pos;
|
||||||
switch (fd) {
|
switch (fd) {
|
||||||
case 0:
|
case 0:
|
||||||
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
|
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
|
||||||
goto out_unlock;
|
goto out;
|
||||||
filp->f_pos++;
|
filp->f_pos++;
|
||||||
case 1:
|
case 1:
|
||||||
ino = parent_ino(dentry);
|
ino = parent_ino(dentry);
|
||||||
if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
|
if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
|
||||||
goto out_unlock;
|
goto out;
|
||||||
filp->f_pos++;
|
filp->f_pos++;
|
||||||
default:
|
default:
|
||||||
files = get_files_struct(p);
|
files = get_files_struct(p);
|
||||||
if (!files)
|
if (!files)
|
||||||
goto out_unlock;
|
goto out;
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for (fd = filp->f_pos-2;
|
for (fd = filp->f_pos-2;
|
||||||
fd < files_fdtable(files)->max_fds;
|
fd < files_fdtable(files)->max_fds;
|
||||||
|
@ -2174,9 +2118,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
put_files_struct(files);
|
put_files_struct(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
unlock_trace(p);
|
|
||||||
out:
|
out:
|
||||||
put_task_struct(p);
|
put_task_struct(p);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
|
@ -2254,7 +2195,6 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
|
||||||
ei->fd = fd;
|
ei->fd = fd;
|
||||||
inode->i_mode = S_IFREG | S_IRUSR;
|
inode->i_mode = S_IFREG | S_IRUSR;
|
||||||
inode->i_fop = &proc_fdinfo_file_operations;
|
inode->i_fop = &proc_fdinfo_file_operations;
|
||||||
inode->i_op = &proc_fdinfo_link_inode_operations;
|
|
||||||
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
d_set_d_op(dentry, &tid_fd_dentry_operations);
|
||||||
d_add(dentry, inode);
|
d_add(dentry, inode);
|
||||||
/* Close the race of the process dying before we return the dentry */
|
/* Close the race of the process dying before we return the dentry */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue