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

Commit 6ecdcbcd authored by Konstantin Khlebnikov's avatar Konstantin Khlebnikov Committed by Greg Kroah-Hartman
Browse files

proc: use down_read_killable mmap_sem for /proc/pid/map_files

[ Upstream commit cd9e2bb8271c971d9f37c722be2616c7f8ba0664 ]

Do not remain stuck forever if something goes wrong.  Using a killable
lock permits cleanup of stuck tasks and simplifies investigation.

It seems ->d_revalidate() could return any error (except ECHILD) to abort
validation and pass error as result of lookup sequence.

[akpm@linux-foundation.org: fix proc_map_files_lookup() return value, per Andrei]
Link: http://lkml.kernel.org/r/156007493995.3335.9595044802115356911.stgit@buzz


Signed-off-by: default avatarKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Reviewed-by: default avatarRoman Gushchin <guro@fb.com>
Reviewed-by: default avatarCyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: default avatarKirill Tkhai <ktkhai@virtuozzo.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Michal Koutný <mkoutny@suse.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 3d617da8
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -1960,10 +1960,13 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
		goto out;

	if (!dname_to_vma_addr(dentry, &vm_start, &vm_end)) {
		down_read(&mm->mmap_sem);
		exact_vma_exists = !!find_exact_vma(mm, vm_start, vm_end);
		status = down_read_killable(&mm->mmap_sem);
		if (!status) {
			exact_vma_exists = !!find_exact_vma(mm, vm_start,
							    vm_end);
			up_read(&mm->mmap_sem);
		}
	}

	mmput(mm);

@@ -2008,8 +2011,11 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
	if (rc)
		goto out_mmput;

	rc = down_read_killable(&mm->mmap_sem);
	if (rc)
		goto out_mmput;

	rc = -ENOENT;
	down_read(&mm->mmap_sem);
	vma = find_exact_vma(mm, vm_start, vm_end);
	if (vma && vma->vm_file) {
		*path = vma->vm_file->f_path;
@@ -2105,7 +2111,11 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
	if (!mm)
		goto out_put_task;

	down_read(&mm->mmap_sem);
	result = ERR_PTR(-EINTR);
	if (down_read_killable(&mm->mmap_sem))
		goto out_put_mm;

	result = ERR_PTR(-ENOENT);
	vma = find_exact_vma(mm, vm_start, vm_end);
	if (!vma)
		goto out_no_vma;
@@ -2116,6 +2126,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,

out_no_vma:
	up_read(&mm->mmap_sem);
out_put_mm:
	mmput(mm);
out_put_task:
	put_task_struct(task);
@@ -2157,7 +2168,12 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
	mm = get_task_mm(task);
	if (!mm)
		goto out_put_task;
	down_read(&mm->mmap_sem);

	ret = down_read_killable(&mm->mmap_sem);
	if (ret) {
		mmput(mm);
		goto out_put_task;
	}

	nr_files = 0;