root/fs/squashfs/xattr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. squashfs_listxattr
  2. squashfs_xattr_get
  3. squashfs_xattr_handler_get
  4. squashfs_trusted_xattr_handler_list
  5. squashfs_xattr_handler

   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 
  24 static const struct xattr_handler *squashfs_xattr_handler(int);
  25 
  26 ssize_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 
 100 failed:
 101         return err;
 102 }
 103 
 104 
 105 static 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 
 197 failed:
 198         kfree(target);
 199         return err;
 200 }
 201 
 202 
 203 static 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  */
 216 static 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  */
 225 static bool squashfs_trusted_xattr_handler_list(struct dentry *d)
 226 {
 227         return capable(CAP_SYS_ADMIN);
 228 }
 229 
 230 static 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  */
 240 static 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 
 246 static 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 
 265 const 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 

/* [<][>][^][v][top][bottom][index][help] */