Skip to content

Commit 6d89f74

Browse files
Mikulas Patockaherbertx
authored andcommitted
crypto: deflate - fix spurious -ENOSPC
The code in deflate_decompress_one may erroneously return -ENOSPC even if it didn't run out of output space. The error happens under this condition: - Suppose that there are two input pages, the compressed data fits into the first page and the zlib checksum is placed in the second page. - The code iterates over the first page, decompresses the data and fully fills the destination buffer, zlib_inflate returns Z_OK becuse zlib hasn't seen the checksum yet. - The outer do-while loop is iterated again, acomp_walk_next_src sets the input parameters to the second page containing the checksum. - We go into the inner do-while loop, execute "dcur = acomp_walk_next_dst(&walk);". "dcur" is zero, so we break out of the loop and return -ENOSPC, despite the fact that the decompressed data fit into the destination buffer. In order to fix this bug, this commit changes the logic when to report the -ENOSPC error. We report the error if the destination buffer is empty *and* if zlib_inflate didn't make any progress consuming the input buffer. If zlib_inflate consumes the trailing checksum, we see that it made progress and we will not return -ENOSPC. Fixes: 08cabc7 ("crypto: deflate - Convert to acomp") Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 80688af commit 6d89f74

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

crypto/deflate.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,21 @@ static int deflate_decompress_one(struct acomp_req *req,
164164

165165
do {
166166
unsigned int dcur;
167+
unsigned long avail_in;
167168

168169
dcur = acomp_walk_next_dst(&walk);
169-
if (!dcur) {
170-
out_of_space = true;
171-
break;
172-
}
173170

174171
stream->avail_out = dcur;
175172
stream->next_out = walk.dst.virt.addr;
173+
avail_in = stream->avail_in;
176174

177175
ret = zlib_inflate(stream, Z_NO_FLUSH);
178176

177+
if (!dcur && avail_in == stream->avail_in) {
178+
out_of_space = true;
179+
break;
180+
}
181+
179182
dcur -= stream->avail_out;
180183
acomp_walk_done_dst(&walk, dcur);
181184
} while (ret == Z_OK && stream->avail_in);

0 commit comments

Comments
 (0)