xattr.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Extended attribute handling for AFS. We use xattrs to get and set metadata
  3. * instead of providing pioctl().
  4. *
  5. * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
  6. * Written by David Howells (dhowells@redhat.com)
  7. */
  8. #include <linux/slab.h>
  9. #include <linux/fs.h>
  10. #include <linux/xattr.h>
  11. #include "internal.h"
  12. /*
  13. * Deal with the result of a successful fetch ACL operation.
  14. */
  15. static void afs_acl_success(struct afs_operation *op)
  16. {
  17. afs_vnode_commit_status(op, &op->file[0]);
  18. }
  19. static void afs_acl_put(struct afs_operation *op)
  20. {
  21. kfree(op->acl);
  22. }
  23. static const struct afs_operation_ops afs_fetch_acl_operation = {
  24. .issue_afs_rpc = afs_fs_fetch_acl,
  25. .success = afs_acl_success,
  26. .put = afs_acl_put,
  27. };
  28. /*
  29. * Get a file's ACL.
  30. */
  31. static int afs_xattr_get_acl(const struct xattr_handler *handler,
  32. struct dentry *dentry,
  33. struct inode *inode, const char *name,
  34. void *buffer, size_t size)
  35. {
  36. struct afs_operation *op;
  37. struct afs_vnode *vnode = AFS_FS_I(inode);
  38. struct afs_acl *acl = NULL;
  39. int ret;
  40. op = afs_alloc_operation(NULL, vnode->volume);
  41. if (IS_ERR(op))
  42. return -ENOMEM;
  43. afs_op_set_vnode(op, 0, vnode);
  44. op->ops = &afs_fetch_acl_operation;
  45. afs_begin_vnode_operation(op);
  46. afs_wait_for_operation(op);
  47. acl = op->acl;
  48. op->acl = NULL;
  49. ret = afs_put_operation(op);
  50. if (ret == 0) {
  51. ret = acl->size;
  52. if (size > 0) {
  53. if (acl->size <= size)
  54. memcpy(buffer, acl->data, acl->size);
  55. else
  56. ret = -ERANGE;
  57. }
  58. }
  59. kfree(acl);
  60. return ret;
  61. }
  62. static bool afs_make_acl(struct afs_operation *op,
  63. const void *buffer, size_t size)
  64. {
  65. struct afs_acl *acl;
  66. acl = kmalloc_flex(*acl, data, size);
  67. if (!acl) {
  68. afs_op_nomem(op);
  69. return false;
  70. }
  71. acl->size = size;
  72. memcpy(acl->data, buffer, size);
  73. op->acl = acl;
  74. return true;
  75. }
  76. static const struct afs_operation_ops afs_store_acl_operation = {
  77. .issue_afs_rpc = afs_fs_store_acl,
  78. .success = afs_acl_success,
  79. .put = afs_acl_put,
  80. };
  81. /*
  82. * Set a file's AFS3 ACL.
  83. */
  84. static int afs_xattr_set_acl(const struct xattr_handler *handler,
  85. struct mnt_idmap *idmap,
  86. struct dentry *dentry,
  87. struct inode *inode, const char *name,
  88. const void *buffer, size_t size, int flags)
  89. {
  90. struct afs_operation *op;
  91. struct afs_vnode *vnode = AFS_FS_I(inode);
  92. if (flags == XATTR_CREATE)
  93. return -EINVAL;
  94. op = afs_alloc_operation(NULL, vnode->volume);
  95. if (IS_ERR(op))
  96. return -ENOMEM;
  97. afs_op_set_vnode(op, 0, vnode);
  98. if (!afs_make_acl(op, buffer, size))
  99. return afs_put_operation(op);
  100. op->ops = &afs_store_acl_operation;
  101. return afs_do_sync_operation(op);
  102. }
  103. static const struct xattr_handler afs_xattr_afs_acl_handler = {
  104. .name = "afs.acl",
  105. .get = afs_xattr_get_acl,
  106. .set = afs_xattr_set_acl,
  107. };
  108. static const struct afs_operation_ops yfs_fetch_opaque_acl_operation = {
  109. .issue_yfs_rpc = yfs_fs_fetch_opaque_acl,
  110. .success = afs_acl_success,
  111. /* Don't free op->yacl in .put here */
  112. };
  113. /*
  114. * Get a file's YFS ACL.
  115. */
  116. static int afs_xattr_get_yfs(const struct xattr_handler *handler,
  117. struct dentry *dentry,
  118. struct inode *inode, const char *name,
  119. void *buffer, size_t size)
  120. {
  121. struct afs_operation *op;
  122. struct afs_vnode *vnode = AFS_FS_I(inode);
  123. struct yfs_acl *yacl = NULL;
  124. char buf[16], *data;
  125. int which = 0, dsize, ret = -ENOMEM;
  126. if (strcmp(name, "acl") == 0)
  127. which = 0;
  128. else if (strcmp(name, "acl_inherited") == 0)
  129. which = 1;
  130. else if (strcmp(name, "acl_num_cleaned") == 0)
  131. which = 2;
  132. else if (strcmp(name, "vol_acl") == 0)
  133. which = 3;
  134. else
  135. return -EOPNOTSUPP;
  136. yacl = kzalloc_obj(struct yfs_acl);
  137. if (!yacl)
  138. goto error;
  139. if (which == 0)
  140. yacl->flags |= YFS_ACL_WANT_ACL;
  141. else if (which == 3)
  142. yacl->flags |= YFS_ACL_WANT_VOL_ACL;
  143. op = afs_alloc_operation(NULL, vnode->volume);
  144. if (IS_ERR(op))
  145. goto error_yacl;
  146. afs_op_set_vnode(op, 0, vnode);
  147. op->yacl = yacl;
  148. op->ops = &yfs_fetch_opaque_acl_operation;
  149. afs_begin_vnode_operation(op);
  150. afs_wait_for_operation(op);
  151. ret = afs_put_operation(op);
  152. if (ret == 0) {
  153. switch (which) {
  154. case 0:
  155. data = yacl->acl->data;
  156. dsize = yacl->acl->size;
  157. break;
  158. case 1:
  159. data = buf;
  160. dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
  161. break;
  162. case 2:
  163. data = buf;
  164. dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
  165. break;
  166. case 3:
  167. data = yacl->vol_acl->data;
  168. dsize = yacl->vol_acl->size;
  169. break;
  170. default:
  171. ret = -EOPNOTSUPP;
  172. goto error_yacl;
  173. }
  174. ret = dsize;
  175. if (size > 0) {
  176. if (dsize <= size)
  177. memcpy(buffer, data, dsize);
  178. else
  179. ret = -ERANGE;
  180. }
  181. } else if (ret == -ENOTSUPP) {
  182. ret = -ENODATA;
  183. }
  184. error_yacl:
  185. yfs_free_opaque_acl(yacl);
  186. error:
  187. return ret;
  188. }
  189. static const struct afs_operation_ops yfs_store_opaque_acl2_operation = {
  190. .issue_yfs_rpc = yfs_fs_store_opaque_acl2,
  191. .success = afs_acl_success,
  192. .put = afs_acl_put,
  193. };
  194. /*
  195. * Set a file's YFS ACL.
  196. */
  197. static int afs_xattr_set_yfs(const struct xattr_handler *handler,
  198. struct mnt_idmap *idmap,
  199. struct dentry *dentry,
  200. struct inode *inode, const char *name,
  201. const void *buffer, size_t size, int flags)
  202. {
  203. struct afs_operation *op;
  204. struct afs_vnode *vnode = AFS_FS_I(inode);
  205. int ret;
  206. if (flags == XATTR_CREATE ||
  207. strcmp(name, "acl") != 0)
  208. return -EINVAL;
  209. op = afs_alloc_operation(NULL, vnode->volume);
  210. if (IS_ERR(op))
  211. return -ENOMEM;
  212. afs_op_set_vnode(op, 0, vnode);
  213. if (!afs_make_acl(op, buffer, size))
  214. return afs_put_operation(op);
  215. op->ops = &yfs_store_opaque_acl2_operation;
  216. ret = afs_do_sync_operation(op);
  217. if (ret == -ENOTSUPP)
  218. ret = -ENODATA;
  219. return ret;
  220. }
  221. static const struct xattr_handler afs_xattr_yfs_handler = {
  222. .prefix = "afs.yfs.",
  223. .get = afs_xattr_get_yfs,
  224. .set = afs_xattr_set_yfs,
  225. };
  226. /*
  227. * Get the name of the cell on which a file resides.
  228. */
  229. static int afs_xattr_get_cell(const struct xattr_handler *handler,
  230. struct dentry *dentry,
  231. struct inode *inode, const char *name,
  232. void *buffer, size_t size)
  233. {
  234. struct afs_vnode *vnode = AFS_FS_I(inode);
  235. struct afs_cell *cell = vnode->volume->cell;
  236. size_t namelen;
  237. namelen = cell->name_len;
  238. if (size == 0)
  239. return namelen;
  240. if (namelen > size)
  241. return -ERANGE;
  242. memcpy(buffer, cell->name, namelen);
  243. return namelen;
  244. }
  245. static const struct xattr_handler afs_xattr_afs_cell_handler = {
  246. .name = "afs.cell",
  247. .get = afs_xattr_get_cell,
  248. };
  249. /*
  250. * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
  251. * hex numbers separated by colons.
  252. */
  253. static int afs_xattr_get_fid(const struct xattr_handler *handler,
  254. struct dentry *dentry,
  255. struct inode *inode, const char *name,
  256. void *buffer, size_t size)
  257. {
  258. struct afs_vnode *vnode = AFS_FS_I(inode);
  259. char text[16 + 1 + 24 + 1 + 8 + 1];
  260. size_t len;
  261. /* The volume ID is 64-bit, the vnode ID is 96-bit and the
  262. * uniquifier is 32-bit.
  263. */
  264. len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
  265. if (vnode->fid.vnode_hi)
  266. len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
  267. vnode->fid.vnode_hi, vnode->fid.vnode);
  268. else
  269. len += scnprintf(text + len, sizeof(text) - len, "%llx",
  270. vnode->fid.vnode);
  271. len += scnprintf(text + len, sizeof(text) - len, ":%x",
  272. vnode->fid.unique);
  273. if (size == 0)
  274. return len;
  275. if (len > size)
  276. return -ERANGE;
  277. memcpy(buffer, text, len);
  278. return len;
  279. }
  280. static const struct xattr_handler afs_xattr_afs_fid_handler = {
  281. .name = "afs.fid",
  282. .get = afs_xattr_get_fid,
  283. };
  284. /*
  285. * Get the name of the volume on which a file resides.
  286. */
  287. static int afs_xattr_get_volume(const struct xattr_handler *handler,
  288. struct dentry *dentry,
  289. struct inode *inode, const char *name,
  290. void *buffer, size_t size)
  291. {
  292. struct afs_vnode *vnode = AFS_FS_I(inode);
  293. const char *volname = vnode->volume->name;
  294. size_t namelen;
  295. namelen = strlen(volname);
  296. if (size == 0)
  297. return namelen;
  298. if (namelen > size)
  299. return -ERANGE;
  300. memcpy(buffer, volname, namelen);
  301. return namelen;
  302. }
  303. static const struct xattr_handler afs_xattr_afs_volume_handler = {
  304. .name = "afs.volume",
  305. .get = afs_xattr_get_volume,
  306. };
  307. const struct xattr_handler * const afs_xattr_handlers[] = {
  308. &afs_xattr_afs_acl_handler,
  309. &afs_xattr_afs_cell_handler,
  310. &afs_xattr_afs_fid_handler,
  311. &afs_xattr_afs_volume_handler,
  312. &afs_xattr_yfs_handler, /* afs.yfs. prefix */
  313. NULL
  314. };