--- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -1,7 +1,8 @@ config SQUASHFS tristate "SquashFS 4.0 - Squashed file system support" depends on BLOCK - select ZLIB_INFLATE + select CRYPTO + select CRYPTO_ZLIB help Saying Y here includes support for SquashFS 4.0 (a Compressed Read-Only File System). Squashfs is a highly compressed read-only --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -32,7 +32,8 @@ #include #include #include -#include + +#include #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -153,7 +154,8 @@ int squashfs_read_data(struct super_bloc } if (compressed) { - int zlib_err = 0, zlib_init = 0; + int res = 0, decomp_init = 0; + struct comp_request req; /* * Uncompress block. @@ -161,12 +163,13 @@ int squashfs_read_data(struct super_bloc mutex_lock(&msblk->read_data_mutex); - msblk->stream.avail_out = 0; - msblk->stream.avail_in = 0; + req.avail_out = 0; + req.avail_in = 0; bytes = length; + length = 0; do { - if (msblk->stream.avail_in == 0 && k < b) { + if (req.avail_in == 0 && k < b) { avail = min(bytes, msblk->devblksize - offset); bytes -= avail; wait_on_buffer(bh[k]); @@ -179,45 +182,47 @@ int squashfs_read_data(struct super_bloc continue; } - msblk->stream.next_in = bh[k]->b_data + offset; - msblk->stream.avail_in = avail; + req.next_in = bh[k]->b_data + offset; + req.avail_in = avail; offset = 0; } - if (msblk->stream.avail_out == 0 && page < pages) { - msblk->stream.next_out = buffer[page++]; - msblk->stream.avail_out = PAGE_CACHE_SIZE; + if (req.avail_out == 0 && page < pages) { + req.next_out = buffer[page++]; + req.avail_out = PAGE_CACHE_SIZE; } - if (!zlib_init) { - zlib_err = zlib_inflateInit(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflateInit returned" - " unexpected result 0x%x," - " srclength %d\n", zlib_err, - srclength); + if (!decomp_init) { + res = crypto_decompress_init(msblk->tfm); + if (res) { + ERROR("crypto_decompress_init " + "returned %d, srclength %d\n", + res, srclength); goto release_mutex; } - zlib_init = 1; + decomp_init = 1; } - zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); + res = crypto_decompress_update(msblk->tfm, &req); + if (res < 0) { + ERROR("crypto_decompress_update returned %d, " + "data probably corrupt\n", res); + goto release_mutex; + } + length += res; - if (msblk->stream.avail_in == 0 && k < b) + if (req.avail_in == 0 && k < b) put_bh(bh[k++]); - } while (zlib_err == Z_OK); + } while (bytes || res); - if (zlib_err != Z_STREAM_END) { - ERROR("zlib_inflate error, data probably corrupt\n"); + res = crypto_decompress_final(msblk->tfm, &req); + if (res < 0) { + ERROR("crypto_decompress_final returned %d, data " + "probably corrupt\n", res); goto release_mutex; } + length += res; - zlib_err = zlib_inflateEnd(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflate error, data probably corrupt\n"); - goto release_mutex; - } - length = msblk->stream.total_out; mutex_unlock(&msblk->read_data_mutex); } else { /* --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h @@ -64,7 +64,7 @@ struct squashfs_sb_info { struct mutex read_data_mutex; struct mutex meta_index_mutex; struct meta_index *meta_index; - z_stream stream; + struct crypto_pcomp *tfm; __le64 *inode_lookup_table; u64 inode_table; u64 directory_table; --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -37,11 +37,19 @@ #include #include +#include + +#include + #include "squashfs_fs.h" #include "squashfs_fs_sb.h" #include "squashfs_fs_i.h" #include "squashfs.h" + +#define SQUASHFS_CRYPTO_ALG "zlib" + + static struct file_system_type squashfs_fs_type; static struct super_operations squashfs_super_ops; @@ -75,6 +83,16 @@ static int squashfs_fill_super(struct su unsigned short flags; unsigned int fragments; u64 lookup_table_start; + struct { + struct nlattr nla; + int val; + } params = { + .nla = { + .nla_len = nla_attr_size(sizeof(int)), + .nla_type = ZLIB_DECOMP_WINDOWBITS, + }, + .val = DEF_WBITS, + }; int err; TRACE("Entered squashfs_fill_superblock\n"); @@ -86,16 +104,25 @@ static int squashfs_fill_super(struct su } msblk = sb->s_fs_info; - msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), - GFP_KERNEL); - if (msblk->stream.workspace == NULL) { - ERROR("Failed to allocate zlib workspace\n"); + msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(msblk->tfm)) { + ERROR("Failed to load %s crypto module\n", + SQUASHFS_CRYPTO_ALG); + err = PTR_ERR(msblk->tfm); + goto failed_pcomp; + } + + err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); + if (err) { + ERROR("Failed to set up decompression parameters\n"); goto failure; } sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); if (sblk == NULL) { ERROR("Failed to allocate squashfs_super_block\n"); + err = -ENOMEM; goto failure; } @@ -294,17 +321,18 @@ failed_mount: kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->id_table); - kfree(msblk->stream.workspace); + crypto_free_pcomp(msblk->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; kfree(sblk); return err; failure: - kfree(msblk->stream.workspace); + crypto_free_pcomp(msblk->tfm); +failed_pcomp: kfree(sb->s_fs_info); sb->s_fs_info = NULL; - return -ENOMEM; + return err; } @@ -346,7 +374,7 @@ static void squashfs_put_super(struct su kfree(sbi->id_table); kfree(sbi->fragment_index); kfree(sbi->meta_index); - kfree(sbi->stream.workspace); + crypto_free_pcomp(sbi->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; }