Re: [PATCH] crypto: skcipher - Elinimate duplicate virt.addr field

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 06, 2025 at 02:07:50PM +0800, Herbert Xu wrote:
> On Wed, Mar 05, 2025 at 07:59:37PM -0800, Eric Biggers wrote:
> >
> > I don't think it will be quite that simple, since the skcipher_walk code relies
> > on the different parts being split up so that it can do things like calculate
> > the length before it starts mapping anything.  If you can make it work, we can
> > do that.  But until that additional patch is ready I don't think it makes sense
> > to merge this one, as it leaves things half-baked with the redundant pointers.
> 
> Sure, fixing it might not be easy, partly because the new interface
> wasn't designed for its needs.
> 
> But getting rid of the duplicate field isn't hard, because we're
> already assuming that the user does not modify walk->XXX.virt.addr,
> at least not far enough to break the unmap (see the WALK_DIFF
> clause).  In fact, grepping through the arch code seems to show
> that nobody actually modifies them at all.  So we could even
> simplify the WALK_SLOW done path.
> 
> ---8<---
> Reuse the addr field from struct scatter_walk for skcipher_walk.
> In order to maintain backwards compatibility with existing users,
> retain the original virt.addr fields through unions.
> 
> Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
> ---
>  crypto/skcipher.c                  | 25 ++++++++++---------------
>  include/crypto/algapi.h            |  3 ++-
>  include/crypto/internal/skcipher.h | 20 +++++++++++++++-----
>  3 files changed, 27 insertions(+), 21 deletions(-)
> 
> diff --git a/crypto/skcipher.c b/crypto/skcipher.c
> index d321c8746950..f770307abb8e 100644
> --- a/crypto/skcipher.c
> +++ b/crypto/skcipher.c
> @@ -43,14 +43,12 @@ static inline void skcipher_map_src(struct skcipher_walk *walk)
>  {
>  	/* XXX */
>  	walk->in.addr = scatterwalk_map(&walk->in);
> -	walk->src.virt.addr = walk->in.addr;
>  }
>  
>  static inline void skcipher_map_dst(struct skcipher_walk *walk)
>  {
>  	/* XXX */
>  	walk->out.addr = scatterwalk_map(&walk->out);
> -	walk->dst.virt.addr = walk->out.addr;
>  }
>  
>  static inline gfp_t skcipher_walk_gfp(struct skcipher_walk *walk)
> @@ -100,8 +98,7 @@ int skcipher_walk_done(struct skcipher_walk *walk, int res)
>  				    SKCIPHER_WALK_DIFF)))) {
>  		scatterwalk_advance(&walk->in, n);
>  	} else if (walk->flags & SKCIPHER_WALK_DIFF) {
> -		scatterwalk_unmap(walk->src.virt.addr);
> -		scatterwalk_advance(&walk->in, n);
> +		scatterwalk_done_src(&walk->in, n);
>  	} else if (walk->flags & SKCIPHER_WALK_COPY) {
>  		scatterwalk_advance(&walk->in, n);
>  		skcipher_map_dst(walk);
> @@ -116,11 +113,8 @@ int skcipher_walk_done(struct skcipher_walk *walk, int res)
>  			 */
>  			res = -EINVAL;
>  			total = 0;
> -		} else {
> -			u8 *buf = PTR_ALIGN(walk->buffer, walk->alignmask + 1);
> -
> -			memcpy_to_scatterwalk(&walk->out, buf, n);
> -		}
> +		} else
> +			memcpy_to_scatterwalk(&walk->out, walk->out.addr, n);
>  		goto dst_done;
>  	}
>  
> @@ -176,10 +170,11 @@ static int skcipher_next_slow(struct skcipher_walk *walk, unsigned int bsize)
>  			return skcipher_walk_done(walk, -ENOMEM);
>  		walk->buffer = buffer;
>  	}
> -	walk->dst.virt.addr = PTR_ALIGN(buffer, alignmask + 1);
> -	walk->src.virt.addr = walk->dst.virt.addr;
>  
> -	memcpy_from_scatterwalk(walk->src.virt.addr, &walk->in, bsize);
> +	buffer = PTR_ALIGN(buffer, alignmask + 1);
> +	memcpy_from_scatterwalk(buffer, &walk->in, bsize);
> +	walk->out.addr = buffer;
> +	walk->in.addr = walk->out.addr;
>  
>  	walk->nbytes = bsize;
>  	walk->flags |= SKCIPHER_WALK_SLOW;
> @@ -199,8 +194,8 @@ static int skcipher_next_copy(struct skcipher_walk *walk)
>  	 * processed (which might be less than walk->nbytes) is known.
>  	 */
>  
> -	walk->src.virt.addr = tmp;
> -	walk->dst.virt.addr = tmp;
> +	walk->in.addr = tmp;
> +	walk->out.addr = tmp;
>  	return 0;
>  }
>  
> @@ -214,7 +209,7 @@ static int skcipher_next_fast(struct skcipher_walk *walk)
>  		(u8 *)(sg_page(walk->out.sg) + (walk->out.offset >> PAGE_SHIFT));
>  
>  	skcipher_map_src(walk);
> -	walk->dst.virt.addr = walk->src.virt.addr;
> +	walk->out.addr = walk->in.addr;
>  
>  	if (diff) {
>  		walk->flags |= SKCIPHER_WALK_DIFF;
> diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
> index 41733a0b45dd..94147ea8c14d 100644
> --- a/include/crypto/algapi.h
> +++ b/include/crypto/algapi.h
> @@ -120,9 +120,10 @@ struct crypto_queue {
>  };
>  
>  struct scatter_walk {
> +	/* Must be the first member, see struct skcipher_walk. */
> +	void *addr;
>  	struct scatterlist *sg;
>  	unsigned int offset;
> -	void *addr;
>  };
>  
>  struct crypto_attr_alg {
> diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
> index d6ae7a86fed2..357441b56c1e 100644
> --- a/include/crypto/internal/skcipher.h
> +++ b/include/crypto/internal/skcipher.h
> @@ -57,14 +57,24 @@ struct crypto_lskcipher_spawn {
>  struct skcipher_walk {
>  	union {
>  		struct {
> -			void *addr;
> -		} virt;
> -	} src, dst;
> +			struct {
> +				void *const addr;
> +			} virt;
> +		} src;
> +		struct scatter_walk in;
> +	};
>  
> -	struct scatter_walk in;
>  	unsigned int nbytes;
>  
> -	struct scatter_walk out;
> +	union {
> +		struct {
> +			struct {
> +				void *const addr;
> +			} virt;
> +		} dst;
> +		struct scatter_walk out;
> +	};
> +

Those unions are ugly, but I guess this is good enough.  Please also delete the
/* XXX */ comments, fix the typo in the title, and resend this as a real patch.
Thanks!

- Eric




[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]
  Powered by Linux