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

xattr.c (6862B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Squashfs - a compressed read only filesystem for Linux
      4 *
      5 * Copyright (c) 2010
      6 * Phillip Lougher <phillip@squashfs.org.uk>
      7 *
      8 * xattr.c
      9 */
     10
     11#include <linux/init.h>
     12#include <linux/module.h>
     13#include <linux/string.h>
     14#include <linux/fs.h>
     15#include <linux/vfs.h>
     16#include <linux/xattr.h>
     17#include <linux/slab.h>
     18
     19#include "squashfs_fs.h"
     20#include "squashfs_fs_sb.h"
     21#include "squashfs_fs_i.h"
     22#include "squashfs.h"
     23
     24static const struct xattr_handler *squashfs_xattr_handler(int);
     25
     26ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
     27	size_t buffer_size)
     28{
     29	struct inode *inode = d_inode(d);
     30	struct super_block *sb = inode->i_sb;
     31	struct squashfs_sb_info *msblk = sb->s_fs_info;
     32	u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr)
     33						 + msblk->xattr_table;
     34	int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr);
     35	int count = squashfs_i(inode)->xattr_count;
     36	size_t rest = buffer_size;
     37	int err;
     38
     39	/* check that the file system has xattrs */
     40	if (msblk->xattr_id_table == NULL)
     41		return -EOPNOTSUPP;
     42
     43	/* loop reading each xattr name */
     44	while (count--) {
     45		struct squashfs_xattr_entry entry;
     46		struct squashfs_xattr_val val;
     47		const struct xattr_handler *handler;
     48		int name_size;
     49
     50		err = squashfs_read_metadata(sb, &entry, &start, &offset,
     51							sizeof(entry));
     52		if (err < 0)
     53			goto failed;
     54
     55		name_size = le16_to_cpu(entry.size);
     56		handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
     57		if (handler && (!handler->list || handler->list(d))) {
     58			const char *prefix = handler->prefix ?: handler->name;
     59			size_t prefix_size = strlen(prefix);
     60
     61			if (buffer) {
     62				if (prefix_size + name_size + 1 > rest) {
     63					err = -ERANGE;
     64					goto failed;
     65				}
     66				memcpy(buffer, prefix, prefix_size);
     67				buffer += prefix_size;
     68			}
     69			err = squashfs_read_metadata(sb, buffer, &start,
     70				&offset, name_size);
     71			if (err < 0)
     72				goto failed;
     73			if (buffer) {
     74				buffer[name_size] = '\0';
     75				buffer += name_size + 1;
     76			}
     77			rest -= prefix_size + name_size + 1;
     78		} else  {
     79			/* no handler or insuffficient privileges, so skip */
     80			err = squashfs_read_metadata(sb, NULL, &start,
     81				&offset, name_size);
     82			if (err < 0)
     83				goto failed;
     84		}
     85
     86
     87		/* skip remaining xattr entry */
     88		err = squashfs_read_metadata(sb, &val, &start, &offset,
     89						sizeof(val));
     90		if (err < 0)
     91			goto failed;
     92
     93		err = squashfs_read_metadata(sb, NULL, &start, &offset,
     94						le32_to_cpu(val.vsize));
     95		if (err < 0)
     96			goto failed;
     97	}
     98	err = buffer_size - rest;
     99
    100failed:
    101	return err;
    102}
    103
    104
    105static int squashfs_xattr_get(struct inode *inode, int name_index,
    106	const char *name, void *buffer, size_t buffer_size)
    107{
    108	struct super_block *sb = inode->i_sb;
    109	struct squashfs_sb_info *msblk = sb->s_fs_info;
    110	u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr)
    111						 + msblk->xattr_table;
    112	int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr);
    113	int count = squashfs_i(inode)->xattr_count;
    114	int name_len = strlen(name);
    115	int err, vsize;
    116	char *target = kmalloc(name_len, GFP_KERNEL);
    117
    118	if (target == NULL)
    119		return  -ENOMEM;
    120
    121	/* loop reading each xattr name */
    122	for (; count; count--) {
    123		struct squashfs_xattr_entry entry;
    124		struct squashfs_xattr_val val;
    125		int type, prefix, name_size;
    126
    127		err = squashfs_read_metadata(sb, &entry, &start, &offset,
    128							sizeof(entry));
    129		if (err < 0)
    130			goto failed;
    131
    132		name_size = le16_to_cpu(entry.size);
    133		type = le16_to_cpu(entry.type);
    134		prefix = type & SQUASHFS_XATTR_PREFIX_MASK;
    135
    136		if (prefix == name_index && name_size == name_len)
    137			err = squashfs_read_metadata(sb, target, &start,
    138						&offset, name_size);
    139		else
    140			err = squashfs_read_metadata(sb, NULL, &start,
    141						&offset, name_size);
    142		if (err < 0)
    143			goto failed;
    144
    145		if (prefix == name_index && name_size == name_len &&
    146					strncmp(target, name, name_size) == 0) {
    147			/* found xattr */
    148			if (type & SQUASHFS_XATTR_VALUE_OOL) {
    149				__le64 xattr_val;
    150				u64 xattr;
    151				/* val is a reference to the real location */
    152				err = squashfs_read_metadata(sb, &val, &start,
    153						&offset, sizeof(val));
    154				if (err < 0)
    155					goto failed;
    156				err = squashfs_read_metadata(sb, &xattr_val,
    157					&start, &offset, sizeof(xattr_val));
    158				if (err < 0)
    159					goto failed;
    160				xattr = le64_to_cpu(xattr_val);
    161				start = SQUASHFS_XATTR_BLK(xattr) +
    162							msblk->xattr_table;
    163				offset = SQUASHFS_XATTR_OFFSET(xattr);
    164			}
    165			/* read xattr value */
    166			err = squashfs_read_metadata(sb, &val, &start, &offset,
    167							sizeof(val));
    168			if (err < 0)
    169				goto failed;
    170
    171			vsize = le32_to_cpu(val.vsize);
    172			if (buffer) {
    173				if (vsize > buffer_size) {
    174					err = -ERANGE;
    175					goto failed;
    176				}
    177				err = squashfs_read_metadata(sb, buffer, &start,
    178					 &offset, vsize);
    179				if (err < 0)
    180					goto failed;
    181			}
    182			break;
    183		}
    184
    185		/* no match, skip remaining xattr entry */
    186		err = squashfs_read_metadata(sb, &val, &start, &offset,
    187							sizeof(val));
    188		if (err < 0)
    189			goto failed;
    190		err = squashfs_read_metadata(sb, NULL, &start, &offset,
    191						le32_to_cpu(val.vsize));
    192		if (err < 0)
    193			goto failed;
    194	}
    195	err = count ? vsize : -ENODATA;
    196
    197failed:
    198	kfree(target);
    199	return err;
    200}
    201
    202
    203static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
    204				      struct dentry *unused,
    205				      struct inode *inode,
    206				      const char *name,
    207				      void *buffer, size_t size)
    208{
    209	return squashfs_xattr_get(inode, handler->flags, name,
    210		buffer, size);
    211}
    212
    213/*
    214 * User namespace support
    215 */
    216static const struct xattr_handler squashfs_xattr_user_handler = {
    217	.prefix	= XATTR_USER_PREFIX,
    218	.flags	= SQUASHFS_XATTR_USER,
    219	.get	= squashfs_xattr_handler_get
    220};
    221
    222/*
    223 * Trusted namespace support
    224 */
    225static bool squashfs_trusted_xattr_handler_list(struct dentry *d)
    226{
    227	return capable(CAP_SYS_ADMIN);
    228}
    229
    230static const struct xattr_handler squashfs_xattr_trusted_handler = {
    231	.prefix	= XATTR_TRUSTED_PREFIX,
    232	.flags	= SQUASHFS_XATTR_TRUSTED,
    233	.list	= squashfs_trusted_xattr_handler_list,
    234	.get	= squashfs_xattr_handler_get
    235};
    236
    237/*
    238 * Security namespace support
    239 */
    240static const struct xattr_handler squashfs_xattr_security_handler = {
    241	.prefix	= XATTR_SECURITY_PREFIX,
    242	.flags	= SQUASHFS_XATTR_SECURITY,
    243	.get	= squashfs_xattr_handler_get
    244};
    245
    246static const struct xattr_handler *squashfs_xattr_handler(int type)
    247{
    248	if (type & ~(SQUASHFS_XATTR_PREFIX_MASK | SQUASHFS_XATTR_VALUE_OOL))
    249		/* ignore unrecognised type */
    250		return NULL;
    251
    252	switch (type & SQUASHFS_XATTR_PREFIX_MASK) {
    253	case SQUASHFS_XATTR_USER:
    254		return &squashfs_xattr_user_handler;
    255	case SQUASHFS_XATTR_TRUSTED:
    256		return &squashfs_xattr_trusted_handler;
    257	case SQUASHFS_XATTR_SECURITY:
    258		return &squashfs_xattr_security_handler;
    259	default:
    260		/* ignore unrecognised type */
    261		return NULL;
    262	}
    263}
    264
    265const struct xattr_handler *squashfs_xattr_handlers[] = {
    266	&squashfs_xattr_user_handler,
    267	&squashfs_xattr_trusted_handler,
    268	&squashfs_xattr_security_handler,
    269	NULL
    270};
    271