attrlist.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. *
  4. * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
  5. *
  6. */
  7. #include <linux/fs.h>
  8. #include "debug.h"
  9. #include "ntfs.h"
  10. #include "ntfs_fs.h"
  11. /*
  12. * al_is_valid_le
  13. *
  14. * Return: True if @le is valid.
  15. */
  16. static inline bool al_is_valid_le(const struct ntfs_inode *ni,
  17. struct ATTR_LIST_ENTRY *le)
  18. {
  19. if (!le || !ni->attr_list.le || !ni->attr_list.size)
  20. return false;
  21. return PtrOffset(ni->attr_list.le, le) + le16_to_cpu(le->size) <=
  22. ni->attr_list.size;
  23. }
  24. void al_destroy(struct ntfs_inode *ni)
  25. {
  26. run_close(&ni->attr_list.run);
  27. kvfree(ni->attr_list.le);
  28. ni->attr_list.le = NULL;
  29. ni->attr_list.size = 0;
  30. ni->attr_list.dirty = false;
  31. }
  32. /*
  33. * ntfs_load_attr_list
  34. *
  35. * This method makes sure that the ATTRIB list, if present,
  36. * has been properly set up.
  37. */
  38. int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr)
  39. {
  40. int err;
  41. size_t lsize;
  42. void *le = NULL;
  43. if (ni->attr_list.size)
  44. return 0;
  45. if (!attr->non_res) {
  46. lsize = le32_to_cpu(attr->res.data_size);
  47. if (!lsize) {
  48. err = -EINVAL;
  49. goto out;
  50. }
  51. /* attr is resident: lsize < record_size (1K or 4K) */
  52. le = kvmalloc(al_aligned(lsize), GFP_KERNEL);
  53. if (!le) {
  54. err = -ENOMEM;
  55. goto out;
  56. }
  57. memcpy(le, resident_data(attr), lsize);
  58. } else if (attr->nres.svcn) {
  59. err = -EINVAL;
  60. goto out;
  61. } else {
  62. u16 run_off = le16_to_cpu(attr->nres.run_off);
  63. lsize = le64_to_cpu(attr->nres.data_size);
  64. if (!lsize) {
  65. err = -EINVAL;
  66. goto out;
  67. }
  68. run_init(&ni->attr_list.run);
  69. if (run_off > le32_to_cpu(attr->size)) {
  70. err = -EINVAL;
  71. goto out;
  72. }
  73. err = run_unpack_ex(&ni->attr_list.run, ni->mi.sbi, ni->mi.rno,
  74. 0, le64_to_cpu(attr->nres.evcn), 0,
  75. Add2Ptr(attr, run_off),
  76. le32_to_cpu(attr->size) - run_off);
  77. if (err < 0)
  78. goto out;
  79. /* attr is nonresident.
  80. * The worst case:
  81. * 1T (2^40) extremely fragmented file.
  82. * cluster = 4K (2^12) => 2^28 fragments
  83. * 2^9 fragments per one record => 2^19 records
  84. * 2^5 bytes of ATTR_LIST_ENTRY per one record => 2^24 bytes.
  85. *
  86. * the result is 16M bytes per attribute list.
  87. * Use kvmalloc to allocate in range [several Kbytes - dozen Mbytes]
  88. */
  89. le = kvmalloc(al_aligned(lsize), GFP_KERNEL);
  90. if (!le) {
  91. err = -ENOMEM;
  92. goto out;
  93. }
  94. err = ntfs_read_run_nb(ni->mi.sbi, &ni->attr_list.run, 0, le,
  95. lsize, NULL);
  96. if (err)
  97. goto out;
  98. }
  99. ni->attr_list.size = lsize;
  100. ni->attr_list.le = le;
  101. return 0;
  102. out:
  103. ni->attr_list.le = le;
  104. al_destroy(ni);
  105. return err;
  106. }
  107. /*
  108. * al_enumerate
  109. *
  110. * Return:
  111. * * The next list le.
  112. * * If @le is NULL then return the first le.
  113. */
  114. struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
  115. struct ATTR_LIST_ENTRY *le)
  116. {
  117. size_t off;
  118. u16 sz;
  119. const unsigned le_min_size = le_size(0);
  120. if (!le) {
  121. le = ni->attr_list.le;
  122. } else {
  123. sz = le16_to_cpu(le->size);
  124. if (sz < le_min_size) {
  125. /* Impossible 'cause we should not return such le. */
  126. return NULL;
  127. }
  128. le = Add2Ptr(le, sz);
  129. }
  130. /* Check boundary. */
  131. off = PtrOffset(ni->attr_list.le, le);
  132. if (off + le_min_size > ni->attr_list.size) {
  133. /* The regular end of list. */
  134. return NULL;
  135. }
  136. sz = le16_to_cpu(le->size);
  137. /* Check le for errors. */
  138. if (sz < le_min_size || off + sz > ni->attr_list.size ||
  139. sz < le->name_off + le->name_len * sizeof(short)) {
  140. return NULL;
  141. }
  142. return le;
  143. }
  144. /*
  145. * al_find_le
  146. *
  147. * Find the first le in the list which matches type, name and VCN.
  148. *
  149. * Return: NULL if not found.
  150. */
  151. struct ATTR_LIST_ENTRY *al_find_le(struct ntfs_inode *ni,
  152. struct ATTR_LIST_ENTRY *le,
  153. const struct ATTRIB *attr)
  154. {
  155. CLST svcn = attr_svcn(attr);
  156. return al_find_ex(ni, le, attr->type, attr_name(attr), attr->name_len,
  157. &svcn);
  158. }
  159. /*
  160. * al_find_ex
  161. *
  162. * Find the first le in the list which matches type, name and VCN.
  163. *
  164. * Return: NULL if not found.
  165. */
  166. struct ATTR_LIST_ENTRY *al_find_ex(struct ntfs_inode *ni,
  167. struct ATTR_LIST_ENTRY *le,
  168. enum ATTR_TYPE type, const __le16 *name,
  169. u8 name_len, const CLST *vcn)
  170. {
  171. struct ATTR_LIST_ENTRY *ret = NULL;
  172. u32 type_in = le32_to_cpu(type);
  173. while ((le = al_enumerate(ni, le))) {
  174. u64 le_vcn;
  175. int diff = le32_to_cpu(le->type) - type_in;
  176. /* List entries are sorted by type, name and VCN. */
  177. if (diff < 0)
  178. continue;
  179. if (diff > 0)
  180. return ret;
  181. if (le->name_len != name_len)
  182. continue;
  183. le_vcn = le64_to_cpu(le->vcn);
  184. if (!le_vcn) {
  185. /*
  186. * Compare entry names only for entry with vcn == 0.
  187. */
  188. diff = ntfs_cmp_names(le_name(le), name_len, name,
  189. name_len, ni->mi.sbi->upcase,
  190. true);
  191. if (diff < 0)
  192. continue;
  193. if (diff > 0)
  194. return ret;
  195. }
  196. if (!vcn)
  197. return le;
  198. if (*vcn == le_vcn)
  199. return le;
  200. if (*vcn < le_vcn)
  201. return ret;
  202. ret = le;
  203. }
  204. return ret;
  205. }
  206. /*
  207. * al_find_le_to_insert
  208. *
  209. * Find the first list entry which matches type, name and VCN.
  210. */
  211. static struct ATTR_LIST_ENTRY *al_find_le_to_insert(struct ntfs_inode *ni,
  212. enum ATTR_TYPE type,
  213. const __le16 *name,
  214. u8 name_len, CLST vcn)
  215. {
  216. struct ATTR_LIST_ENTRY *le = NULL, *prev;
  217. u32 type_in = le32_to_cpu(type);
  218. /* List entries are sorted by type, name and VCN. */
  219. while ((le = al_enumerate(ni, prev = le))) {
  220. int diff = le32_to_cpu(le->type) - type_in;
  221. if (diff < 0)
  222. continue;
  223. if (diff > 0)
  224. return le;
  225. if (!le->vcn) {
  226. /*
  227. * Compare entry names only for entry with vcn == 0.
  228. */
  229. diff = ntfs_cmp_names(le_name(le), le->name_len, name,
  230. name_len, ni->mi.sbi->upcase,
  231. true);
  232. if (diff < 0)
  233. continue;
  234. if (diff > 0)
  235. return le;
  236. }
  237. if (le64_to_cpu(le->vcn) >= vcn)
  238. return le;
  239. }
  240. return prev ? Add2Ptr(prev, le16_to_cpu(prev->size)) : ni->attr_list.le;
  241. }
  242. /*
  243. * al_add_le
  244. *
  245. * Add an "attribute list entry" to the list.
  246. */
  247. int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
  248. u8 name_len, CLST svcn, __le16 id, const struct MFT_REF *ref,
  249. struct ATTR_LIST_ENTRY **new_le)
  250. {
  251. int err;
  252. struct ATTRIB *attr;
  253. struct ATTR_LIST_ENTRY *le;
  254. size_t off;
  255. u16 sz;
  256. size_t asize, new_asize, old_size;
  257. u64 new_size;
  258. typeof(ni->attr_list) *al = &ni->attr_list;
  259. /*
  260. * Compute the size of the new 'le'
  261. */
  262. sz = le_size(name_len);
  263. old_size = al->size;
  264. new_size = old_size + sz;
  265. asize = al_aligned(old_size);
  266. new_asize = al_aligned(new_size);
  267. /* Scan forward to the point at which the new 'le' should be inserted. */
  268. le = al_find_le_to_insert(ni, type, name, name_len, svcn);
  269. off = PtrOffset(al->le, le);
  270. if (new_size > asize) {
  271. void *ptr = kmalloc(new_asize, GFP_NOFS);
  272. if (!ptr)
  273. return -ENOMEM;
  274. memcpy(ptr, al->le, off);
  275. memcpy(Add2Ptr(ptr, off + sz), le, old_size - off);
  276. le = Add2Ptr(ptr, off);
  277. kvfree(al->le);
  278. al->le = ptr;
  279. } else {
  280. memmove(Add2Ptr(le, sz), le, old_size - off);
  281. }
  282. *new_le = le;
  283. al->size = new_size;
  284. le->type = type;
  285. le->size = cpu_to_le16(sz);
  286. le->name_len = name_len;
  287. le->name_off = offsetof(struct ATTR_LIST_ENTRY, name);
  288. le->vcn = cpu_to_le64(svcn);
  289. le->ref = *ref;
  290. le->id = id;
  291. memcpy(le->name, name, sizeof(short) * name_len);
  292. err = attr_set_size_ex(ni, ATTR_LIST, NULL, 0, &al->run, new_size,
  293. &new_size, true, &attr, false);
  294. if (err) {
  295. /* Undo memmove above. */
  296. memmove(le, Add2Ptr(le, sz), old_size - off);
  297. al->size = old_size;
  298. return err;
  299. }
  300. al->dirty = true;
  301. if (attr && attr->non_res) {
  302. err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
  303. al->size, 0);
  304. if (err)
  305. return err;
  306. al->dirty = false;
  307. }
  308. return 0;
  309. }
  310. /*
  311. * al_remove_le - Remove @le from attribute list.
  312. */
  313. bool al_remove_le(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le)
  314. {
  315. u16 size;
  316. size_t off;
  317. typeof(ni->attr_list) *al = &ni->attr_list;
  318. if (!al_is_valid_le(ni, le))
  319. return false;
  320. /* Save on stack the size of 'le' */
  321. size = le16_to_cpu(le->size);
  322. off = PtrOffset(al->le, le);
  323. memmove(le, Add2Ptr(le, size), al->size - (off + size));
  324. al->size -= size;
  325. al->dirty = true;
  326. return true;
  327. }
  328. int al_update(struct ntfs_inode *ni, int sync)
  329. {
  330. int err;
  331. struct ATTRIB *attr;
  332. typeof(ni->attr_list) *al = &ni->attr_list;
  333. if (!al->dirty || !al->size)
  334. return 0;
  335. /*
  336. * Attribute list increased on demand in al_add_le.
  337. * Attribute list decreased here.
  338. */
  339. err = attr_set_size_ex(ni, ATTR_LIST, NULL, 0, &al->run, al->size, NULL,
  340. false, &attr, false);
  341. if (err)
  342. goto out;
  343. if (!attr->non_res) {
  344. memcpy(resident_data(attr), al->le, al->size);
  345. } else {
  346. err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
  347. al->size, sync);
  348. if (err)
  349. goto out;
  350. attr->nres.valid_size = attr->nres.data_size;
  351. }
  352. ni->mi.dirty = true;
  353. al->dirty = false;
  354. out:
  355. return err;
  356. }