Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e442a49 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Revert "proc: fix races against execve() of /proc/PID/fd**"



This reverts commit aa6afca5.

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: default avatarAlex Villacís Lasso <a_villacis@palosanto.com>
Requested-by: default avatarJames Morris <jmorris@namei.org>
Requested-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 19e0bafc
Loading
Loading
Loading
Loading
+43 −103
Original line number Diff line number Diff line
@@ -1652,46 +1652,12 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
	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 = {
	.readlink	= proc_pid_readlink,
	.follow_link	= proc_pid_follow_link,
	.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 */

@@ -1923,25 +1889,16 @@ static unsigned name_to_int(struct dentry *dentry)

static int proc_fd_info(struct inode *inode, struct path *path, char *info)
{
	struct task_struct *task;
	struct files_struct *files;
	struct task_struct *task = get_proc_task(inode);
	struct files_struct *files = NULL;
	struct file *file;
	int fd = proc_fd(inode);
	int rc;

	task = get_proc_task(inode);
	if (!task)
		return -ENOENT;

	rc = -EACCES;
	if (lock_trace(task))
		goto out_task;

	rc = -ENOENT;
	if (task) {
		files = get_files_struct(task);
	if (files == NULL)
		goto out_unlock;

		put_task_struct(task);
	}
	if (files) {
		/*
		 * We are not taking a ref to the file structure, so we must
		 * hold ->file_lock.
@@ -1967,17 +1924,14 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
					 "flags:\t0%o\n",
					 (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;
			return 0;
		}
		spin_unlock(&files->file_lock);
		put_files_struct(files);
	}
	return -ENOENT;
}

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);
	put_files_struct(files);

	inode->i_op = &proc_fd_link_inode_operations;
	inode->i_op = &proc_pid_link_inode_operations;
	inode->i_size = 64;
	ei->op.proc_get_link = proc_fd_link;
	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)
		goto out;

	result = ERR_PTR(-EACCES);
	if (lock_trace(task))
		goto out;

	result = instantiate(dir, dentry, task, &fd);
	unlock_trace(task);
out:
	put_task_struct(task);
out_no_task:
@@ -2129,28 +2078,23 @@ static int proc_readfd_common(struct file * filp, void * dirent,
	retval = -ENOENT;
	if (!p)
		goto out_no_task;

	retval = -EACCES;
	if (lock_trace(p))
		goto out;

	retval = 0;

	fd = filp->f_pos;
	switch (fd) {
		case 0:
			if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
				goto out_unlock;
				goto out;
			filp->f_pos++;
		case 1:
			ino = parent_ino(dentry);
			if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
				goto out_unlock;
				goto out;
			filp->f_pos++;
		default:
			files = get_files_struct(p);
			if (!files)
				goto out_unlock;
				goto out;
			rcu_read_lock();
			for (fd = filp->f_pos-2;
			     fd < files_fdtable(files)->max_fds;
@@ -2174,9 +2118,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
			rcu_read_unlock();
			put_files_struct(files);
	}

out_unlock:
	unlock_trace(p);
out:
	put_task_struct(p);
out_no_task:
@@ -2254,7 +2195,6 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
	ei->fd = fd;
	inode->i_mode = S_IFREG | S_IRUSR;
	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_add(dentry, inode);
	/* Close the race of the process dying before we return the dentry */