Fix these two error paths:
1. When set_memory_decrypted() fails, pages may be left fully or partially
decrypted.
2. Decrypted pages may be freed if swiotlb_alloc_tlb() determines that the
physical address is too high.
To fix the first issue, call set_memory_encrypted() on the allocated region
after a failed decryption attempt. If that also fails, leak the pages.
To fix the second issue, check that the TLB physical address is below the
requested limit before decrypting.
Let the caller differentiate between unsuitable physical address (=> retry
from a lower zone) and allocation failures (=> no point in retrying).
Cc: stable(a)vger.kernel.org
Cc: Rick Edgecombe <rick.p.edgecombe(a)intel.com>
Fixes: 79636caad361 ("swiotlb: if swiotlb is full, fall back to a transient memory pool")
Signed-off-by: Petr Tesarik <petr.tesarik1(a)huawei-partners.com>
---
kernel/dma/swiotlb.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index dff067bd56b1..0e1632f75421 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -558,29 +558,40 @@ void __init swiotlb_exit(void)
* alloc_dma_pages() - allocate pages to be used for DMA
* @gfp: GFP flags for the allocation.
* @bytes: Size of the buffer.
+ * @phys_limit: Maximum allowed physical address of the buffer.
*
* Allocate pages from the buddy allocator. If successful, make the allocated
* pages decrypted that they can be used for DMA.
*
- * Return: Decrypted pages, or %NULL on failure.
+ * Return: Decrypted pages, %NULL on allocation failure, or ERR_PTR(-EAGAIN)
+ * if the allocated physical address was above @phys_limit.
*/
-static struct page *alloc_dma_pages(gfp_t gfp, size_t bytes)
+static struct page *alloc_dma_pages(gfp_t gfp, size_t bytes, u64 phys_limit)
{
unsigned int order = get_order(bytes);
struct page *page;
+ phys_addr_t paddr;
void *vaddr;
page = alloc_pages(gfp, order);
if (!page)
return NULL;
- vaddr = page_address(page);
+ paddr = page_to_phys(page);
+ if (paddr + bytes - 1 > phys_limit) {
+ __free_pages(page, order);
+ return ERR_PTR(-EAGAIN);
+ }
+
+ vaddr = phys_to_virt(paddr);
if (set_memory_decrypted((unsigned long)vaddr, PFN_UP(bytes)))
goto error;
return page;
error:
- __free_pages(page, order);
+ /* Intentional leak if pages cannot be encrypted again. */
+ if (!set_memory_encrypted((unsigned long)vaddr, PFN_UP(bytes)))
+ __free_pages(page, order);
return NULL;
}
@@ -618,11 +629,7 @@ static struct page *swiotlb_alloc_tlb(struct device *dev, size_t bytes,
else if (phys_limit <= DMA_BIT_MASK(32))
gfp |= __GFP_DMA32;
- while ((page = alloc_dma_pages(gfp, bytes)) &&
- page_to_phys(page) + bytes - 1 > phys_limit) {
- /* allocated, but too high */
- __free_pages(page, get_order(bytes));
-
+ while (IS_ERR(page = alloc_dma_pages(gfp, bytes, phys_limit))) {
if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
phys_limit < DMA_BIT_MASK(64) &&
!(gfp & (__GFP_DMA32 | __GFP_DMA)))
--
2.34.1
We now only capture 8 bits for oemid in card->cid.oemid, so quirks that
were filling up the full 16 bits up till now would no longer apply.
Work around the problem by only checking for the bottom 8 bits when
checking if quirks should be applied
Fixes: 84ee19bffc93 ("mmc: core: Capture correct oemid-bits for eMMC cards")
Link: https://lkml.kernel.org/r/ZToJsSLHr8RnuTHz@codewreck.org
Signed-off-by: Dominique Martinet <dominique.martinet(a)atmark-techno.com>
Cc: stable(a)vger.kernel.org
Cc: Avri Altman <avri.altman(a)wdc.com>
Cc: Ulf Hansson <ulf.hansson(a)linaro.org>
Cc: Alex Fetters <Alex.Fetters(a)garmin.com>
---
Notes:
- mmc_fixup_device() was rewritten in 5.17, so older stable kernels
will need a separate patch... I suppose I can send it to stable
after this is merged if we go this way
- struct mmc_cid's and mmc_fixup's oemid fields are unsigned shorts,
we probably just want to make them unsigned char instead in which
case we don't need that check anymore?
But it's kind of nice to have a wider type so CID_OEMID_ANY can never
be a match.... Which unfortunately my patch makes moot as
((unsigned short)-1) & 0xff will be 0xff which can match anything...
- this could also be worked around in the _FIXUP_EXT macro that builds
the fixup structs, but we're getting ugly here... Or we can just go
for the big boom and try to fix all MMC_FIXUP() users in tree and
call it a day, but that'll also be fun to backport.
drivers/mmc/core/quirks.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
index 32b64b564fb1..27e0349e176d 100644
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -211,8 +211,9 @@ static inline void mmc_fixup_device(struct mmc_card *card,
if (f->manfid != CID_MANFID_ANY &&
f->manfid != card->cid.manfid)
continue;
+ /* Only the bottom 8bits are valid in JESD84-B51 */
if (f->oemid != CID_OEMID_ANY &&
- f->oemid != card->cid.oemid)
+ (f->oemid & 0xff) != (card->cid.oemid & 0xff))
continue;
if (f->name != CID_NAME_ANY &&
strncmp(f->name, card->cid.prod_name,
--
2.39.2