cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fragment.c (2631B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Squashfs - a compressed read only filesystem for Linux
      4 *
      5 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
      6 * Phillip Lougher <phillip@squashfs.org.uk>
      7 *
      8 * fragment.c
      9 */
     10
     11/*
     12 * This file implements code to handle compressed fragments (tail-end packed
     13 * datablocks).
     14 *
     15 * Regular files contain a fragment index which is mapped to a fragment
     16 * location on disk and compressed size using a fragment lookup table.
     17 * Like everything in Squashfs this fragment lookup table is itself stored
     18 * compressed into metadata blocks.  A second index table is used to locate
     19 * these.  This second index table for speed of access (and because it
     20 * is small) is read at mount time and cached in memory.
     21 */
     22
     23#include <linux/fs.h>
     24#include <linux/vfs.h>
     25#include <linux/slab.h>
     26
     27#include "squashfs_fs.h"
     28#include "squashfs_fs_sb.h"
     29#include "squashfs.h"
     30
     31/*
     32 * Look-up fragment using the fragment index table.  Return the on disk
     33 * location of the fragment and its compressed size
     34 */
     35int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
     36				u64 *fragment_block)
     37{
     38	struct squashfs_sb_info *msblk = sb->s_fs_info;
     39	int block, offset, size;
     40	struct squashfs_fragment_entry fragment_entry;
     41	u64 start_block;
     42
     43	if (fragment >= msblk->fragments)
     44		return -EIO;
     45	block = SQUASHFS_FRAGMENT_INDEX(fragment);
     46	offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
     47
     48	start_block = le64_to_cpu(msblk->fragment_index[block]);
     49
     50	size = squashfs_read_metadata(sb, &fragment_entry, &start_block,
     51					&offset, sizeof(fragment_entry));
     52	if (size < 0)
     53		return size;
     54
     55	*fragment_block = le64_to_cpu(fragment_entry.start_block);
     56	return squashfs_block_size(fragment_entry.size);
     57}
     58
     59
     60/*
     61 * Read the uncompressed fragment lookup table indexes off disk into memory
     62 */
     63__le64 *squashfs_read_fragment_index_table(struct super_block *sb,
     64	u64 fragment_table_start, u64 next_table, unsigned int fragments)
     65{
     66	unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments);
     67	__le64 *table;
     68
     69	/*
     70	 * Sanity check, length bytes should not extend into the next table -
     71	 * this check also traps instances where fragment_table_start is
     72	 * incorrectly larger than the next table start
     73	 */
     74	if (fragment_table_start + length > next_table)
     75		return ERR_PTR(-EINVAL);
     76
     77	table = squashfs_read_table(sb, fragment_table_start, length);
     78
     79	/*
     80	 * table[0] points to the first fragment table metadata block, this
     81	 * should be less than fragment_table_start
     82	 */
     83	if (!IS_ERR(table) && le64_to_cpu(table[0]) >= fragment_table_start) {
     84		kfree(table);
     85		return ERR_PTR(-EINVAL);
     86	}
     87
     88	return table;
     89}