kernel/module/decompress.c

Source file repositories/reference/linux-study-clean/kernel/module/decompress.c

File Facts

System
Linux kernel
Corpus path
kernel/module/decompress.c
Extension
.c
Size
7958 bytes
Lines
371
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(page)) {
			retval = PTR_ERR(page);
			goto out_inflate_end;
		}

		s.next_out = kmap_local_page(page);
		s.avail_out = PAGE_SIZE;
		rc = zlib_inflate(&s, 0);
		kunmap_local(s.next_out);

		new_size += PAGE_SIZE - s.avail_out;
	} while (rc == Z_OK);

	if (rc != Z_STREAM_END) {
		pr_err("decompression failed with status %d\n", rc);
		retval = -EINVAL;
		goto out_inflate_end;
	}

	retval = new_size;

out_inflate_end:
	zlib_inflateEnd(&s);
out:
	kvfree(s.workspace);
	return retval;
}
#elif defined(CONFIG_MODULE_COMPRESS_XZ)
#include <linux/xz.h>
#define MODULE_COMPRESSION	xz
#define MODULE_DECOMPRESS_FN	module_xz_decompress

static ssize_t module_xz_decompress(struct load_info *info,
				    const void *buf, size_t size)
{
	static const u8 signature[] = { 0xfd, '7', 'z', 'X', 'Z', 0 };
	struct xz_dec *xz_dec;
	struct xz_buf xz_buf;
	enum xz_ret xz_ret;
	size_t new_size = 0;
	ssize_t retval;

	if (size < sizeof(signature) ||
	    memcmp(buf, signature, sizeof(signature))) {
		pr_err("not an xz compressed module\n");
		return -EINVAL;
	}

	xz_dec = xz_dec_init(XZ_DYNALLOC, (u32)-1);
	if (!xz_dec)
		return -ENOMEM;

	xz_buf.in_size = size;
	xz_buf.in = buf;
	xz_buf.in_pos = 0;

	do {
		struct page *page = module_get_next_page(info);

		if (IS_ERR(page)) {
			retval = PTR_ERR(page);
			goto out;
		}

		xz_buf.out = kmap_local_page(page);
		xz_buf.out_pos = 0;
		xz_buf.out_size = PAGE_SIZE;
		xz_ret = xz_dec_run(xz_dec, &xz_buf);
		kunmap_local(xz_buf.out);

		new_size += xz_buf.out_pos;
	} while (xz_buf.out_pos == PAGE_SIZE && xz_ret == XZ_OK);

	if (xz_ret != XZ_STREAM_END) {
		pr_err("decompression failed with status %d\n", xz_ret);
		retval = -EINVAL;
		goto out;
	}

	retval = new_size;

 out:
	xz_dec_end(xz_dec);
	return retval;
}
#elif defined(CONFIG_MODULE_COMPRESS_ZSTD)
#include <linux/zstd.h>
#define MODULE_COMPRESSION	zstd
#define MODULE_DECOMPRESS_FN	module_zstd_decompress

Annotation

Implementation Notes