mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
erofs: enable error reporting for z_erofs_fixup_insize()
Enable propagation of detailed errors to callers. Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
This commit is contained in:
@@ -72,8 +72,8 @@ struct z_erofs_stream_dctx {
|
|||||||
|
|
||||||
const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx,
|
const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx,
|
||||||
void **dst, void **src, struct page **pgpl);
|
void **dst, void **src, struct page **pgpl);
|
||||||
int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf,
|
const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq,
|
||||||
unsigned int padbufsize);
|
const char *padbuf, unsigned int padbufsize);
|
||||||
int __init z_erofs_init_decompressor(void);
|
int __init z_erofs_init_decompressor(void);
|
||||||
void z_erofs_exit_decompressor(void);
|
void z_erofs_exit_decompressor(void);
|
||||||
int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
|
int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
|
||||||
|
|||||||
@@ -178,21 +178,21 @@ static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the exact inputsize with zero_padding feature.
|
* Get the exact on-disk size of the compressed data:
|
||||||
* - For LZ4, it should work if zero_padding feature is on (5.3+);
|
* - For LZ4, it should apply if the zero_padding feature is on (5.3+);
|
||||||
* - For MicroLZMA, it'd be enabled all the time.
|
* - For others, zero_padding is enabled all the time.
|
||||||
*/
|
*/
|
||||||
int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf,
|
const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq,
|
||||||
unsigned int padbufsize)
|
const char *padbuf, unsigned int padbufsize)
|
||||||
{
|
{
|
||||||
const char *padend;
|
const char *padend;
|
||||||
|
|
||||||
padend = memchr_inv(padbuf, 0, padbufsize);
|
padend = memchr_inv(padbuf, 0, padbufsize);
|
||||||
if (!padend)
|
if (!padend)
|
||||||
return -EFSCORRUPTED;
|
return "compressed data start not found";
|
||||||
rq->inputsize -= padend - padbuf;
|
rq->inputsize -= padend - padbuf;
|
||||||
rq->pageofs_in += padend - padbuf;
|
rq->pageofs_in += padend - padbuf;
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst)
|
static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst)
|
||||||
@@ -200,6 +200,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
|
|||||||
bool support_0padding = false, may_inplace = false;
|
bool support_0padding = false, may_inplace = false;
|
||||||
unsigned int inputmargin;
|
unsigned int inputmargin;
|
||||||
u8 *out, *headpage, *src;
|
u8 *out, *headpage, *src;
|
||||||
|
const char *reason;
|
||||||
int ret, maptype;
|
int ret, maptype;
|
||||||
|
|
||||||
DBG_BUGON(*rq->in == NULL);
|
DBG_BUGON(*rq->in == NULL);
|
||||||
@@ -208,12 +209,12 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
|
|||||||
/* LZ4 decompression inplace is only safe if zero_padding is enabled */
|
/* LZ4 decompression inplace is only safe if zero_padding is enabled */
|
||||||
if (erofs_sb_has_zero_padding(EROFS_SB(rq->sb))) {
|
if (erofs_sb_has_zero_padding(EROFS_SB(rq->sb))) {
|
||||||
support_0padding = true;
|
support_0padding = true;
|
||||||
ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
|
reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
|
||||||
min_t(unsigned int, rq->inputsize,
|
min_t(unsigned int, rq->inputsize,
|
||||||
rq->sb->s_blocksize - rq->pageofs_in));
|
rq->sb->s_blocksize - rq->pageofs_in));
|
||||||
if (ret) {
|
if (reason) {
|
||||||
kunmap_local(headpage);
|
kunmap_local(headpage);
|
||||||
return ret;
|
return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED;
|
||||||
}
|
}
|
||||||
may_inplace = !((rq->pageofs_in + rq->inputsize) &
|
may_inplace = !((rq->pageofs_in + rq->inputsize) &
|
||||||
(rq->sb->s_blocksize - 1));
|
(rq->sb->s_blocksize - 1));
|
||||||
|
|||||||
@@ -9,16 +9,17 @@ static int __z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
|
|||||||
struct sg_table st_src, st_dst;
|
struct sg_table st_src, st_dst;
|
||||||
struct acomp_req *req;
|
struct acomp_req *req;
|
||||||
struct crypto_wait wait;
|
struct crypto_wait wait;
|
||||||
|
const char *reason;
|
||||||
u8 *headpage;
|
u8 *headpage;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
headpage = kmap_local_page(*rq->in);
|
headpage = kmap_local_page(*rq->in);
|
||||||
ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
|
reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
|
||||||
min_t(unsigned int, rq->inputsize,
|
min_t(unsigned int, rq->inputsize,
|
||||||
rq->sb->s_blocksize - rq->pageofs_in));
|
rq->sb->s_blocksize - rq->pageofs_in));
|
||||||
kunmap_local(headpage);
|
kunmap_local(headpage);
|
||||||
if (ret)
|
if (reason)
|
||||||
return ret;
|
return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED;
|
||||||
|
|
||||||
req = acomp_request_alloc(tfm);
|
req = acomp_request_alloc(tfm);
|
||||||
if (!req)
|
if (!req)
|
||||||
|
|||||||
@@ -103,16 +103,16 @@ static const char *__z_erofs_deflate_decompress(struct z_erofs_decompress_req *r
|
|||||||
struct super_block *sb = rq->sb;
|
struct super_block *sb = rq->sb;
|
||||||
struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 };
|
struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 };
|
||||||
struct z_erofs_deflate *strm;
|
struct z_erofs_deflate *strm;
|
||||||
const char *reason = NULL;
|
const char *reason;
|
||||||
int zerr, err;
|
int zerr;
|
||||||
|
|
||||||
/* 1. get the exact DEFLATE compressed size */
|
/* 1. get the exact DEFLATE compressed size */
|
||||||
dctx.kin = kmap_local_page(*rq->in);
|
dctx.kin = kmap_local_page(*rq->in);
|
||||||
err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
||||||
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
||||||
if (err) {
|
if (reason) {
|
||||||
kunmap_local(dctx.kin);
|
kunmap_local(dctx.kin);
|
||||||
return ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. get an available DEFLATE context */
|
/* 2. get an available DEFLATE context */
|
||||||
@@ -130,7 +130,7 @@ again:
|
|||||||
/* 3. multi-call decompress */
|
/* 3. multi-call decompress */
|
||||||
zerr = zlib_inflateInit2(&strm->z, -MAX_WBITS);
|
zerr = zlib_inflateInit2(&strm->z, -MAX_WBITS);
|
||||||
if (zerr != Z_OK) {
|
if (zerr != Z_OK) {
|
||||||
err = -EINVAL;
|
reason = ERR_PTR(-EINVAL);
|
||||||
goto failed_zinit;
|
goto failed_zinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,12 +161,11 @@ again:
|
|||||||
reason = (zerr == Z_DATA_ERROR ?
|
reason = (zerr == Z_DATA_ERROR ?
|
||||||
"corrupted compressed data" :
|
"corrupted compressed data" :
|
||||||
"unexpected end of stream");
|
"unexpected end of stream");
|
||||||
err = -EFSCORRUPTED;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zlib_inflateEnd(&strm->z) != Z_OK && !err)
|
if (zlib_inflateEnd(&strm->z) != Z_OK && !reason)
|
||||||
err = -EIO;
|
reason = ERR_PTR(-EIO);
|
||||||
if (dctx.kout)
|
if (dctx.kout)
|
||||||
kunmap_local(dctx.kout);
|
kunmap_local(dctx.kout);
|
||||||
failed_zinit:
|
failed_zinit:
|
||||||
@@ -177,7 +176,7 @@ failed_zinit:
|
|||||||
z_erofs_deflate_head = strm;
|
z_erofs_deflate_head = strm;
|
||||||
spin_unlock(&z_erofs_deflate_lock);
|
spin_unlock(&z_erofs_deflate_lock);
|
||||||
wake_up(&z_erofs_deflate_wq);
|
wake_up(&z_erofs_deflate_wq);
|
||||||
return reason ?: ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
|
static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
|
||||||
|
|||||||
@@ -154,16 +154,15 @@ static const char *z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
|
|||||||
struct xz_buf buf = {};
|
struct xz_buf buf = {};
|
||||||
struct z_erofs_lzma *strm;
|
struct z_erofs_lzma *strm;
|
||||||
enum xz_ret xz_err;
|
enum xz_ret xz_err;
|
||||||
const char *reason = NULL;
|
const char *reason;
|
||||||
int err;
|
|
||||||
|
|
||||||
/* 1. get the exact LZMA compressed size */
|
/* 1. get the exact LZMA compressed size */
|
||||||
dctx.kin = kmap_local_page(*rq->in);
|
dctx.kin = kmap_local_page(*rq->in);
|
||||||
err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
||||||
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
||||||
if (err) {
|
if (reason) {
|
||||||
kunmap_local(dctx.kin);
|
kunmap_local(dctx.kin);
|
||||||
return ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. get an available lzma context */
|
/* 2. get an available lzma context */
|
||||||
@@ -224,7 +223,7 @@ again:
|
|||||||
z_erofs_lzma_head = strm;
|
z_erofs_lzma_head = strm;
|
||||||
spin_unlock(&z_erofs_lzma_lock);
|
spin_unlock(&z_erofs_lzma_lock);
|
||||||
wake_up(&z_erofs_lzma_wq);
|
wake_up(&z_erofs_lzma_wq);
|
||||||
return reason ?: ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct z_erofs_decompressor z_erofs_lzma_decomp = {
|
const struct z_erofs_decompressor z_erofs_lzma_decomp = {
|
||||||
|
|||||||
@@ -143,17 +143,17 @@ static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
|
|||||||
zstd_in_buffer in_buf = { NULL, 0, 0 };
|
zstd_in_buffer in_buf = { NULL, 0, 0 };
|
||||||
zstd_out_buffer out_buf = { NULL, 0, 0 };
|
zstd_out_buffer out_buf = { NULL, 0, 0 };
|
||||||
struct z_erofs_zstd *strm;
|
struct z_erofs_zstd *strm;
|
||||||
const char *reason = NULL;
|
|
||||||
zstd_dstream *stream;
|
zstd_dstream *stream;
|
||||||
int zerr, err;
|
const char *reason;
|
||||||
|
int zerr;
|
||||||
|
|
||||||
/* 1. get the exact compressed size */
|
/* 1. get the exact compressed size */
|
||||||
dctx.kin = kmap_local_page(*rq->in);
|
dctx.kin = kmap_local_page(*rq->in);
|
||||||
err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
|
||||||
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
|
||||||
if (err) {
|
if (reason) {
|
||||||
kunmap_local(dctx.kin);
|
kunmap_local(dctx.kin);
|
||||||
return ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. get an available ZSTD context */
|
/* 2. get an available ZSTD context */
|
||||||
@@ -162,7 +162,7 @@ static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
|
|||||||
/* 3. multi-call decompress */
|
/* 3. multi-call decompress */
|
||||||
stream = zstd_init_dstream(z_erofs_zstd_max_dictsize, strm->wksp, strm->wkspsz);
|
stream = zstd_init_dstream(z_erofs_zstd_max_dictsize, strm->wksp, strm->wkspsz);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
err = -ENOMEM;
|
reason = ERR_PTR(-ENOMEM);
|
||||||
goto failed_zinit;
|
goto failed_zinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ failed_zinit:
|
|||||||
z_erofs_zstd_head = strm;
|
z_erofs_zstd_head = strm;
|
||||||
spin_unlock(&z_erofs_zstd_lock);
|
spin_unlock(&z_erofs_zstd_lock);
|
||||||
wake_up(&z_erofs_zstd_wq);
|
wake_up(&z_erofs_zstd_wq);
|
||||||
return reason ?: ERR_PTR(err);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct z_erofs_decompressor z_erofs_zstd_decomp = {
|
const struct z_erofs_decompressor z_erofs_zstd_decomp = {
|
||||||
|
|||||||
Reference in New Issue
Block a user