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

symlink.c (3138B)


      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 * symlink.c
      9 */
     10
     11/*
     12 * This file implements code to handle symbolic links.
     13 *
     14 * The data contents of symbolic links are stored inside the symbolic
     15 * link inode within the inode table.  This allows the normally small symbolic
     16 * link to be compressed as part of the inode table, achieving much greater
     17 * compression than if the symbolic link was compressed individually.
     18 */
     19
     20#include <linux/fs.h>
     21#include <linux/vfs.h>
     22#include <linux/kernel.h>
     23#include <linux/string.h>
     24#include <linux/pagemap.h>
     25#include <linux/xattr.h>
     26
     27#include "squashfs_fs.h"
     28#include "squashfs_fs_sb.h"
     29#include "squashfs_fs_i.h"
     30#include "squashfs.h"
     31#include "xattr.h"
     32
     33static int squashfs_symlink_read_folio(struct file *file, struct folio *folio)
     34{
     35	struct page *page = &folio->page;
     36	struct inode *inode = page->mapping->host;
     37	struct super_block *sb = inode->i_sb;
     38	struct squashfs_sb_info *msblk = sb->s_fs_info;
     39	int index = page->index << PAGE_SHIFT;
     40	u64 block = squashfs_i(inode)->start;
     41	int offset = squashfs_i(inode)->offset;
     42	int length = min_t(int, i_size_read(inode) - index, PAGE_SIZE);
     43	int bytes, copied;
     44	void *pageaddr;
     45	struct squashfs_cache_entry *entry;
     46
     47	TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
     48			"%llx, offset %x\n", page->index, block, offset);
     49
     50	/*
     51	 * Skip index bytes into symlink metadata.
     52	 */
     53	if (index) {
     54		bytes = squashfs_read_metadata(sb, NULL, &block, &offset,
     55								index);
     56		if (bytes < 0) {
     57			ERROR("Unable to read symlink [%llx:%x]\n",
     58				squashfs_i(inode)->start,
     59				squashfs_i(inode)->offset);
     60			goto error_out;
     61		}
     62	}
     63
     64	/*
     65	 * Read length bytes from symlink metadata.  Squashfs_read_metadata
     66	 * is not used here because it can sleep and we want to use
     67	 * kmap_atomic to map the page.  Instead call the underlying
     68	 * squashfs_cache_get routine.  As length bytes may overlap metadata
     69	 * blocks, we may need to call squashfs_cache_get multiple times.
     70	 */
     71	for (bytes = 0; bytes < length; offset = 0, bytes += copied) {
     72		entry = squashfs_cache_get(sb, msblk->block_cache, block, 0);
     73		if (entry->error) {
     74			ERROR("Unable to read symlink [%llx:%x]\n",
     75				squashfs_i(inode)->start,
     76				squashfs_i(inode)->offset);
     77			squashfs_cache_put(entry);
     78			goto error_out;
     79		}
     80
     81		pageaddr = kmap_atomic(page);
     82		copied = squashfs_copy_data(pageaddr + bytes, entry, offset,
     83								length - bytes);
     84		if (copied == length - bytes)
     85			memset(pageaddr + length, 0, PAGE_SIZE - length);
     86		else
     87			block = entry->next_index;
     88		kunmap_atomic(pageaddr);
     89		squashfs_cache_put(entry);
     90	}
     91
     92	flush_dcache_page(page);
     93	SetPageUptodate(page);
     94	unlock_page(page);
     95	return 0;
     96
     97error_out:
     98	SetPageError(page);
     99	unlock_page(page);
    100	return 0;
    101}
    102
    103
    104const struct address_space_operations squashfs_symlink_aops = {
    105	.read_folio = squashfs_symlink_read_folio
    106};
    107
    108const struct inode_operations squashfs_symlink_inode_ops = {
    109	.get_link = page_get_link,
    110	.listxattr = squashfs_listxattr
    111};
    112