From 0438c468c45364ab1e0b4dc2bad792ee92e1df8f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Dec 2022 12:43:23 +0100 Subject: [PATCH] 5.4-stable patches added patches: v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch --- queue-5.4/series | 1 + ...low_pfn-if-pin_user_pages_fast-fails.patch | 114 ++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 queue-5.4/v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch diff --git a/queue-5.4/series b/queue-5.4/series index 720e7339838..7d31e7b3f1e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -153,3 +153,4 @@ mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch mmc-sdhci-fix-voltage-switch-delay.patch proc-avoid-integer-type-confusion-in-get_proc_long.patch proc-proc_skip_spaces-shouldn-t-think-it-is-working-on-c-strings.patch +v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch diff --git a/queue-5.4/v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch b/queue-5.4/v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch new file mode 100644 index 00000000000..6ae8e7d930e --- /dev/null +++ b/queue-5.4/v4l2-don-t-fall-back-to-follow_pfn-if-pin_user_pages_fast-fails.patch @@ -0,0 +1,114 @@ +From 6647e76ab623b2b3fb2efe03a86e9c9046c52c33 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 30 Nov 2022 16:10:52 -0800 +Subject: v4l2: don't fall back to follow_pfn() if pin_user_pages_fast() fails + +From: Linus Torvalds + +commit 6647e76ab623b2b3fb2efe03a86e9c9046c52c33 upstream. + +The V4L2_MEMORY_USERPTR interface is long deprecated and shouldn't be +used (and is discouraged for any modern v4l drivers). And Seth Jenkins +points out that the fallback to VM_PFNMAP/VM_IO is fundamentally racy +and dangerous. + +Note that it's not even a case that should trigger, since any normal +user pointer logic ends up just using the pin_user_pages_fast() call +that does the proper page reference counting. That's not the problem +case, only if you try to use special device mappings do you have any +issues. + +Normally I'd just remove this during the merge window, but since Seth +pointed out the problem cases, we really want to know as soon as +possible if there are actually any users of this odd special case of a +legacy interface. Neither Hans nor Mauro seem to think that such +mis-uses of the old legacy interface should exist. As Mauro says: + + "See, V4L2 has actually 4 streaming APIs: + - Kernel-allocated mmap (usually referred simply as just mmap); + - USERPTR mmap; + - read(); + - dmabuf; + + The USERPTR is one of the oldest way to use it, coming from V4L + version 1 times, and by far the least used one" + +And Hans chimed in on the USERPTR interface: + + "To be honest, I wouldn't mind if it goes away completely, but that's a + bit of a pipe dream right now" + +but while removing this legacy interface entirely may be a pipe dream we +can at least try to remove the unlikely (and actively broken) case of +using special device mappings for USERPTR accesses. + +This replaces it with a WARN_ONCE() that we can remove once we've +hopefully confirmed that no actual users exist. + +NOTE! Longer term, this means that a 'struct frame_vector' only ever +contains proper page pointers, and all the games we have with converting +them to pages can go away (grep for 'frame_vector_to_pages()' and the +uses of 'vec->is_pfns'). But this is just the first step, to verify +that this code really is all dead, and do so as quickly as possible. + +Reported-by: Seth Jenkins +Acked-by: Hans Verkuil +Acked-by: Mauro Carvalho Chehab +Cc: David Hildenbrand +Cc: Jan Kara +Signed-off-by: Linus Torvalds +Signed-off-by: Sergey Senozhatsky +Signed-off-by: Greg Kroah-Hartman +--- + mm/frame_vector.c | 31 ++++++------------------------- + 1 file changed, 6 insertions(+), 25 deletions(-) + +--- a/mm/frame_vector.c ++++ b/mm/frame_vector.c +@@ -37,7 +37,6 @@ int get_vaddr_frames(unsigned long start + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + int ret = 0; +- int err; + int locked; + + if (nr_frames == 0) +@@ -74,32 +73,14 @@ int get_vaddr_frames(unsigned long start + vec->is_pfns = false; + ret = get_user_pages_locked(start, nr_frames, + gup_flags, (struct page **)(vec->ptrs), &locked); +- goto out; ++ if (likely(ret > 0)) ++ goto out; + } + +- vec->got_ref = false; +- vec->is_pfns = true; +- do { +- unsigned long *nums = frame_vector_pfns(vec); +- +- while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) { +- err = follow_pfn(vma, start, &nums[ret]); +- if (err) { +- if (ret == 0) +- ret = err; +- goto out; +- } +- start += PAGE_SIZE; +- ret++; +- } +- /* +- * We stop if we have enough pages or if VMA doesn't completely +- * cover the tail page. +- */ +- if (ret >= nr_frames || start < vma->vm_end) +- break; +- vma = find_vma_intersection(mm, start, start + 1); +- } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP)); ++ /* This used to (racily) return non-refcounted pfns. Let people know */ ++ WARN_ONCE(1, "get_vaddr_frames() cannot follow VM_IO mapping"); ++ vec->nr_frames = 0; ++ + out: + if (locked) + up_read(&mm->mmap_sem); -- 2.47.3