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

Commit 2b8143d6 authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Greg Kroah-Hartman
Browse files

mm: replace __access_remote_vm() write parameter with gup_flags



commit 442486ec1096781c50227b73f721a63974b0fdda upstream.

This removes the 'write' argument from __access_remote_vm() and replaces
it with 'gup_flags' as use of this function previously silently implied
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising
behaviour (and hence bugs) within the mm subsystem.

Signed-off-by: default avatarLorenzo Stoakes <lstoakes@gmail.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 4.4: adjust context]
Signed-off-by: default avatarBen Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8e50b8b0
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -3711,14 +3711,11 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
 * given task for page fault accounting.
 */
static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
		unsigned long addr, void *buf, int len, int write)
		unsigned long addr, void *buf, int len, unsigned int gup_flags)
{
	struct vm_area_struct *vma;
	void *old_buf = buf;
	unsigned int flags = FOLL_FORCE;

	if (write)
		flags |= FOLL_WRITE;
	int write = gup_flags & FOLL_WRITE;

	down_read(&mm->mmap_sem);
	/* ignore errors, just check how much was successfully transferred */
@@ -3728,7 +3725,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
		struct page *page = NULL;

		ret = get_user_pages(tsk, mm, addr, 1,
				flags, &page, &vma);
				gup_flags, &page, &vma);
		if (ret <= 0) {
#ifndef CONFIG_HAVE_IOREMAP_PROT
			break;
@@ -3787,7 +3784,12 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
int access_remote_vm(struct mm_struct *mm, unsigned long addr,
		void *buf, int len, int write)
{
	return __access_remote_vm(NULL, mm, addr, buf, len, write);
	unsigned int flags = FOLL_FORCE;

	if (write)
		flags |= FOLL_WRITE;

	return __access_remote_vm(NULL, mm, addr, buf, len, flags);
}

/*
@@ -3800,12 +3802,17 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,
{
	struct mm_struct *mm;
	int ret;
	unsigned int flags = FOLL_FORCE;

	mm = get_task_mm(tsk);
	if (!mm)
		return 0;

	ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
	if (write)
		flags |= FOLL_WRITE;

	ret = __access_remote_vm(tsk, mm, addr, buf, len, flags);

	mmput(mm);

	return ret;
+6 −3
Original line number Diff line number Diff line
@@ -1929,9 +1929,10 @@ void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf)
EXPORT_SYMBOL(filemap_map_pages);

static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
		unsigned long addr, void *buf, int len, int write)
		unsigned long addr, void *buf, int len, unsigned int gup_flags)
{
	struct vm_area_struct *vma;
	int write = gup_flags & FOLL_WRITE;

	down_read(&mm->mmap_sem);

@@ -1973,7 +1974,8 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
int access_remote_vm(struct mm_struct *mm, unsigned long addr,
		void *buf, int len, int write)
{
	return __access_remote_vm(NULL, mm, addr, buf, len, write);
	return __access_remote_vm(NULL, mm, addr, buf, len,
			write ? FOLL_WRITE : 0);
}

/*
@@ -1991,7 +1993,8 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
	if (!mm)
		return 0;

	len = __access_remote_vm(tsk, mm, addr, buf, len, write);
	len = __access_remote_vm(tsk, mm, addr, buf, len,
			write ? FOLL_WRITE : 0);

	mmput(mm);
	return len;