xattr.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: LGPL-2.1
  2. /*
  3. * Copyright IBM Corporation, 2010
  4. * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
  5. */
  6. #include <linux/module.h>
  7. #include <linux/fs.h>
  8. #include <linux/sched.h>
  9. #include <linux/uio.h>
  10. #include <linux/posix_acl_xattr.h>
  11. #include <net/9p/9p.h>
  12. #include <net/9p/client.h>
  13. #include "fid.h"
  14. #include "xattr.h"
  15. ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
  16. void *buffer, size_t buffer_size)
  17. {
  18. ssize_t retval;
  19. u64 attr_size;
  20. struct p9_fid *attr_fid;
  21. struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size};
  22. struct iov_iter to;
  23. int err;
  24. iov_iter_kvec(&to, ITER_DEST, &kvec, 1, buffer_size);
  25. attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
  26. if (IS_ERR(attr_fid)) {
  27. retval = PTR_ERR(attr_fid);
  28. p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n",
  29. retval);
  30. return retval;
  31. }
  32. if (attr_size > buffer_size) {
  33. if (buffer_size)
  34. retval = -ERANGE;
  35. else if (attr_size > SSIZE_MAX)
  36. retval = -EOVERFLOW;
  37. else /* request to get the attr_size */
  38. retval = attr_size;
  39. } else {
  40. iov_iter_truncate(&to, attr_size);
  41. retval = p9_client_read(attr_fid, 0, &to, &err);
  42. if (err)
  43. retval = err;
  44. }
  45. p9_fid_put(attr_fid);
  46. return retval;
  47. }
  48. /*
  49. * v9fs_xattr_get()
  50. *
  51. * Copy an extended attribute into the buffer
  52. * provided, or compute the buffer size required.
  53. * Buffer is NULL to compute the size of the buffer required.
  54. *
  55. * Returns a negative error number on failure, or the number of bytes
  56. * used / required on success.
  57. */
  58. ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
  59. void *buffer, size_t buffer_size)
  60. {
  61. struct p9_fid *fid;
  62. int ret;
  63. p9_debug(P9_DEBUG_VFS, "name = '%s' value_len = %zu\n",
  64. name, buffer_size);
  65. fid = v9fs_fid_lookup(dentry);
  66. if (IS_ERR(fid))
  67. return PTR_ERR(fid);
  68. ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
  69. p9_fid_put(fid);
  70. return ret;
  71. }
  72. /*
  73. * v9fs_xattr_set()
  74. *
  75. * Create, replace or remove an extended attribute for this inode. Buffer
  76. * is NULL to remove an existing extended attribute, and non-NULL to
  77. * either replace an existing extended attribute, or create a new extended
  78. * attribute. The flags XATTR_REPLACE and XATTR_CREATE
  79. * specify that an extended attribute must exist and must not exist
  80. * previous to the call, respectively.
  81. *
  82. * Returns 0, or a negative error number on failure.
  83. */
  84. int v9fs_xattr_set(struct dentry *dentry, const char *name,
  85. const void *value, size_t value_len, int flags)
  86. {
  87. int ret;
  88. struct p9_fid *fid;
  89. fid = v9fs_fid_lookup(dentry);
  90. if (IS_ERR(fid))
  91. return PTR_ERR(fid);
  92. ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
  93. p9_fid_put(fid);
  94. return ret;
  95. }
  96. int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
  97. const void *value, size_t value_len, int flags)
  98. {
  99. struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len};
  100. struct iov_iter from;
  101. int retval, err;
  102. iov_iter_kvec(&from, ITER_SOURCE, &kvec, 1, value_len);
  103. p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n",
  104. name, value_len, flags);
  105. /* Clone it */
  106. fid = clone_fid(fid);
  107. if (IS_ERR(fid))
  108. return PTR_ERR(fid);
  109. /*
  110. * On success fid points to xattr
  111. */
  112. retval = p9_client_xattrcreate(fid, name, value_len, flags);
  113. if (retval < 0)
  114. p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n",
  115. retval);
  116. else
  117. p9_client_write(fid, 0, &from, &retval);
  118. err = p9_fid_put(fid);
  119. if (!retval && err)
  120. retval = err;
  121. return retval;
  122. }
  123. ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
  124. {
  125. /* Txattrwalk with an empty string lists xattrs instead */
  126. return v9fs_xattr_get(dentry, "", buffer, buffer_size);
  127. }
  128. static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
  129. struct dentry *dentry, struct inode *inode,
  130. const char *name, void *buffer, size_t size)
  131. {
  132. const char *full_name = xattr_full_name(handler, name);
  133. return v9fs_xattr_get(dentry, full_name, buffer, size);
  134. }
  135. static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
  136. struct mnt_idmap *idmap,
  137. struct dentry *dentry, struct inode *inode,
  138. const char *name, const void *value,
  139. size_t size, int flags)
  140. {
  141. const char *full_name = xattr_full_name(handler, name);
  142. return v9fs_xattr_set(dentry, full_name, value, size, flags);
  143. }
  144. static const struct xattr_handler v9fs_xattr_user_handler = {
  145. .prefix = XATTR_USER_PREFIX,
  146. .get = v9fs_xattr_handler_get,
  147. .set = v9fs_xattr_handler_set,
  148. };
  149. static const struct xattr_handler v9fs_xattr_trusted_handler = {
  150. .prefix = XATTR_TRUSTED_PREFIX,
  151. .get = v9fs_xattr_handler_get,
  152. .set = v9fs_xattr_handler_set,
  153. };
  154. #ifdef CONFIG_9P_FS_SECURITY
  155. static const struct xattr_handler v9fs_xattr_security_handler = {
  156. .prefix = XATTR_SECURITY_PREFIX,
  157. .get = v9fs_xattr_handler_get,
  158. .set = v9fs_xattr_handler_set,
  159. };
  160. #endif
  161. const struct xattr_handler * const v9fs_xattr_handlers[] = {
  162. &v9fs_xattr_user_handler,
  163. &v9fs_xattr_trusted_handler,
  164. #ifdef CONFIG_9P_FS_SECURITY
  165. &v9fs_xattr_security_handler,
  166. #endif
  167. NULL
  168. };