On incremental uncompressed builds, z_erofs_parse_cfgs takes the legacy path for
images without COMPR_CFGS and unconditionally sets available_compr_algs
to LZ4, regardless of whether compression was actually used.
When the current build requests no compression, z_erofs_compress_init
returns early leaving ccfg uninitialized and available_compr_algs
unchanged, subsquently causing a crash when alg is dereferenced.

Fix this by gating compression on whether the per-algorithm ccfg entry was
actually initialized rather than trusting the superblock bitmask.

Simple repro with alpine rootfs:

./mkfs.erofs /tmp/alpine.erofs /tmp/alpine
./mkfs.erofs --incremental=data /tmp/alpine.erofs /tmp/alpine

mkfs.erofs 1.9-g1d5bacbb
<W> erofs: EXPERIMENTAL incremental build in use. Use at your own risk!
Processing bin/sh ...zsh: segmentation fault (core dumped)  ./mkfs.erofs 
--incremental=data /tmp/alpine.erofs /tmp/alpine

Signed-off-by: Jonathan Calmels <[email protected]>
---
 lib/compress.c          | 10 ++++++++++
 lib/inode.c             | 17 ++++++++++++-----
 lib/liberofs_compress.h |  1 +
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/lib/compress.c b/lib/compress.c
index ea07409..e5bb784 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -2186,6 +2186,16 @@ static int z_erofs_build_compr_cfgs(struct 
erofs_importer *im,
        return ret;
 }
 
+bool z_erofs_compress_alg_enabled(const struct erofs_importer *im, u8 algid)
+{
+       struct erofs_sb_info *sbi = im->sbi;
+
+       if (!sbi->available_compr_algs || !sbi->zmgr || algid >= 
EROFS_MAX_COMPR_CFGS)
+               return false;
+
+       return sbi->zmgr->ccfg[algid].enable;
+}
+
 int z_erofs_compress_init(struct erofs_importer *im)
 {
        const struct erofs_importer_params *params = im->params;
diff --git a/lib/inode.c b/lib/inode.c
index c225faa..05344e7 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -624,9 +624,18 @@ int erofs_write_file_from_buffer(struct erofs_inode 
*inode, char *buf)
 static bool erofs_file_is_compressible(struct erofs_importer *im,
                                       struct erofs_inode *inode)
 {
-       if (erofs_is_metabox_inode(inode) &&
-           !im->params->pclusterblks_metabox)
+       u8 algid;
+
+       if (erofs_is_metabox_inode(inode)) {
+               if (!im->params->pclusterblks_metabox)
+                       return false;
+               algid = cfg.c_mkfs_metabox_algid;
+       } else {
+               algid = inode->z_algorithmtype[0];
+       }
+       if (!z_erofs_compress_alg_enabled(im, algid))
                return false;
+
        if (cfg.c_compress_hints_file)
                return z_erofs_apply_compress_hints(im, inode);
        return true;
@@ -2049,7 +2058,6 @@ static int erofs_mkfs_begin_nondirectory(const struct 
erofs_mkfs_btctx *btctx,
                        return ret;
 
                if (inode->datasource != EROFS_INODE_DATA_SOURCE_REBUILD_BLOB &&
-                   inode->sbi->available_compr_algs &&
                    erofs_file_is_compressible(im, inode)) {
                        ctx.ictx = erofs_prepare_compressed_file(im, inode);
                        if (IS_ERR(ctx.ictx))
@@ -2378,8 +2386,7 @@ struct erofs_inode 
*erofs_mkfs_build_special_from_fd(struct erofs_importer *im,
                return ERR_PTR(ret);
        }
 
-       if (sbi->available_compr_algs &&
-           erofs_file_is_compressible(im, inode)) {
+       if (erofs_file_is_compressible(im, inode)) {
                ictx = erofs_prepare_compressed_file(im, inode);
                if (IS_ERR(ictx))
                        return ERR_CAST(ictx);
diff --git a/lib/liberofs_compress.h b/lib/liberofs_compress.h
index da6eb1a..32e8e03 100644
--- a/lib/liberofs_compress.h
+++ b/lib/liberofs_compress.h
@@ -14,6 +14,7 @@
 
 struct z_erofs_compress_ictx;
 
+bool z_erofs_compress_alg_enabled(const struct erofs_importer *im, u8 algid);
 void z_erofs_drop_inline_pcluster(struct erofs_inode *inode);
 void *erofs_prepare_compressed_file(struct erofs_importer *im,
                                    struct erofs_inode *inode);
-- 
2.53.0


Reply via email to