From: David Hildenbrand <david@redhat.com>
To: Pasha Tatashin <pasha.tatashin@soleen.com>,
Ruihan Li <lrh2000@pku.edu.cn>
Cc: syzbot+fcf1a817ceb50935ce99@syzkaller.appspotmail.com,
akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, gregkh@linuxfoundation.org,
linux-usb@vger.kernel.org, syzkaller-bugs@googlegroups.com,
Matthew Wilcox <willy@infradead.org>,
Lorenzo Stoakes <lstoakes@gmail.com>,
Vlastimil Babka <vbabka@suse.cz>
Subject: Re: usbdev_mmap causes type confusion in page_table_check
Date: Mon, 8 May 2023 23:37:03 +0200 [thread overview]
Message-ID: <8019cf35-e631-0252-0d38-d2454f5f0e11@redhat.com> (raw)
In-Reply-To: <CA+CK2bBe2YKYM3rUTCnZ0RF=NFUR9VqO-QYn3ygPsFJWLY1MUA@mail.gmail.com>
On 08.05.23 23:27, Pasha Tatashin wrote:
> On Sun, May 7, 2023 at 9:58 AM Ruihan Li <lrh2000@pku.edu.cn> wrote:
>>
>> Hi all,
>
> Hi Ruihan,
>
> Thank you for bisecting, and great analysis of the problem.
>
>> Recently, syzbot reported [1] ("kernel BUG in page_table_check_clear"). After
>> some bisection, I found out that when usbdev_mmap calls remap_pfn_range on
>> kmalloc'ed memory, it causes type confusion between struct folio and slab in
>> page_table_check. As I will explain below, it seems that both usb-side and
>> mm-side need some fixes. So I have cc'd linux-usb and linux-mm here, as well
>> as their maintainers, to see whether there are any comments on the proposed
>> way to fix.
>>
>> [1] https://lore.kernel.org/all/000000000000258e5e05fae79fc1@google.com/
>>
>> To handle mmap requests for /dev/bus/usb/XXX/YYY, usbdev_mmap first allocates
>> memory by calling usb_alloc_coherent and then maps it into the user space
>> using remap_pfn_range:
>>
>> static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
>> {
>> // ...
>> mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN,
>> &dma_handle);
>> // ...
>> if (hcd->localmem_pool || !hcd_uses_dma(hcd)) {
>> if (remap_pfn_range(vma, vma->vm_start,
>> virt_to_phys(usbm->mem) >> PAGE_SHIFT,
>> size, vma->vm_page_prot) < 0) {
>> // ...
>> }
>> }
>> // ...
>> }
>>
>> Note that in this case, we consider the DMA-unavailable scenario, which, to be
>> honest, is rare in practice. However, syzbot emulates USB devices using a
>> module named dummy_hcd, and since these devices are emulated, DMA is not
>> available at all.
>>
>> Meanwhile, usb_alloc_coherent calls hcd_buffer_alloc, which uses kmalloc for
>> memory allocation:
>>
>> void *hcd_buffer_alloc(
>> struct usb_bus *bus,
>> size_t size,
>> gfp_t mem_flags,
>> dma_addr_t *dma
>> )
>> {
>> // ...
>> if (!hcd_uses_dma(hcd)) {
>> *dma = ~(dma_addr_t) 0;
>> return kmalloc(size, mem_flags);
>> }
>> // ...
>> }
>>
>> However, during the update of the page table to map the kmalloc'd page into
>> the user space, page_table_check_set attempts to determine whether the page is
>> anonymous using PageAnon:
>>
>> static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
>> unsigned long pfn, unsigned long pgcnt,
>> bool rw)
>> {
>> // ...
>> anon = PageAnon(page);
>> for (i = 0; i < pgcnt; i++) {
>> // ...
>> if (anon) {
>> BUG_ON(atomic_read(&ptc->file_map_count));
>> BUG_ON(atomic_inc_return(&ptc->anon_map_count) > 1 && rw);
>> } else {
>> BUG_ON(atomic_read(&ptc->anon_map_count));
>> BUG_ON(atomic_inc_return(&ptc->file_map_count) < 0);
>> }
>> // ...
>> }
>> // ...
>> }
>>
>> This call to PageAnon is invalid for slab pages because slab reuses the bits
>> in struct page/folio to store its internal states, and the anonymity bit only
>> exists in struct page/folio. As a result, the counters are incorrectly updated
>> and checked in page_table_check_set and page_table_check_clear, leading to the
>> bug being raised.
>
> We should change anon boolean to be:
>
> anon = !PageSlab(page) && PageAnon(page);
>
> This way, we will have a correct way to determine anon pages, and the
> rest will fall into file_map_count. The file (non-anon) PTEs are OK to
> be double mapped, so there won't be any problems from page_table_check
> point of view even if it is a slab page.
I'm surprised that we allow mapping slab pages to user space. I somehow
remember that this is a big no-no.
Do we really want to allow that? Are there many such users or is this
the only one?
If we do support it, we might want to update some PageAnon() checks in
mm/gup.c too to exclude slab pages ...
--
Thanks,
David / dhildenb
next prev parent reply other threads:[~2023-05-08 21:37 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-05 0:46 [syzbot] [mm?] kernel BUG in page_table_check_clear syzbot
2023-05-07 13:58 ` usbdev_mmap causes type confusion in page_table_check Ruihan Li
2023-05-08 21:27 ` Pasha Tatashin
2023-05-08 21:36 ` Matthew Wilcox
2023-05-08 21:48 ` Pasha Tatashin
2023-05-08 21:52 ` Matthew Wilcox
2023-05-08 21:55 ` Pasha Tatashin
2023-05-08 22:46 ` David Hildenbrand
2023-05-08 23:17 ` Pasha Tatashin
2023-05-08 23:21 ` Pasha Tatashin
2023-05-08 23:37 ` David Hildenbrand
2023-05-09 0:07 ` Pasha Tatashin
2023-05-08 21:37 ` David Hildenbrand [this message]
2023-05-09 13:25 ` Christoph Hellwig
2023-05-09 14:01 ` Greg KH
2023-05-10 13:17 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8019cf35-e631-0252-0d38-d2454f5f0e11@redhat.com \
--to=david@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-usb@vger.kernel.org \
--cc=lrh2000@pku.edu.cn \
--cc=lstoakes@gmail.com \
--cc=pasha.tatashin@soleen.com \
--cc=syzbot+fcf1a817ceb50935ce99@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
--cc=vbabka@suse.cz \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox