mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			235 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- 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 <linux/mutex.h>
 | |
|  #include <linux/string.h>
 | |
|  #include <linux/buffer_head.h>
 | |
| -#include <linux/zlib.h>
 | |
| +
 | |
| +#include <crypto/compress.h>
 | |
|  
 | |
|  #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
 | |
| @@ -38,11 +38,19 @@
 | |
|  #include <linux/zlib.h>
 | |
|  #include <linux/magic.h>
 | |
|  
 | |
| +#include <crypto/compress.h>
 | |
| +
 | |
| +#include <net/netlink.h>
 | |
| +
 | |
|  #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;
 | |
|  
 | |
| @@ -76,6 +84,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");
 | |
| @@ -87,16 +105,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;
 | |
|  	}
 | |
|  
 | |
| @@ -295,17 +322,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;
 | |
|  }
 | |
|  
 | |
|  
 | |
| @@ -349,7 +377,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;
 | |
|  	}
 |