]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
usercopy: Remove folio references from check_heap_object()
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 13 Nov 2025 00:09:27 +0000 (00:09 +0000)
committerVlastimil Babka <vbabka@suse.cz>
Thu, 13 Nov 2025 10:01:08 +0000 (11:01 +0100)
Use page_slab() instead of virt_to_folio() followed by folio_slab().
We do end up calling compound_head() twice for non-slab copies, but that
will not be a problem once we allocate memdescs separately.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Kees Cook <kees@kernel.org>
Cc: Gustavo A. R. Silva <gustavoars@kernel.org>
Cc: linux-hardening@vger.kernel.org
Link: https://patch.msgid.link/20251113000932.1589073-14-willy@infradead.org
Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
mm/usercopy.c

index dbdcc43964fb1ca97842f1dbc9cf587adcb121c3..5de7a518b1b1c2b13c65ba1683509ab46ad0bdac 100644 (file)
@@ -164,7 +164,8 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
 {
        unsigned long addr = (unsigned long)ptr;
        unsigned long offset;
-       struct folio *folio;
+       struct page *page;
+       struct slab *slab;
 
        if (is_kmap_addr(ptr)) {
                offset = offset_in_page(ptr);
@@ -189,16 +190,23 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
        if (!virt_addr_valid(ptr))
                return;
 
-       folio = virt_to_folio(ptr);
-
-       if (folio_test_slab(folio)) {
+       page = virt_to_page(ptr);
+       slab = page_slab(page);
+       if (slab) {
                /* Check slab allocator for flags and size. */
-               __check_heap_object(ptr, n, folio_slab(folio), to_user);
-       } else if (folio_test_large(folio)) {
-               offset = ptr - folio_address(folio);
-               if (n > folio_size(folio) - offset)
+               __check_heap_object(ptr, n, slab, to_user);
+       } else if (PageCompound(page)) {
+               page = compound_head(page);
+               offset = ptr - page_address(page);
+               if (n > page_size(page) - offset)
                        usercopy_abort("page alloc", NULL, to_user, offset, n);
        }
+
+       /*
+        * We cannot check non-compound pages.  They might be part of
+        * a large allocation, in which case crossing a page boundary
+        * is fine.
+        */
 }
 
 DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,