From: Eric Biggers <ebiggers@kernel.org>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Linux Crypto Mailing List <linux-crypto@vger.kernel.org>
Subject: Re: [v2 PATCH 1/2] crypto: scatterwalk - Use nth_page instead of doing it by hand
Date: Wed, 12 Mar 2025 12:56:22 -0700 [thread overview]
Message-ID: <20250312195622.GA1621@sol.localdomain> (raw)
In-Reply-To: <03f40ecd970de816686b233bd79406768dc66bbc.1741753576.git.herbert@gondor.apana.org.au>
On Wed, Mar 12, 2025 at 12:29:57PM +0800, Herbert Xu wrote:
> Curiously, the Crypto API scatterwalk incremented pages by hand
> rather than using nth_page. Possibly because scatterwalk predates
> nth_page (the following commit is from the history tree):
Well, also because it's never been clearly defined what a scatterlist even is.
> commit 3957f2b34960d85b63e814262a8be7d5ad91444d
> Author: James Morris <jmorris@intercode.com.au>
> Date: Sun Feb 2 07:35:32 2003 -0800
>
> [CRYPTO]: in/out scatterlist support for ciphers.
>
> Fix this by using nth_page.
This needs an explanation of what this is actually fixing.
I think it is: on a system with SPARSEMEM && !SPARSEMEM_VMEMMAP, if the caller
provided a scatterlist element that spanned physical memory sections that are
physically contiguous (but have separate vmemmaps), then the struct page(s)
calculated for any non-first sections would be invalid. But then that invalid
struct page just gets passed to kmap_local_page(), so it would only matter if
also HIGHMEM || WANT_PAGE_VIRTUAL which are the cases where the struct page
actually gets used, I think?
All the edge cases like this need to be fixed of course, though fortunately it
sounds like this one was super rare.
> diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
> index b7e617ae4442..0ba5be363abf 100644
> --- a/include/crypto/scatterwalk.h
> +++ b/include/crypto/scatterwalk.h
> @@ -100,11 +100,15 @@ static inline void scatterwalk_get_sglist(struct scatter_walk *walk,
> static inline void scatterwalk_map(struct scatter_walk *walk)
> {
> struct page *base_page = sg_page(walk->sg);
> + unsigned int offset = walk->offset;
> + void *addr;
>
> if (IS_ENABLED(CONFIG_HIGHMEM)) {
> - walk->__addr = kmap_local_page(base_page +
> - (walk->offset >> PAGE_SHIFT)) +
> - offset_in_page(walk->offset);
> + struct page *page;
> +
> + page = nth_page(base_page, offset >> PAGE_SHIFT);
> + offset = offset_in_page(offset);
> + addr = kmap_local_page(page) + offset;
It would be cleaner as:
struct page *page;
page = nth_page(base_page, offset >> PAGE_SHIFT);
walk->__addr = kmap_local_page(page) + offset_in_page(offset);
> } else {
> /*
> * When !HIGHMEM we allow the walker to return segments that
> @@ -112,13 +116,14 @@ static inline void scatterwalk_map(struct scatter_walk *walk)
> * clear that in this case we're working in the linear buffer of
> * the whole sg entry in the kernel's direct map rather than
> * within the mapped buffer of a single page, compute the
> - * address as an offset from the page_address() of the first
> - * page of the sg entry. Either way the result is the address
> - * in the direct map, but this makes it clearer what is really
> - * going on.
> + * address as an offset from the lowmem_page_address() of
> + * the first page of the sg entry. Either way the result
> + * is the address in the direct map, but this makes it clearer
> + * what is really going on.
> */
> - walk->__addr = page_address(base_page) + walk->offset;
> + addr = lowmem_page_address(base_page) + offset;
> }
> + walk->__addr = addr;
This change is unrelated and seems incorrect. lowmem_page_address() is a mm
implementation detail. page_address() is the right one to use.
- Eric
next prev parent reply other threads:[~2025-03-12 19:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-12 4:29 [v2 PATCH 0/2] crypto: Use nth_page instead of doing it by hand Herbert Xu
2025-03-12 4:29 ` [v2 PATCH 1/2] crypto: scatterwalk - " Herbert Xu
2025-03-12 19:56 ` Eric Biggers [this message]
2025-03-13 1:43 ` Herbert Xu
2025-03-13 3:13 ` Eric Biggers
2025-03-12 4:30 ` [v2 PATCH 2/2] crypto: hash " Herbert Xu
2025-03-12 20:09 ` Eric Biggers
2025-03-13 2:36 ` Herbert Xu
2025-03-13 3:07 ` Eric Biggers
2025-03-13 4:04 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250312195622.GA1621@sol.localdomain \
--to=ebiggers@kernel.org \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox