Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp378818pxj; Tue, 18 May 2021 05:35:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwxd1SRtjg/XR4Ch1/VExB4CZ7KxqMgThBgNWgMIbcAn4HtuyVdcNc2pGocBrKr7Tx78IDj X-Received: by 2002:a05:6402:3553:: with SMTP id f19mr6615576edd.167.1621341315267; Tue, 18 May 2021 05:35:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621341315; cv=none; d=google.com; s=arc-20160816; b=tF99BOZ9mOVrMxWWKqn8L0DK2kWqcW7jIut3t7ulRyi9I3pdy7BJYPMGaYv7Wa4JEl mgwsn4bW0evagN6SNnTpsMBUejeR7xbQOcNGtjoR9UrycvRLGCUNerjVLCilSJ0cRzAq lT44iwpgZ52bNXkaLAughqAK/HFw+bVUNPhYzLiAlc8jeqLLx2MM07WliPyMhXVKyBey 1y20TbDLX5FC4AAsTMnL0I+0WRZnJrsL9bqeYuRiojtAABMP8nyM9+Xy295oX5koXXNq 7a9Ey76gapwBB7yMuOIqBOS1dRFFxwe2BIm0khXM7NwyMF7qgMA8+YFmMTZOMAoscf+3 gKNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=MsmGWqgGvr3K2KrY8gCS/KdRMNq4uxUeaGaSrWIvExA=; b=FsfLZCPWSJL1PuLPY/G7uNh/OPhJtL1RRZ9vO050Dtlyy33M5G2tKFDkacfD2+LS4k WPPUiWelopYXCd67I+lh3EnMQ7vt4lDOh0yBTF3wpU1pzCjfXptBWxK8OHa6Cpd8S77n TDY0yycnfpoFC6TZIpJ2asHIZ7pv9ebhztnFUSycEnwWP/C7ePMMqT/7d57crwj4yatq 1WrrabnDG8g8wt/ABnrPwq+VaKIeTrb4CGz9HgihjtFJfmnzRGOiJD5TK23EZd7lNQl3 Hy8FasoOW4sr1rWKPLRPpca0WSGVLyRwkIyAsOaZsqNx3baYS/hGwCwr8x0IgCJuDHhE YAlg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hXiFwShU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 26si17238487ejx.371.2021.05.18.05.34.52; Tue, 18 May 2021 05:35:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hXiFwShU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242178AbhEQPdj (ORCPT + 99 others); Mon, 17 May 2021 11:33:39 -0400 Received: from mail.kernel.org ([198.145.29.99]:56032 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244089AbhEQPSk (ORCPT ); Mon, 17 May 2021 11:18:40 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id B0EBE61C73; Mon, 17 May 2021 14:33:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1621262020; bh=K9jm3lQXIJXrJPBmrlBsloqGvVATvMESbRmNo2MUQDI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hXiFwShUIuew2m3u5aq3exWzhRI5HRAxExdUOc9r9W5ROUn3eBAuerK52LYlc/WLu 7EROOdkJw2zfzrYSGoODqqVrNnLvDMxki7ln8DJBPC01FmJY+AsyQnDLXdRJ6OQOB3 IdVdAST7t/+WLJP8Lzy6HtQeVdydYurw1Lee425E= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Matthew Wilcox (Oracle)" , Ilias Apalodimas , Jesper Dangaard Brouer , Vlastimil Babka , Matteo Croce , Andrew Morton , Linus Torvalds Subject: [PATCH 5.4 125/141] mm: fix struct page layout on 32-bit systems Date: Mon, 17 May 2021 16:02:57 +0200 Message-Id: <20210517140247.027645278@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210517140242.729269392@linuxfoundation.org> References: <20210517140242.729269392@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Matthew Wilcox (Oracle) commit 9ddb3c14afba8bc5950ed297f02d4ae05ff35cd1 upstream. 32-bit architectures which expect 8-byte alignment for 8-byte integers and need 64-bit DMA addresses (arm, mips, ppc) had their struct page inadvertently expanded in 2019. When the dma_addr_t was added, it forced the alignment of the union to 8 bytes, which inserted a 4 byte gap between 'flags' and the union. Fix this by storing the dma_addr_t in one or two adjacent unsigned longs. This restores the alignment to that of an unsigned long. We always store the low bits in the first word to prevent the PageTail bit from being inadvertently set on a big endian platform. If that happened, get_user_pages_fast() racing against a page which was freed and reallocated to the page_pool could dereference a bogus compound_head(), which would be hard to trace back to this cause. Link: https://lkml.kernel.org/r/20210510153211.1504886-1-willy@infradead.org Fixes: c25fff7171be ("mm: add dma_addr_t to struct page") Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Ilias Apalodimas Acked-by: Jesper Dangaard Brouer Acked-by: Vlastimil Babka Tested-by: Matteo Croce Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/mm_types.h | 4 ++-- include/net/page_pool.h | 12 +++++++++++- net/core/page_pool.c | 6 +++--- 3 files changed, 16 insertions(+), 6 deletions(-) --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -95,10 +95,10 @@ struct page { }; struct { /* page_pool used by netstack */ /** - * @dma_addr: might require a 64-bit value even on + * @dma_addr: might require a 64-bit value on * 32-bit architectures. */ - dma_addr_t dma_addr; + unsigned long dma_addr[2]; }; struct { /* slab, slob and slub */ union { --- a/include/net/page_pool.h +++ b/include/net/page_pool.h @@ -185,7 +185,17 @@ static inline void page_pool_release_pag static inline dma_addr_t page_pool_get_dma_addr(struct page *page) { - return page->dma_addr; + dma_addr_t ret = page->dma_addr[0]; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16; + return ret; +} + +static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr) +{ + page->dma_addr[0] = addr; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + page->dma_addr[1] = upper_32_bits(addr); } static inline bool is_page_pool_compiled_in(void) --- a/net/core/page_pool.c +++ b/net/core/page_pool.c @@ -157,7 +157,7 @@ static struct page *__page_pool_alloc_pa put_page(page); return NULL; } - page->dma_addr = dma; + page_pool_set_dma_addr(page, dma); skip_dma_map: /* Track how many pages are held 'in-flight' */ @@ -216,12 +216,12 @@ static void __page_pool_clean_page(struc if (!(pool->p.flags & PP_FLAG_DMA_MAP)) goto skip_dma_unmap; - dma = page->dma_addr; + dma = page_pool_get_dma_addr(page); /* DMA unmap */ dma_unmap_page_attrs(pool->p.dev, dma, PAGE_SIZE << pool->p.order, pool->p.dma_dir, DMA_ATTR_SKIP_CPU_SYNC); - page->dma_addr = 0; + page_pool_set_dma_addr(page, 0); skip_dma_unmap: /* This may be the last page returned, releasing the pool, so * it is not safe to reference pool afterwards.