Line data Source code
1 : #include <linux/zutil.h> 2 : #include <linux/errno.h> 3 : #include <linux/slab.h> 4 : #include <linux/vmalloc.h> 5 : 6 : /* Utility function: initialize zlib, unpack binary blob, clean up zlib, 7 : * return len or negative error code. 8 : */ 9 0 : int zlib_inflate_blob(void *gunzip_buf, unsigned int sz, 10 : const void *buf, unsigned int len) 11 : { 12 0 : const u8 *zbuf = buf; 13 0 : struct z_stream_s *strm; 14 0 : int rc; 15 : 16 0 : rc = -ENOMEM; 17 0 : strm = kmalloc(sizeof(*strm), GFP_KERNEL); 18 0 : if (strm == NULL) 19 0 : goto gunzip_nomem1; 20 0 : strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); 21 0 : if (strm->workspace == NULL) 22 0 : goto gunzip_nomem2; 23 : 24 : /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename) 25 : * expected to be stripped from input 26 : */ 27 0 : strm->next_in = zbuf; 28 0 : strm->avail_in = len; 29 0 : strm->next_out = gunzip_buf; 30 0 : strm->avail_out = sz; 31 : 32 0 : rc = zlib_inflateInit2(strm, -MAX_WBITS); 33 0 : if (rc == Z_OK) { 34 0 : rc = zlib_inflate(strm, Z_FINISH); 35 : /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ 36 0 : if (rc == Z_STREAM_END) 37 0 : rc = sz - strm->avail_out; 38 : else 39 : rc = -EINVAL; 40 0 : zlib_inflateEnd(strm); 41 : } else 42 : rc = -EINVAL; 43 : 44 0 : kfree(strm->workspace); 45 0 : gunzip_nomem2: 46 0 : kfree(strm); 47 0 : gunzip_nomem1: 48 0 : return rc; /* returns Z_OK (0) if successful */ 49 : }