^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Squashfs - a compressed read only filesystem for Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Phillip Lougher <phillip@squashfs.org.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * decompressor.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/buffer_head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "squashfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "squashfs_fs_sb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "decompressor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "squashfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "page_actor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * This file (and decompressor.h) implements a decompressor framework for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Squashfs, allowing multiple decompressors to be easily supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifndef CONFIG_SQUASHFS_LZ4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static const struct squashfs_decompressor squashfs_lz4_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) NULL, NULL, NULL, NULL, LZ4_COMPRESSION, "lz4", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #ifndef CONFIG_SQUASHFS_LZO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static const struct squashfs_decompressor squashfs_lzo_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifndef CONFIG_SQUASHFS_XZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct squashfs_decompressor squashfs_xz_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifndef CONFIG_SQUASHFS_ZLIB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const struct squashfs_decompressor squashfs_zlib_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "zlib", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #ifndef CONFIG_SQUASHFS_ZSTD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static const struct squashfs_decompressor squashfs_zstd_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) NULL, NULL, NULL, NULL, ZSTD_COMPRESSION, "zstd", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) NULL, NULL, NULL, NULL, 0, "unknown", 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static const struct squashfs_decompressor *decompressor[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) &squashfs_zlib_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) &squashfs_lz4_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) &squashfs_lzo_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) &squashfs_xz_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) &squashfs_lzma_unsupported_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) &squashfs_zstd_comp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) &squashfs_unknown_comp_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) for (i = 0; decompressor[i]->id; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (id == decompressor[i]->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return decompressor[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void *get_comp_opts(struct super_block *sb, unsigned short flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct squashfs_sb_info *msblk = sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) void *buffer = NULL, *comp_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct squashfs_page_actor *actor = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Read decompressor specific options from file system if present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (SQUASHFS_COMP_OPTS(flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) comp_opts = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) actor = squashfs_page_actor_init(&buffer, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (actor == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) comp_opts = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) length = squashfs_read_data(sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) sizeof(struct squashfs_super_block), 0, NULL, actor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (length < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) comp_opts = ERR_PTR(length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) comp_opts = squashfs_comp_opts(msblk, buffer, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) kfree(actor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return comp_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void *squashfs_decompressor_setup(struct super_block *sb, unsigned short flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct squashfs_sb_info *msblk = sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) void *stream, *comp_opts = get_comp_opts(sb, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (IS_ERR(comp_opts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return comp_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) stream = squashfs_decompressor_create(msblk, comp_opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (IS_ERR(stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) kfree(comp_opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }