brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · ce6608c Raw
272 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Squashfs - a compressed read only filesystem for Linux4 *5 * Copyright (c) 20106 * Phillip Lougher <phillip@squashfs.org.uk>7 *8 * xattr.c9 */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		else140			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 support215 */216static const struct xattr_handler squashfs_xattr_user_handler = {217	.prefix	= XATTR_USER_PREFIX,218	.flags	= SQUASHFS_XATTR_USER,219	.get	= squashfs_xattr_handler_get220};221 222/*223 * Trusted namespace support224 */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_get235};236 237/*238 * Security namespace support239 */240static const struct xattr_handler squashfs_xattr_security_handler = {241	.prefix	= XATTR_SECURITY_PREFIX,242	.flags	= SQUASHFS_XATTR_SECURITY,243	.get	= squashfs_xattr_handler_get244};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 * const squashfs_xattr_handlers[] = {266	&squashfs_xattr_user_handler,267	&squashfs_xattr_trusted_handler,268	&squashfs_xattr_security_handler,269	NULL270};271 272