xattr.c 12 KB

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