root/fs/orangefs/xattr.c

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

DEFINITIONS

This source file includes following definitions.
  1. is_reserved_key
  2. convert_to_internal_xattr_flags
  3. xattr_key
  4. find_cached_xattr
  5. orangefs_inode_getxattr
  6. orangefs_inode_removexattr
  7. orangefs_inode_setxattr
  8. orangefs_listxattr
  9. orangefs_xattr_set_default
  10. orangefs_xattr_get_default

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * (C) 2001 Clemson University and The University of Chicago
   4  * Copyright 2018 Omnibond Systems, L.L.C.
   5  *
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 /*
  10  *  Linux VFS extended attribute operations.
  11  */
  12 
  13 #include "protocol.h"
  14 #include "orangefs-kernel.h"
  15 #include "orangefs-bufmap.h"
  16 #include <linux/posix_acl_xattr.h>
  17 #include <linux/xattr.h>
  18 #include <linux/hashtable.h>
  19 
  20 #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
  21 #define SYSTEM_ORANGEFS_KEY_LEN 13
  22 
  23 /*
  24  * this function returns
  25  *   0 if the key corresponding to name is not meant to be printed as part
  26  *     of a listxattr.
  27  *   1 if the key corresponding to name is meant to be returned as part of
  28  *     a listxattr.
  29  * The ones that start SYSTEM_ORANGEFS_KEY are the ones to avoid printing.
  30  */
  31 static int is_reserved_key(const char *key, size_t size)
  32 {
  33 
  34         if (size < SYSTEM_ORANGEFS_KEY_LEN)
  35                 return 1;
  36 
  37         return strncmp(key, SYSTEM_ORANGEFS_KEY, SYSTEM_ORANGEFS_KEY_LEN) ?  1 : 0;
  38 }
  39 
  40 static inline int convert_to_internal_xattr_flags(int setxattr_flags)
  41 {
  42         int internal_flag = 0;
  43 
  44         if (setxattr_flags & XATTR_REPLACE) {
  45                 /* Attribute must exist! */
  46                 internal_flag = ORANGEFS_XATTR_REPLACE;
  47         } else if (setxattr_flags & XATTR_CREATE) {
  48                 /* Attribute must not exist */
  49                 internal_flag = ORANGEFS_XATTR_CREATE;
  50         }
  51         return internal_flag;
  52 }
  53 
  54 static unsigned int xattr_key(const char *key)
  55 {
  56         unsigned int i = 0;
  57         while (key)
  58                 i += *key++;
  59         return i % 16;
  60 }
  61 
  62 static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
  63     const char *key)
  64 {
  65         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
  66         struct orangefs_cached_xattr *cx;
  67         struct hlist_head *h;
  68         struct hlist_node *tmp;
  69         h = &orangefs_inode->xattr_cache[xattr_key(key)];
  70         if (hlist_empty(h))
  71                 return NULL;
  72         hlist_for_each_entry_safe(cx, tmp, h, node) {
  73 /*              if (!time_before(jiffies, cx->timeout)) {
  74                         hlist_del(&cx->node);
  75                         kfree(cx);
  76                         continue;
  77                 }*/
  78                 if (!strcmp(cx->key, key))
  79                         return cx;
  80         }
  81         return NULL;
  82 }
  83 
  84 /*
  85  * Tries to get a specified key's attributes of a given
  86  * file into a user-specified buffer. Note that the getxattr
  87  * interface allows for the users to probe the size of an
  88  * extended attribute by passing in a value of 0 to size.
  89  * Thus our return value is always the size of the attribute
  90  * unless the key does not exist for the file and/or if
  91  * there were errors in fetching the attribute value.
  92  */
  93 ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
  94                                 void *buffer, size_t size)
  95 {
  96         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
  97         struct orangefs_kernel_op_s *new_op = NULL;
  98         struct orangefs_cached_xattr *cx;
  99         ssize_t ret = -ENOMEM;
 100         ssize_t length = 0;
 101         int fsuid;
 102         int fsgid;
 103 
 104         gossip_debug(GOSSIP_XATTR_DEBUG,
 105                      "%s: name %s, buffer_size %zd\n",
 106                      __func__, name, size);
 107 
 108         if (S_ISLNK(inode->i_mode))
 109                 return -EOPNOTSUPP;
 110 
 111         if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
 112                 return -EINVAL;
 113 
 114         fsuid = from_kuid(&init_user_ns, current_fsuid());
 115         fsgid = from_kgid(&init_user_ns, current_fsgid());
 116 
 117         gossip_debug(GOSSIP_XATTR_DEBUG,
 118                      "getxattr on inode %pU, name %s "
 119                      "(uid %o, gid %o)\n",
 120                      get_khandle_from_ino(inode),
 121                      name,
 122                      fsuid,
 123                      fsgid);
 124 
 125         down_read(&orangefs_inode->xattr_sem);
 126 
 127         cx = find_cached_xattr(inode, name);
 128         if (cx && time_before(jiffies, cx->timeout)) {
 129                 if (cx->length == -1) {
 130                         ret = -ENODATA;
 131                         goto out_unlock;
 132                 } else {
 133                         if (size == 0) {
 134                                 ret = cx->length;
 135                                 goto out_unlock;
 136                         }
 137                         if (cx->length > size) {
 138                                 ret = -ERANGE;
 139                                 goto out_unlock;
 140                         }
 141                         memcpy(buffer, cx->val, cx->length);
 142                         memset(buffer + cx->length, 0, size - cx->length);
 143                         ret = cx->length;
 144                         goto out_unlock;
 145                 }
 146         }
 147 
 148         new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
 149         if (!new_op)
 150                 goto out_unlock;
 151 
 152         new_op->upcall.req.getxattr.refn = orangefs_inode->refn;
 153         strcpy(new_op->upcall.req.getxattr.key, name);
 154 
 155         /*
 156          * NOTE: Although keys are meant to be NULL terminated textual
 157          * strings, I am going to explicitly pass the length just in case
 158          * we change this later on...
 159          */
 160         new_op->upcall.req.getxattr.key_sz = strlen(name) + 1;
 161 
 162         ret = service_operation(new_op, "orangefs_inode_getxattr",
 163                                 get_interruptible_flag(inode));
 164         if (ret != 0) {
 165                 if (ret == -ENOENT) {
 166                         ret = -ENODATA;
 167                         gossip_debug(GOSSIP_XATTR_DEBUG,
 168                                      "orangefs_inode_getxattr: inode %pU key %s"
 169                                      " does not exist!\n",
 170                                      get_khandle_from_ino(inode),
 171                                      (char *)new_op->upcall.req.getxattr.key);
 172                         cx = kmalloc(sizeof *cx, GFP_KERNEL);
 173                         if (cx) {
 174                                 strcpy(cx->key, name);
 175                                 cx->length = -1;
 176                                 cx->timeout = jiffies +
 177                                     orangefs_getattr_timeout_msecs*HZ/1000;
 178                                 hash_add(orangefs_inode->xattr_cache, &cx->node,
 179                                     xattr_key(cx->key));
 180                         }
 181                 }
 182                 goto out_release_op;
 183         }
 184 
 185         /*
 186          * Length returned includes null terminator.
 187          */
 188         length = new_op->downcall.resp.getxattr.val_sz;
 189 
 190         /*
 191          * Just return the length of the queried attribute.
 192          */
 193         if (size == 0) {
 194                 ret = length;
 195                 goto out_release_op;
 196         }
 197 
 198         /*
 199          * Check to see if key length is > provided buffer size.
 200          */
 201         if (length > size) {
 202                 ret = -ERANGE;
 203                 goto out_release_op;
 204         }
 205 
 206         memcpy(buffer, new_op->downcall.resp.getxattr.val, length);
 207         memset(buffer + length, 0, size - length);
 208         gossip_debug(GOSSIP_XATTR_DEBUG,
 209              "orangefs_inode_getxattr: inode %pU "
 210              "key %s key_sz %d, val_len %d\n",
 211              get_khandle_from_ino(inode),
 212              (char *)new_op->
 213                 upcall.req.getxattr.key,
 214                      (int)new_op->
 215                 upcall.req.getxattr.key_sz,
 216              (int)ret);
 217 
 218         ret = length;
 219 
 220         if (cx) {
 221                 strcpy(cx->key, name);
 222                 memcpy(cx->val, buffer, length);
 223                 cx->length = length;
 224                 cx->timeout = jiffies + HZ;
 225         } else {
 226                 cx = kmalloc(sizeof *cx, GFP_KERNEL);
 227                 if (cx) {
 228                         strcpy(cx->key, name);
 229                         memcpy(cx->val, buffer, length);
 230                         cx->length = length;
 231                         cx->timeout = jiffies + HZ;
 232                         hash_add(orangefs_inode->xattr_cache, &cx->node,
 233                             xattr_key(cx->key));
 234                 }
 235         }
 236 
 237 out_release_op:
 238         op_release(new_op);
 239 out_unlock:
 240         up_read(&orangefs_inode->xattr_sem);
 241         return ret;
 242 }
 243 
 244 static int orangefs_inode_removexattr(struct inode *inode, const char *name,
 245                                       int flags)
 246 {
 247         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 248         struct orangefs_kernel_op_s *new_op = NULL;
 249         struct orangefs_cached_xattr *cx;
 250         struct hlist_head *h;
 251         struct hlist_node *tmp;
 252         int ret = -ENOMEM;
 253 
 254         if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
 255                 return -EINVAL;
 256 
 257         down_write(&orangefs_inode->xattr_sem);
 258         new_op = op_alloc(ORANGEFS_VFS_OP_REMOVEXATTR);
 259         if (!new_op)
 260                 goto out_unlock;
 261 
 262         new_op->upcall.req.removexattr.refn = orangefs_inode->refn;
 263         /*
 264          * NOTE: Although keys are meant to be NULL terminated
 265          * textual strings, I am going to explicitly pass the
 266          * length just in case we change this later on...
 267          */
 268         strcpy(new_op->upcall.req.removexattr.key, name);
 269         new_op->upcall.req.removexattr.key_sz = strlen(name) + 1;
 270 
 271         gossip_debug(GOSSIP_XATTR_DEBUG,
 272                      "orangefs_inode_removexattr: key %s, key_sz %d\n",
 273                      (char *)new_op->upcall.req.removexattr.key,
 274                      (int)new_op->upcall.req.removexattr.key_sz);
 275 
 276         ret = service_operation(new_op,
 277                                 "orangefs_inode_removexattr",
 278                                 get_interruptible_flag(inode));
 279         if (ret == -ENOENT) {
 280                 /*
 281                  * Request to replace a non-existent attribute is an error.
 282                  */
 283                 if (flags & XATTR_REPLACE)
 284                         ret = -ENODATA;
 285                 else
 286                         ret = 0;
 287         }
 288 
 289         gossip_debug(GOSSIP_XATTR_DEBUG,
 290                      "orangefs_inode_removexattr: returning %d\n", ret);
 291 
 292         op_release(new_op);
 293 
 294         h = &orangefs_inode->xattr_cache[xattr_key(name)];
 295         hlist_for_each_entry_safe(cx, tmp, h, node) {
 296                 if (!strcmp(cx->key, name)) {
 297                         hlist_del(&cx->node);
 298                         kfree(cx);
 299                         break;
 300                 }
 301         }
 302 
 303 out_unlock:
 304         up_write(&orangefs_inode->xattr_sem);
 305         return ret;
 306 }
 307 
 308 /*
 309  * Tries to set an attribute for a given key on a file.
 310  *
 311  * Returns a -ve number on error and 0 on success.  Key is text, but value
 312  * can be binary!
 313  */
 314 int orangefs_inode_setxattr(struct inode *inode, const char *name,
 315                             const void *value, size_t size, int flags)
 316 {
 317         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 318         struct orangefs_kernel_op_s *new_op;
 319         int internal_flag = 0;
 320         struct orangefs_cached_xattr *cx;
 321         struct hlist_head *h;
 322         struct hlist_node *tmp;
 323         int ret = -ENOMEM;
 324 
 325         gossip_debug(GOSSIP_XATTR_DEBUG,
 326                      "%s: name %s, buffer_size %zd\n",
 327                      __func__, name, size);
 328 
 329         if (size > ORANGEFS_MAX_XATTR_VALUELEN)
 330                 return -EINVAL;
 331         if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
 332                 return -EINVAL;
 333 
 334         internal_flag = convert_to_internal_xattr_flags(flags);
 335 
 336         /* This is equivalent to a removexattr */
 337         if (size == 0 && !value) {
 338                 gossip_debug(GOSSIP_XATTR_DEBUG,
 339                              "removing xattr (%s)\n",
 340                              name);
 341                 return orangefs_inode_removexattr(inode, name, flags);
 342         }
 343 
 344         gossip_debug(GOSSIP_XATTR_DEBUG,
 345                      "setxattr on inode %pU, name %s\n",
 346                      get_khandle_from_ino(inode),
 347                      name);
 348 
 349         down_write(&orangefs_inode->xattr_sem);
 350         new_op = op_alloc(ORANGEFS_VFS_OP_SETXATTR);
 351         if (!new_op)
 352                 goto out_unlock;
 353 
 354 
 355         new_op->upcall.req.setxattr.refn = orangefs_inode->refn;
 356         new_op->upcall.req.setxattr.flags = internal_flag;
 357         /*
 358          * NOTE: Although keys are meant to be NULL terminated textual
 359          * strings, I am going to explicitly pass the length just in
 360          * case we change this later on...
 361          */
 362         strcpy(new_op->upcall.req.setxattr.keyval.key, name);
 363         new_op->upcall.req.setxattr.keyval.key_sz = strlen(name) + 1;
 364         memcpy(new_op->upcall.req.setxattr.keyval.val, value, size);
 365         new_op->upcall.req.setxattr.keyval.val_sz = size;
 366 
 367         gossip_debug(GOSSIP_XATTR_DEBUG,
 368                      "orangefs_inode_setxattr: key %s, key_sz %d "
 369                      " value size %zd\n",
 370                      (char *)new_op->upcall.req.setxattr.keyval.key,
 371                      (int)new_op->upcall.req.setxattr.keyval.key_sz,
 372                      size);
 373 
 374         ret = service_operation(new_op,
 375                                 "orangefs_inode_setxattr",
 376                                 get_interruptible_flag(inode));
 377 
 378         gossip_debug(GOSSIP_XATTR_DEBUG,
 379                      "orangefs_inode_setxattr: returning %d\n",
 380                      ret);
 381 
 382         /* when request is serviced properly, free req op struct */
 383         op_release(new_op);
 384 
 385         h = &orangefs_inode->xattr_cache[xattr_key(name)];
 386         hlist_for_each_entry_safe(cx, tmp, h, node) {
 387                 if (!strcmp(cx->key, name)) {
 388                         hlist_del(&cx->node);
 389                         kfree(cx);
 390                         break;
 391                 }
 392         }
 393 
 394 out_unlock:
 395         up_write(&orangefs_inode->xattr_sem);
 396         return ret;
 397 }
 398 
 399 /*
 400  * Tries to get a specified object's keys into a user-specified buffer of a
 401  * given size.  Note that like the previous instances of xattr routines, this
 402  * also allows you to pass in a NULL pointer and 0 size to probe the size for
 403  * subsequent memory allocations. Thus our return value is always the size of
 404  * all the keys unless there were errors in fetching the keys!
 405  */
 406 ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 407 {
 408         struct inode *inode = dentry->d_inode;
 409         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 410         struct orangefs_kernel_op_s *new_op;
 411         __u64 token = ORANGEFS_ITERATE_START;
 412         ssize_t ret = -ENOMEM;
 413         ssize_t total = 0;
 414         int count_keys = 0;
 415         int key_size;
 416         int i = 0;
 417         int returned_count = 0;
 418 
 419         if (size > 0 && !buffer) {
 420                 gossip_err("%s: bogus NULL pointers\n", __func__);
 421                 return -EINVAL;
 422         }
 423 
 424         down_read(&orangefs_inode->xattr_sem);
 425         new_op = op_alloc(ORANGEFS_VFS_OP_LISTXATTR);
 426         if (!new_op)
 427                 goto out_unlock;
 428 
 429         if (buffer && size > 0)
 430                 memset(buffer, 0, size);
 431 
 432 try_again:
 433         key_size = 0;
 434         new_op->upcall.req.listxattr.refn = orangefs_inode->refn;
 435         new_op->upcall.req.listxattr.token = token;
 436         new_op->upcall.req.listxattr.requested_count =
 437             (size == 0) ? 0 : ORANGEFS_MAX_XATTR_LISTLEN;
 438         ret = service_operation(new_op, __func__,
 439                                 get_interruptible_flag(inode));
 440         if (ret != 0)
 441                 goto done;
 442 
 443         if (size == 0) {
 444                 /*
 445                  * This is a bit of a big upper limit, but I did not want to
 446                  * spend too much time getting this correct, since users end
 447                  * up allocating memory rather than us...
 448                  */
 449                 total = new_op->downcall.resp.listxattr.returned_count *
 450                         ORANGEFS_MAX_XATTR_NAMELEN;
 451                 goto done;
 452         }
 453 
 454         returned_count = new_op->downcall.resp.listxattr.returned_count;
 455         if (returned_count < 0 ||
 456             returned_count > ORANGEFS_MAX_XATTR_LISTLEN) {
 457                 gossip_err("%s: impossible value for returned_count:%d:\n",
 458                 __func__,
 459                 returned_count);
 460                 ret = -EIO;
 461                 goto done;
 462         }
 463 
 464         /*
 465          * Check to see how much can be fit in the buffer. Fit only whole keys.
 466          */
 467         for (i = 0; i < returned_count; i++) {
 468                 if (new_op->downcall.resp.listxattr.lengths[i] < 0 ||
 469                     new_op->downcall.resp.listxattr.lengths[i] >
 470                     ORANGEFS_MAX_XATTR_NAMELEN) {
 471                         gossip_err("%s: impossible value for lengths[%d]\n",
 472                             __func__,
 473                             new_op->downcall.resp.listxattr.lengths[i]);
 474                         ret = -EIO;
 475                         goto done;
 476                 }
 477                 if (total + new_op->downcall.resp.listxattr.lengths[i] > size)
 478                         goto done;
 479 
 480                 /*
 481                  * Since many dumb programs try to setxattr() on our reserved
 482                  * xattrs this is a feeble attempt at defeating those by not
 483                  * listing them in the output of listxattr.. sigh
 484                  */
 485                 if (is_reserved_key(new_op->downcall.resp.listxattr.key +
 486                                     key_size,
 487                                     new_op->downcall.resp.
 488                                         listxattr.lengths[i])) {
 489                         gossip_debug(GOSSIP_XATTR_DEBUG, "Copying key %d -> %s\n",
 490                                         i, new_op->downcall.resp.listxattr.key +
 491                                                 key_size);
 492                         memcpy(buffer + total,
 493                                 new_op->downcall.resp.listxattr.key + key_size,
 494                                 new_op->downcall.resp.listxattr.lengths[i]);
 495                         total += new_op->downcall.resp.listxattr.lengths[i];
 496                         count_keys++;
 497                 } else {
 498                         gossip_debug(GOSSIP_XATTR_DEBUG, "[RESERVED] key %d -> %s\n",
 499                                         i, new_op->downcall.resp.listxattr.key +
 500                                                 key_size);
 501                 }
 502                 key_size += new_op->downcall.resp.listxattr.lengths[i];
 503         }
 504 
 505         /*
 506          * Since the buffer was large enough, we might have to continue
 507          * fetching more keys!
 508          */
 509         token = new_op->downcall.resp.listxattr.token;
 510         if (token != ORANGEFS_ITERATE_END)
 511                 goto try_again;
 512 
 513 done:
 514         gossip_debug(GOSSIP_XATTR_DEBUG, "%s: returning %d"
 515                      " [size of buffer %ld] (filled in %d keys)\n",
 516                      __func__,
 517                      ret ? (int)ret : (int)total,
 518                      (long)size,
 519                      count_keys);
 520         op_release(new_op);
 521         if (ret == 0)
 522                 ret = total;
 523 out_unlock:
 524         up_read(&orangefs_inode->xattr_sem);
 525         return ret;
 526 }
 527 
 528 static int orangefs_xattr_set_default(const struct xattr_handler *handler,
 529                                       struct dentry *unused,
 530                                       struct inode *inode,
 531                                       const char *name,
 532                                       const void *buffer,
 533                                       size_t size,
 534                                       int flags)
 535 {
 536         return orangefs_inode_setxattr(inode, name, buffer, size, flags);
 537 }
 538 
 539 static int orangefs_xattr_get_default(const struct xattr_handler *handler,
 540                                       struct dentry *unused,
 541                                       struct inode *inode,
 542                                       const char *name,
 543                                       void *buffer,
 544                                       size_t size)
 545 {
 546         return orangefs_inode_getxattr(inode, name, buffer, size);
 547 
 548 }
 549 
 550 static const struct xattr_handler orangefs_xattr_default_handler = {
 551         .prefix = "",  /* match any name => handlers called with full name */
 552         .get = orangefs_xattr_get_default,
 553         .set = orangefs_xattr_set_default,
 554 };
 555 
 556 const struct xattr_handler *orangefs_xattr_handlers[] = {
 557         &posix_acl_access_xattr_handler,
 558         &posix_acl_default_xattr_handler,
 559         &orangefs_xattr_default_handler,
 560         NULL
 561 };

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