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 mnt_idmap *idmap, 530 struct dentry *unused, 531 struct inode *inode, 532 const char *name, 533 const void *buffer, 534 size_t size, 535 int flags) 536 { 537 return orangefs_inode_setxattr(inode, name, buffer, size, flags); 538 } 539 540 static int orangefs_xattr_get_default(const struct xattr_handler *handler, 541 struct dentry *unused, 542 struct inode *inode, 543 const char *name, 544 void *buffer, 545 size_t size) 546 { 547 return orangefs_inode_getxattr(inode, name, buffer, size); 548 549 } 550 551 static const struct xattr_handler orangefs_xattr_default_handler = { 552 .prefix = "", /* match any name => handlers called with full name */ 553 .get = orangefs_xattr_get_default, 554 .set = orangefs_xattr_set_default, 555 }; 556 557 const struct xattr_handler * const orangefs_xattr_handlers[] = { 558 &orangefs_xattr_default_handler, 559 NULL 560 }; 561
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.