Thomas Bogendoerfer ac9833
From: Haiyang Zhang <haiyangz@microsoft.com>
Thomas Bogendoerfer ac9833
Date: Fri, 21 Apr 2023 10:06:58 -0700
Thomas Bogendoerfer ac9833
Subject: net: mana: Check if netdev/napi_alloc_frag returns single page
Thomas Bogendoerfer ac9833
Patch-mainline: v6.4-rc1
Thomas Bogendoerfer ac9833
Git-commit: df18f2da302f169e1a29098c6ca3b474f1b0269e
Thomas Bogendoerfer ac9833
References: bsc#1210551
Thomas Bogendoerfer ac9833
Thomas Bogendoerfer ac9833
netdev/napi_alloc_frag() may fall back to single page which is smaller
Thomas Bogendoerfer ac9833
than the requested size.
Thomas Bogendoerfer ac9833
Add error checking to avoid memory overwritten.
Thomas Bogendoerfer ac9833
Thomas Bogendoerfer ac9833
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Thomas Bogendoerfer ac9833
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Thomas Bogendoerfer ac9833
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer ac9833
---
Thomas Bogendoerfer ac9833
 drivers/net/ethernet/microsoft/mana/mana_en.c |   15 +++++++++++++++
Thomas Bogendoerfer ac9833
 1 file changed, 15 insertions(+)
Thomas Bogendoerfer ac9833
Thomas Bogendoerfer ac9833
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
Thomas Bogendoerfer ac9833
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
Thomas Bogendoerfer ac9833
@@ -512,6 +512,14 @@ static int mana_pre_alloc_rxbufs(struct
Thomas Bogendoerfer ac9833
 			va = netdev_alloc_frag(mpc->rxbpre_alloc_size);
Thomas Bogendoerfer ac9833
 			if (!va)
Thomas Bogendoerfer ac9833
 				goto error;
Thomas Bogendoerfer ac9833
+
Thomas Bogendoerfer ac9833
+			page = virt_to_head_page(va);
Thomas Bogendoerfer ac9833
+			/* Check if the frag falls back to single page */
Thomas Bogendoerfer ac9833
+			if (compound_order(page) <
Thomas Bogendoerfer ac9833
+			    get_order(mpc->rxbpre_alloc_size)) {
Thomas Bogendoerfer ac9833
+				put_page(page);
Thomas Bogendoerfer ac9833
+				goto error;
Thomas Bogendoerfer ac9833
+			}
Thomas Bogendoerfer ac9833
 		} else {
Thomas Bogendoerfer ac9833
 			page = dev_alloc_page();
Thomas Bogendoerfer ac9833
 			if (!page)
Thomas Bogendoerfer ac9833
@@ -1457,6 +1465,13 @@ static void *mana_get_rxfrag(struct mana
Thomas Bogendoerfer ac9833
 
Thomas Bogendoerfer ac9833
 		if (!va)
Thomas Bogendoerfer ac9833
 			return NULL;
Thomas Bogendoerfer ac9833
+
Thomas Bogendoerfer ac9833
+		page = virt_to_head_page(va);
Thomas Bogendoerfer ac9833
+		/* Check if the frag falls back to single page */
Thomas Bogendoerfer ac9833
+		if (compound_order(page) < get_order(rxq->alloc_size)) {
Thomas Bogendoerfer ac9833
+			put_page(page);
Thomas Bogendoerfer ac9833
+			return NULL;
Thomas Bogendoerfer ac9833
+		}
Thomas Bogendoerfer ac9833
 	} else {
Thomas Bogendoerfer ac9833
 		page = dev_alloc_page();
Thomas Bogendoerfer ac9833
 		if (!page)