root/fs/afs/xattr.c

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

DEFINITIONS

This source file includes following definitions.
  1. afs_listxattr
  2. afs_xattr_get_acl
  3. afs_xattr_set_acl
  4. afs_xattr_get_yfs
  5. afs_xattr_set_yfs
  6. afs_xattr_get_cell
  7. afs_xattr_get_fid
  8. afs_xattr_get_volume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* Extended attribute handling for AFS.  We use xattrs to get and set metadata
   3  * instead of providing pioctl().
   4  *
   5  * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
   6  * Written by David Howells (dhowells@redhat.com)
   7  */
   8 
   9 #include <linux/slab.h>
  10 #include <linux/fs.h>
  11 #include <linux/xattr.h>
  12 #include "internal.h"
  13 
  14 static const char afs_xattr_list[] =
  15         "afs.acl\0"
  16         "afs.cell\0"
  17         "afs.fid\0"
  18         "afs.volume\0"
  19         "afs.yfs.acl\0"
  20         "afs.yfs.acl_inherited\0"
  21         "afs.yfs.acl_num_cleaned\0"
  22         "afs.yfs.vol_acl";
  23 
  24 /*
  25  * Retrieve a list of the supported xattrs.
  26  */
  27 ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
  28 {
  29         if (size == 0)
  30                 return sizeof(afs_xattr_list);
  31         if (size < sizeof(afs_xattr_list))
  32                 return -ERANGE;
  33         memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
  34         return sizeof(afs_xattr_list);
  35 }
  36 
  37 /*
  38  * Get a file's ACL.
  39  */
  40 static int afs_xattr_get_acl(const struct xattr_handler *handler,
  41                              struct dentry *dentry,
  42                              struct inode *inode, const char *name,
  43                              void *buffer, size_t size)
  44 {
  45         struct afs_fs_cursor fc;
  46         struct afs_status_cb *scb;
  47         struct afs_vnode *vnode = AFS_FS_I(inode);
  48         struct afs_acl *acl = NULL;
  49         struct key *key;
  50         int ret = -ENOMEM;
  51 
  52         scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
  53         if (!scb)
  54                 goto error;
  55 
  56         key = afs_request_key(vnode->volume->cell);
  57         if (IS_ERR(key)) {
  58                 ret = PTR_ERR(key);
  59                 goto error_scb;
  60         }
  61 
  62         ret = -ERESTARTSYS;
  63         if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
  64                 afs_dataversion_t data_version = vnode->status.data_version;
  65 
  66                 while (afs_select_fileserver(&fc)) {
  67                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
  68                         acl = afs_fs_fetch_acl(&fc, scb);
  69                 }
  70 
  71                 afs_check_for_remote_deletion(&fc, fc.vnode);
  72                 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
  73                                         &data_version, scb);
  74                 ret = afs_end_vnode_operation(&fc);
  75         }
  76 
  77         if (ret == 0) {
  78                 ret = acl->size;
  79                 if (size > 0) {
  80                         if (acl->size <= size)
  81                                 memcpy(buffer, acl->data, acl->size);
  82                         else
  83                                 ret = -ERANGE;
  84                 }
  85                 kfree(acl);
  86         }
  87 
  88         key_put(key);
  89 error_scb:
  90         kfree(scb);
  91 error:
  92         return ret;
  93 }
  94 
  95 /*
  96  * Set a file's AFS3 ACL.
  97  */
  98 static int afs_xattr_set_acl(const struct xattr_handler *handler,
  99                              struct dentry *dentry,
 100                              struct inode *inode, const char *name,
 101                              const void *buffer, size_t size, int flags)
 102 {
 103         struct afs_fs_cursor fc;
 104         struct afs_status_cb *scb;
 105         struct afs_vnode *vnode = AFS_FS_I(inode);
 106         struct afs_acl *acl = NULL;
 107         struct key *key;
 108         int ret = -ENOMEM;
 109 
 110         if (flags == XATTR_CREATE)
 111                 return -EINVAL;
 112 
 113         scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
 114         if (!scb)
 115                 goto error;
 116 
 117         acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
 118         if (!acl)
 119                 goto error_scb;
 120 
 121         key = afs_request_key(vnode->volume->cell);
 122         if (IS_ERR(key)) {
 123                 ret = PTR_ERR(key);
 124                 goto error_acl;
 125         }
 126 
 127         acl->size = size;
 128         memcpy(acl->data, buffer, size);
 129 
 130         ret = -ERESTARTSYS;
 131         if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
 132                 afs_dataversion_t data_version = vnode->status.data_version;
 133 
 134                 while (afs_select_fileserver(&fc)) {
 135                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
 136                         afs_fs_store_acl(&fc, acl, scb);
 137                 }
 138 
 139                 afs_check_for_remote_deletion(&fc, fc.vnode);
 140                 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
 141                                         &data_version, scb);
 142                 ret = afs_end_vnode_operation(&fc);
 143         }
 144 
 145         key_put(key);
 146 error_acl:
 147         kfree(acl);
 148 error_scb:
 149         kfree(scb);
 150 error:
 151         return ret;
 152 }
 153 
 154 static const struct xattr_handler afs_xattr_afs_acl_handler = {
 155         .name   = "afs.acl",
 156         .get    = afs_xattr_get_acl,
 157         .set    = afs_xattr_set_acl,
 158 };
 159 
 160 /*
 161  * Get a file's YFS ACL.
 162  */
 163 static int afs_xattr_get_yfs(const struct xattr_handler *handler,
 164                              struct dentry *dentry,
 165                              struct inode *inode, const char *name,
 166                              void *buffer, size_t size)
 167 {
 168         struct afs_fs_cursor fc;
 169         struct afs_status_cb *scb;
 170         struct afs_vnode *vnode = AFS_FS_I(inode);
 171         struct yfs_acl *yacl = NULL;
 172         struct key *key;
 173         char buf[16], *data;
 174         int which = 0, dsize, ret = -ENOMEM;
 175 
 176         if (strcmp(name, "acl") == 0)
 177                 which = 0;
 178         else if (strcmp(name, "acl_inherited") == 0)
 179                 which = 1;
 180         else if (strcmp(name, "acl_num_cleaned") == 0)
 181                 which = 2;
 182         else if (strcmp(name, "vol_acl") == 0)
 183                 which = 3;
 184         else
 185                 return -EOPNOTSUPP;
 186 
 187         yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
 188         if (!yacl)
 189                 goto error;
 190 
 191         if (which == 0)
 192                 yacl->flags |= YFS_ACL_WANT_ACL;
 193         else if (which == 3)
 194                 yacl->flags |= YFS_ACL_WANT_VOL_ACL;
 195 
 196         scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
 197         if (!scb)
 198                 goto error_yacl;
 199 
 200         key = afs_request_key(vnode->volume->cell);
 201         if (IS_ERR(key)) {
 202                 ret = PTR_ERR(key);
 203                 goto error_scb;
 204         }
 205 
 206         ret = -ERESTARTSYS;
 207         if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
 208                 afs_dataversion_t data_version = vnode->status.data_version;
 209 
 210                 while (afs_select_fileserver(&fc)) {
 211                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
 212                         yfs_fs_fetch_opaque_acl(&fc, yacl, scb);
 213                 }
 214 
 215                 afs_check_for_remote_deletion(&fc, fc.vnode);
 216                 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
 217                                         &data_version, scb);
 218                 ret = afs_end_vnode_operation(&fc);
 219         }
 220 
 221         if (ret < 0)
 222                 goto error_key;
 223 
 224         switch (which) {
 225         case 0:
 226                 data = yacl->acl->data;
 227                 dsize = yacl->acl->size;
 228                 break;
 229         case 1:
 230                 data = buf;
 231                 dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
 232                 break;
 233         case 2:
 234                 data = buf;
 235                 dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
 236                 break;
 237         case 3:
 238                 data = yacl->vol_acl->data;
 239                 dsize = yacl->vol_acl->size;
 240                 break;
 241         default:
 242                 ret = -EOPNOTSUPP;
 243                 goto error_key;
 244         }
 245 
 246         ret = dsize;
 247         if (size > 0) {
 248                 if (dsize > size) {
 249                         ret = -ERANGE;
 250                         goto error_key;
 251                 }
 252                 memcpy(buffer, data, dsize);
 253         }
 254 
 255 error_key:
 256         key_put(key);
 257 error_scb:
 258         kfree(scb);
 259 error_yacl:
 260         yfs_free_opaque_acl(yacl);
 261 error:
 262         return ret;
 263 }
 264 
 265 /*
 266  * Set a file's YFS ACL.
 267  */
 268 static int afs_xattr_set_yfs(const struct xattr_handler *handler,
 269                              struct dentry *dentry,
 270                              struct inode *inode, const char *name,
 271                              const void *buffer, size_t size, int flags)
 272 {
 273         struct afs_fs_cursor fc;
 274         struct afs_status_cb *scb;
 275         struct afs_vnode *vnode = AFS_FS_I(inode);
 276         struct afs_acl *acl = NULL;
 277         struct key *key;
 278         int ret = -ENOMEM;
 279 
 280         if (flags == XATTR_CREATE ||
 281             strcmp(name, "acl") != 0)
 282                 return -EINVAL;
 283 
 284         scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
 285         if (!scb)
 286                 goto error;
 287 
 288         acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
 289         if (!acl)
 290                 goto error_scb;
 291 
 292         acl->size = size;
 293         memcpy(acl->data, buffer, size);
 294 
 295         key = afs_request_key(vnode->volume->cell);
 296         if (IS_ERR(key)) {
 297                 ret = PTR_ERR(key);
 298                 goto error_acl;
 299         }
 300 
 301         ret = -ERESTARTSYS;
 302         if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
 303                 afs_dataversion_t data_version = vnode->status.data_version;
 304 
 305                 while (afs_select_fileserver(&fc)) {
 306                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
 307                         yfs_fs_store_opaque_acl2(&fc, acl, scb);
 308                 }
 309 
 310                 afs_check_for_remote_deletion(&fc, fc.vnode);
 311                 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
 312                                         &data_version, scb);
 313                 ret = afs_end_vnode_operation(&fc);
 314         }
 315 
 316 error_acl:
 317         kfree(acl);
 318         key_put(key);
 319 error_scb:
 320         kfree(scb);
 321 error:
 322         return ret;
 323 }
 324 
 325 static const struct xattr_handler afs_xattr_yfs_handler = {
 326         .prefix = "afs.yfs.",
 327         .get    = afs_xattr_get_yfs,
 328         .set    = afs_xattr_set_yfs,
 329 };
 330 
 331 /*
 332  * Get the name of the cell on which a file resides.
 333  */
 334 static int afs_xattr_get_cell(const struct xattr_handler *handler,
 335                               struct dentry *dentry,
 336                               struct inode *inode, const char *name,
 337                               void *buffer, size_t size)
 338 {
 339         struct afs_vnode *vnode = AFS_FS_I(inode);
 340         struct afs_cell *cell = vnode->volume->cell;
 341         size_t namelen;
 342 
 343         namelen = cell->name_len;
 344         if (size == 0)
 345                 return namelen;
 346         if (namelen > size)
 347                 return -ERANGE;
 348         memcpy(buffer, cell->name, namelen);
 349         return namelen;
 350 }
 351 
 352 static const struct xattr_handler afs_xattr_afs_cell_handler = {
 353         .name   = "afs.cell",
 354         .get    = afs_xattr_get_cell,
 355 };
 356 
 357 /*
 358  * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
 359  * hex numbers separated by colons.
 360  */
 361 static int afs_xattr_get_fid(const struct xattr_handler *handler,
 362                              struct dentry *dentry,
 363                              struct inode *inode, const char *name,
 364                              void *buffer, size_t size)
 365 {
 366         struct afs_vnode *vnode = AFS_FS_I(inode);
 367         char text[16 + 1 + 24 + 1 + 8 + 1];
 368         size_t len;
 369 
 370         /* The volume ID is 64-bit, the vnode ID is 96-bit and the
 371          * uniquifier is 32-bit.
 372          */
 373         len = sprintf(text, "%llx:", vnode->fid.vid);
 374         if (vnode->fid.vnode_hi)
 375                 len += sprintf(text + len, "%x%016llx",
 376                                vnode->fid.vnode_hi, vnode->fid.vnode);
 377         else
 378                 len += sprintf(text + len, "%llx", vnode->fid.vnode);
 379         len += sprintf(text + len, ":%x", vnode->fid.unique);
 380 
 381         if (size == 0)
 382                 return len;
 383         if (len > size)
 384                 return -ERANGE;
 385         memcpy(buffer, text, len);
 386         return len;
 387 }
 388 
 389 static const struct xattr_handler afs_xattr_afs_fid_handler = {
 390         .name   = "afs.fid",
 391         .get    = afs_xattr_get_fid,
 392 };
 393 
 394 /*
 395  * Get the name of the volume on which a file resides.
 396  */
 397 static int afs_xattr_get_volume(const struct xattr_handler *handler,
 398                               struct dentry *dentry,
 399                               struct inode *inode, const char *name,
 400                               void *buffer, size_t size)
 401 {
 402         struct afs_vnode *vnode = AFS_FS_I(inode);
 403         const char *volname = vnode->volume->name;
 404         size_t namelen;
 405 
 406         namelen = strlen(volname);
 407         if (size == 0)
 408                 return namelen;
 409         if (namelen > size)
 410                 return -ERANGE;
 411         memcpy(buffer, volname, namelen);
 412         return namelen;
 413 }
 414 
 415 static const struct xattr_handler afs_xattr_afs_volume_handler = {
 416         .name   = "afs.volume",
 417         .get    = afs_xattr_get_volume,
 418 };
 419 
 420 const struct xattr_handler *afs_xattr_handlers[] = {
 421         &afs_xattr_afs_acl_handler,
 422         &afs_xattr_afs_cell_handler,
 423         &afs_xattr_afs_fid_handler,
 424         &afs_xattr_afs_volume_handler,
 425         &afs_xattr_yfs_handler,         /* afs.yfs. prefix */
 426         NULL
 427 };

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