xattr.c 15 KB

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