Linux cryptographic layer development
 help / color / mirror / Atom feed
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

  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