xattr.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Squashfs - a compressed read only filesystem for Linux
  4. *
  5. * Copyright (c) 2010
  6. * Phillip Lougher <phillip@squashfs.org.uk>
  7. *
  8. * xattr.c
  9. */
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/string.h>
  13. #include <linux/fs.h>
  14. #include <linux/vfs.h>
  15. #include <linux/xattr.h>
  16. #include <linux/slab.h>
  17. #include "squashfs_fs.h"
  18. #include "squashfs_fs_sb.h"
  19. #include "squashfs_fs_i.h"
  20. #include "squashfs.h"
  21. static const struct xattr_handler *squashfs_xattr_handler(int);
  22. ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
  23. size_t buffer_size)
  24. {
  25. struct inode *inode = d_inode(d);
  26. struct super_block *sb = inode->i_sb;
  27. struct squashfs_sb_info *msblk = sb->s_fs_info;
  28. u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr)
  29. + msblk->xattr_table;
  30. int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr);
  31. int count = squashfs_i(inode)->xattr_count;
  32. size_t rest = buffer_size;
  33. int err;
  34. /* check that the file system has xattrs */
  35. if (msblk->xattr_id_table == NULL)
  36. return -EOPNOTSUPP;
  37. /* loop reading each xattr name */
  38. while (count--) {
  39. struct squashfs_xattr_entry entry;
  40. struct squashfs_xattr_val val;
  41. const struct xattr_handler *handler;
  42. int name_size;
  43. err = squashfs_read_metadata(sb, &entry, &start, &offset,
  44. sizeof(entry));
  45. if (err < 0)
  46. goto failed;
  47. name_size = le16_to_cpu(entry.size);
  48. handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
  49. if (handler && (!handler->list || handler->list(d))) {
  50. const char *prefix = handler->prefix ?: handler->name;
  51. size_t prefix_size = strlen(prefix);
  52. if (buffer) {
  53. if (prefix_size + name_size + 1 > rest) {
  54. err = -ERANGE;
  55. goto failed;
  56. }
  57. memcpy(buffer, prefix, prefix_size);
  58. buffer += prefix_size;
  59. }
  60. err = squashfs_read_metadata(sb, buffer, &start,
  61. &offset, name_size);
  62. if (err < 0)
  63. goto failed;
  64. if (buffer) {
  65. buffer[name_size] = '\0';
  66. buffer += name_size + 1;
  67. }
  68. rest -= prefix_size + name_size + 1;
  69. } else {
  70. /* no handler or insuffficient privileges, so skip */
  71. err = squashfs_read_metadata(sb, NULL, &start,
  72. &offset, name_size);
  73. if (err < 0)
  74. goto failed;
  75. }
  76. /* skip remaining xattr entry */
  77. err = squashfs_read_metadata(sb, &val, &start, &offset,
  78. sizeof(val));
  79. if (err < 0)
  80. goto failed;
  81. err = squashfs_read_metadata(sb, NULL, &start, &offset,
  82. le32_to_cpu(val.vsize));
  83. if (err < 0)
  84. goto failed;
  85. }
  86. err = buffer_size - rest;
  87. failed:
  88. return err;
  89. }
  90. static int squashfs_xattr_get(struct inode *inode, int name_index,
  91. const char *name, void *buffer, size_t buffer_size)
  92. {
  93. struct super_block *sb = inode->i_sb;
  94. struct squashfs_sb_info *msblk = sb->s_fs_info;
  95. u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr)
  96. + msblk->xattr_table;
  97. int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr);
  98. int count = squashfs_i(inode)->xattr_count;
  99. int name_len = strlen(name);
  100. int err, vsize;
  101. char *target = kmalloc(name_len, GFP_KERNEL);
  102. if (target == NULL)
  103. return -ENOMEM;
  104. /* loop reading each xattr name */
  105. for (; count; count--) {
  106. struct squashfs_xattr_entry entry;
  107. struct squashfs_xattr_val val;
  108. int type, prefix, name_size;
  109. err = squashfs_read_metadata(sb, &entry, &start, &offset,
  110. sizeof(entry));
  111. if (err < 0)
  112. goto failed;
  113. name_size = le16_to_cpu(entry.size);
  114. type = le16_to_cpu(entry.type);
  115. prefix = type & SQUASHFS_XATTR_PREFIX_MASK;
  116. if (prefix == name_index && name_size == name_len)
  117. err = squashfs_read_metadata(sb, target, &start,
  118. &offset, name_size);
  119. else
  120. err = squashfs_read_metadata(sb, NULL, &start,
  121. &offset, name_size);
  122. if (err < 0)
  123. goto failed;
  124. if (prefix == name_index && name_size == name_len &&
  125. strncmp(target, name, name_size) == 0) {
  126. /* found xattr */
  127. if (type & SQUASHFS_XATTR_VALUE_OOL) {
  128. __le64 xattr_val;
  129. u64 xattr;
  130. /* val is a reference to the real location */
  131. err = squashfs_read_metadata(sb, &val, &start,
  132. &offset, sizeof(val));
  133. if (err < 0)
  134. goto failed;
  135. err = squashfs_read_metadata(sb, &xattr_val,
  136. &start, &offset, sizeof(xattr_val));
  137. if (err < 0)
  138. goto failed;
  139. xattr = le64_to_cpu(xattr_val);
  140. start = SQUASHFS_XATTR_BLK(xattr) +
  141. msblk->xattr_table;
  142. offset = SQUASHFS_XATTR_OFFSET(xattr);
  143. }
  144. /* read xattr value */
  145. err = squashfs_read_metadata(sb, &val, &start, &offset,
  146. sizeof(val));
  147. if (err < 0)
  148. goto failed;
  149. vsize = le32_to_cpu(val.vsize);
  150. if (buffer) {
  151. if (vsize > buffer_size) {
  152. err = -ERANGE;
  153. goto failed;
  154. }
  155. err = squashfs_read_metadata(sb, buffer, &start,
  156. &offset, vsize);
  157. if (err < 0)
  158. goto failed;
  159. }
  160. break;
  161. }
  162. /* no match, skip remaining xattr entry */
  163. err = squashfs_read_metadata(sb, &val, &start, &offset,
  164. sizeof(val));
  165. if (err < 0)
  166. goto failed;
  167. err = squashfs_read_metadata(sb, NULL, &start, &offset,
  168. le32_to_cpu(val.vsize));
  169. if (err < 0)
  170. goto failed;
  171. }
  172. err = count ? vsize : -ENODATA;
  173. failed:
  174. kfree(target);
  175. return err;
  176. }
  177. static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
  178. struct dentry *unused,
  179. struct inode *inode,
  180. const char *name,
  181. void *buffer, size_t size, int flags)
  182. {
  183. return squashfs_xattr_get(inode, handler->flags, name,
  184. buffer, size);
  185. }
  186. /*
  187. * User namespace support
  188. */
  189. static const struct xattr_handler squashfs_xattr_user_handler = {
  190. .prefix = XATTR_USER_PREFIX,
  191. .flags = SQUASHFS_XATTR_USER,
  192. .get = squashfs_xattr_handler_get
  193. };
  194. /*
  195. * Trusted namespace support
  196. */
  197. static bool squashfs_trusted_xattr_handler_list(struct dentry *d)
  198. {
  199. return capable(CAP_SYS_ADMIN);
  200. }
  201. static const struct xattr_handler squashfs_xattr_trusted_handler = {
  202. .prefix = XATTR_TRUSTED_PREFIX,
  203. .flags = SQUASHFS_XATTR_TRUSTED,
  204. .list = squashfs_trusted_xattr_handler_list,
  205. .get = squashfs_xattr_handler_get
  206. };
  207. /*
  208. * Security namespace support
  209. */
  210. static const struct xattr_handler squashfs_xattr_security_handler = {
  211. .prefix = XATTR_SECURITY_PREFIX,
  212. .flags = SQUASHFS_XATTR_SECURITY,
  213. .get = squashfs_xattr_handler_get
  214. };
  215. static const struct xattr_handler *squashfs_xattr_handler(int type)
  216. {
  217. if (type & ~(SQUASHFS_XATTR_PREFIX_MASK | SQUASHFS_XATTR_VALUE_OOL))
  218. /* ignore unrecognised type */
  219. return NULL;
  220. switch (type & SQUASHFS_XATTR_PREFIX_MASK) {
  221. case SQUASHFS_XATTR_USER:
  222. return &squashfs_xattr_user_handler;
  223. case SQUASHFS_XATTR_TRUSTED:
  224. return &squashfs_xattr_trusted_handler;
  225. case SQUASHFS_XATTR_SECURITY:
  226. return &squashfs_xattr_security_handler;
  227. default:
  228. /* ignore unrecognised type */
  229. return NULL;
  230. }
  231. }
  232. const struct xattr_handler *squashfs_xattr_handlers[] = {
  233. &squashfs_xattr_user_handler,
  234. &squashfs_xattr_trusted_handler,
  235. &squashfs_xattr_security_handler,
  236. NULL
  237. };