xattr.c 12 KB

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