[Devel] [PATCH RHEL8 COMMIT] ms/net: introduce helper sendpage_ok() in include/linux/net.h

Konstantin Khorenko khorenko at virtuozzo.com
Fri Jun 11 15:33:49 MSK 2021


The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.40
------>
commit 8a894d5ce45c6886c7a2d695e37c8e91201c69d9
Author: Coly Li <colyli at suse.de>
Date:   Fri Jun 11 15:33:48 2021 +0300

    ms/net: introduce helper sendpage_ok() in include/linux/net.h
    
    The original problem was from nvme-over-tcp code, who mistakenly uses
    kernel_sendpage() to send pages allocated by __get_free_pages() without
    __GFP_COMP flag. Such pages don't have refcount (page_count is 0) on
    tail pages, sending them by kernel_sendpage() may trigger a kernel panic
    from a corrupted kernel heap, because these pages are incorrectly freed
    in network stack as page_count 0 pages.
    
    This patch introduces a helper sendpage_ok(), it returns true if the
    checking page,
    - is not slab page: PageSlab(page) is false.
    - has page refcount: page_count(page) is not zero
    
    All drivers who want to send page to remote end by kernel_sendpage()
    may use this helper to check whether the page is OK. If the helper does
    not return true, the driver should try other non sendpage method (e.g.
    sock_no_sendpage()) to handle the page.
    
    Signed-off-by: Coly Li <colyli at suse.de>
    Cc: Chaitanya Kulkarni <chaitanya.kulkarni at wdc.com>
    Cc: Christoph Hellwig <hch at lst.de>
    Cc: Hannes Reinecke <hare at suse.de>
    Cc: Jan Kara <jack at suse.com>
    Cc: Jens Axboe <axboe at kernel.dk>
    Cc: Mikhail Skorzhinskii <mskorzhinskiy at solarflare.com>
    Cc: Philipp Reisner <philipp.reisner at linbit.com>
    Cc: Sagi Grimberg <sagi at grimberg.me>
    Cc: Vlastimil Babka <vbabka at suse.com>
    Cc: stable at vger.kernel.org
    Signed-off-by: David S. Miller <davem at davemloft.net>
    
    (cherry-picked from ms c381b07941ad ("net: introduce helper sendpage_ok() in
    include/linux/net.h"))
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 include/linux/net.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/linux/net.h b/include/linux/net.h
index df3f79a8e753..216c40d2e6bb 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include <linux/once.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
 
 #include <uapi/linux/net.h>
 
@@ -310,6 +311,21 @@ do {									\
 #define net_get_random_once_wait(buf, nbytes)			\
 	get_random_once_wait((buf), (nbytes))
 
+/*
+ * E.g. XFS meta- & log-data is in slab pages, or bcache meta
+ * data pages, or other high order pages allocated by
+ * __get_free_pages() without __GFP_COMP, which have a page_count
+ * of 0 and/or have PageSlab() set. We cannot use send_page for
+ * those, as that does get_page(); put_page(); and would cause
+ * either a VM_BUG directly, or __page_cache_release a page that
+ * would actually still be referenced by someone, leading to some
+ * obscure delayed Oops somewhere else.
+ */
+static inline bool sendpage_ok(struct page *page)
+{
+	return !PageSlab(page) && page_count(page) >= 1;
+}
+
 int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
 		   size_t num, size_t len);
 int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,


More information about the Devel mailing list