mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Phillip Lougher <phillip@lougher.demon.co.uk>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>,
	linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface
Date: Sun, 08 Mar 2009 06:47:52 +0000	[thread overview]
Message-ID: <49B36A18.5030506@lougher.demon.co.uk> (raw)
In-Reply-To: <20090307104637.GB8731@gondor.apana.org.au>

Herbert Xu wrote:
> On Wed, Feb 25, 2009 at 02:43:14PM +0100, Geert Uytterhoeven wrote:
>> Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
>> instead of calling the underlying zlib library directly. This simplifies e.g.
>> the addition of support for hardware decompression and different decompression
>> algorithms.
>>
>> Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
>> Cc: Phillip Lougher <phillip@lougher.demon.co.uk>
> 
> I've applied patches 1-5.  I'd like to see an ack on this before
> applying it.
> 

I've not acked it because I've not yet made any decisions as to whether 
I want it in Squashfs.  Also as Squashfs maintainer I maintain my own 
tree of patches to Squashfs, and so I'll prefer to add it to my tree for 
subsequent feeding into 2.6.30 once the merge window opens.

I'm fairly agnostic about what decompression library Squashfs uses.  The 
only thing I care about is cleanliness and usability of the API and 
performance.  If the crypto API is cleaner or the cryto zlib 
implementation is faster than the current zlib implementation then I see 
no reason not to move over to it.  But, I've seen no performance figures 
and the API seems clumsier.

Two API issues of concern (one major, one minor).  Both of these relate 
to the way Squashfs drives the decompression code, where it repeatedly 
calls it supplying additional input/output buffers, rather than using a 
"single-shot" approach where it calls the decompression code once 
supplying all the necessary input and output buffer space.

1. Minor issue -the lack of a stream.total_out field.  The current 
zlib_inflate code collects the total number of bytes decompressed over 
the multiple calls into the stream.total_out field.

    There is clearly no such field available in the cryto API, leading 
to the somewhat clumsy need to track it, i.e. it leads to the following 
additional code.

+		unsigned int produced = 0;

[snip]

 > +		length = 0;

[snip]
 > +			produced = req.avail_out;
 > +			error = crypto_decompress_update(msblk->tfm, &req);

 > +			produced -= req.avail_out;
 >
 > +			length += produced;
 >

[snip]
 > +		produced = req.avail_out;
 > +		error = crypto_decompress_final(msblk->tfm, &req);

 > +		produced -= req.avail_out;
 > +
 > +		length += produced;


Whereas previously, only the following single line was required:

 > -		length = msblk->stream.total_out;

2. Major issue - working out loop termination.

It transpires when decompressing from multiple input buffers into 
multiple output buffers, determining when the decompressor has consumed 
all input buffers and has flushed all output to the output buffers is 
difficult.

One might assume loop termination can take place once the decompressor 
has consumed all the input data - however, this is insufficient because 
the decompressor may exit having consumed all the input data but it 
still requires additional output buffer space (stream.avail_in == 0, 
stream.avail_out == 0).

This leads to the exit condition (stream.avail_in == 0 && 
stream.avail_out != 0).  However, this still isn't sufficient because 
the majority of blocks in Squashfs decompress to an exact multiple of 
the output buffer, i.e. stream.avail_in == 0 && stream.avail_out == 0 is 
true at the end of decompression.

(stream.avail_in == 0 && stream_avail_out == 0) == true may or may not 
indicate the end of decompression.  In other words the status of the 
input/output buffers doesn't give sufficient information as to whether 
to terminate the loop or not.

With zlib_inflate this is irrelevant because it supplies a suitable exit 
code indicating whether it needs to be called again (Z_OK) or whether 
decompression has finished (Z_STREAM_END).  This makes loop termination 
easy.

My biggest criticism against the cryto changes to Squashfs is 
crypto_decompress_update doesn't seem to give this information, leaving 
to the clumsy introduction of a check to see if crypto_decompress_update 
produced any output data, i.e.:

-		} while (zlib_err == Z_OK);
 > -

is replaced by:

 > +		} while (bytes || produced);
 > +

This is clearly suboptimal, and always leads to an additional iteration 
around the loop.  Only once we've iterated over the loop one last time 
doing nothing do we decide the decompression has completed.

Not only this, but the loop termination also suffers from a major 
unanticipated bug:

The loop termination forces an additional iteration around the loop even 
though we've run out of output buffer space.

Consider the usual scenario where we're decompressing a buffer into two 
4K pages (pages = 2), and the buffer decompresses to 8K.  The final 
"real" iteration will have produced != 0 and req.avail_out == 0 (we've 
consumed all the output bytes in the last output buffer).

Because produced != 0 we will iterate over the loop again.  But because
req.avail_out == 0 we will load req.next_out with a non-existent buffer 
(we will fall off the end of the buffer array), i.e.

+			if (req.avail_out == 0) {
 > +				req.next_out = buffer[page++];
 > +				req.avail_out = PAGE_CACHE_SIZE;
 >  			}
 >

If for any reason crypto_decompress_update produces unexpected output 
(perhaps because of corrupted data), we will trigger a kernel oops.

Obviously in the majority of cases (which is why the code works), the 
"false" additional iteration doesn't produce any output.  But it is 
distinctly bad practice to have code in the kernel that in normal 
operation passes a bad pointer to crypto_decompress_output, and relies 
on its behaviour not to use that bad pointer.

> Thanks,

Currently as it stands I cannot accept the patch into Squashfs for the 
above reasons.  The code is less optimal, suffers from a major bug, and 
has a number of workarounds stemming from what I feel is a less 
"featureful" API.

I'm willing to consider moving Squashfs over to the crypto API once my 
concerns have been addressed.  The promised simplification in the 
"addition of support for hardware decompression and different 
decompression algorithms" seems quite attractive.  But I'm unwilling to 
degrade the zlib support in Squashfs for this future promise.

Phillip


  reply	other threads:[~2009-03-08  6:48 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-25 13:43 [PATCH 0/6] Partial (de)compression Crypto API Geert Uytterhoeven
2009-02-25 13:43 ` [PATCH 1/6] netlink: Move netlink attribute parsing support to lib/ Geert Uytterhoeven
2009-02-25 13:43   ` [PATCH 2/6] crypto: compress - Add pcomp interface Geert Uytterhoeven
2009-02-25 13:43     ` [PATCH 3/6] crypto: testmgr - Add support for the " Geert Uytterhoeven
2009-02-25 13:43       ` [PATCH 4/6] crypto: new zlib crypto module, using pcomp Geert Uytterhoeven
2009-02-25 13:43         ` [PATCH 5/6] crypto: testmgr - add zlib test Geert Uytterhoeven
2009-02-25 13:43           ` [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface Geert Uytterhoeven
2009-03-07 10:46             ` Herbert Xu
2009-03-08  6:47               ` Phillip Lougher [this message]
2009-03-11 17:59                 ` Geert Uytterhoeven
2009-03-17 12:54                   ` [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface) Geert Uytterhoeven
2009-03-24 16:33                     ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface)) Geert Uytterhoeven
2009-03-25 10:12                       ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out Phillip Lougher
2009-04-20  6:03                       ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface)) Herbert Xu
2009-04-20  7:26                         ` Geert Uytterhoeven
2009-04-20 23:45                           ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out Phillip Lougher
2009-04-21  0:09                             ` Herbert Xu
2009-07-28 14:45                             ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{, de}compress_{update, final}() " Geert Uytterhoeven
2009-05-05 14:14                           ` [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{, de}compress_{update, final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface)) Geert Uytterhoeven
2009-05-11 15:35                             ` [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() Geert Uytterhoeven
2009-05-18  7:16                               ` Geert Uytterhoeven
2009-05-18  7:22                                 ` Herbert Xu
2009-05-27  5:05                               ` Herbert Xu
2009-03-17 12:44             ` [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface Geert Uytterhoeven
2009-02-25 21:59   ` [PATCH 1/6] netlink: Move netlink attribute parsing support to lib/ David Miller

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=49B36A18.5030506@lougher.demon.co.uk \
    --to=phillip@lougher.demon.co.uk \
    --cc=Geert.Uytterhoeven@sonycom.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@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

all inboxes | Powered by JetHome®