format.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2018 Google LLC
  4. */
  5. #include <linux/fs.h>
  6. #include <linux/file.h>
  7. #include <linux/types.h>
  8. #include <linux/mutex.h>
  9. #include <linux/mm.h>
  10. #include <linux/falloc.h>
  11. #include <linux/slab.h>
  12. #include <linux/crc32.h>
  13. #include <linux/kernel.h>
  14. #include "format.h"
  15. #include "data_mgmt.h"
  16. struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi,
  17. struct file *backing_file)
  18. {
  19. struct backing_file_context *result = NULL;
  20. result = kzalloc(sizeof(*result), GFP_NOFS);
  21. if (!result)
  22. return ERR_PTR(-ENOMEM);
  23. result->bc_file = get_file(backing_file);
  24. result->bc_cred = mi->mi_owner;
  25. mutex_init(&result->bc_mutex);
  26. return result;
  27. }
  28. void incfs_free_bfc(struct backing_file_context *bfc)
  29. {
  30. if (!bfc)
  31. return;
  32. if (bfc->bc_file)
  33. fput(bfc->bc_file);
  34. mutex_destroy(&bfc->bc_mutex);
  35. kfree(bfc);
  36. }
  37. static loff_t incfs_get_end_offset(struct file *f)
  38. {
  39. /*
  40. * This function assumes that file size and the end-offset
  41. * are the same. This is not always true.
  42. */
  43. return i_size_read(file_inode(f));
  44. }
  45. /*
  46. * Truncate the tail of the file to the given length.
  47. * Used to rollback partially successful multistep writes.
  48. */
  49. static int truncate_backing_file(struct backing_file_context *bfc,
  50. loff_t new_end)
  51. {
  52. struct inode *inode = NULL;
  53. struct dentry *dentry = NULL;
  54. loff_t old_end = 0;
  55. struct iattr attr;
  56. int result = 0;
  57. if (!bfc)
  58. return -EFAULT;
  59. LOCK_REQUIRED(bfc->bc_mutex);
  60. if (!bfc->bc_file)
  61. return -EFAULT;
  62. old_end = incfs_get_end_offset(bfc->bc_file);
  63. if (old_end == new_end)
  64. return 0;
  65. if (old_end < new_end)
  66. return -EINVAL;
  67. inode = bfc->bc_file->f_inode;
  68. dentry = bfc->bc_file->f_path.dentry;
  69. attr.ia_size = new_end;
  70. attr.ia_valid = ATTR_SIZE;
  71. inode_lock(inode);
  72. result = notify_change(dentry, &attr, NULL);
  73. inode_unlock(inode);
  74. return result;
  75. }
  76. static int write_to_bf(struct backing_file_context *bfc, const void *buf,
  77. size_t count, loff_t pos)
  78. {
  79. ssize_t res = incfs_kwrite(bfc, buf, count, pos);
  80. if (res < 0)
  81. return res;
  82. if (res != count)
  83. return -EIO;
  84. return 0;
  85. }
  86. static int append_zeros_no_fallocate(struct backing_file_context *bfc,
  87. size_t file_size, size_t len)
  88. {
  89. u8 buffer[256] = {};
  90. size_t i;
  91. for (i = 0; i < len; i += sizeof(buffer)) {
  92. int to_write = len - i > sizeof(buffer)
  93. ? sizeof(buffer) : len - i;
  94. int err = write_to_bf(bfc, buffer, to_write, file_size + i);
  95. if (err)
  96. return err;
  97. }
  98. return 0;
  99. }
  100. /* Append a given number of zero bytes to the end of the backing file. */
  101. static int append_zeros(struct backing_file_context *bfc, size_t len)
  102. {
  103. loff_t file_size = 0;
  104. loff_t new_last_byte_offset = 0;
  105. int result;
  106. if (!bfc)
  107. return -EFAULT;
  108. if (len == 0)
  109. return 0;
  110. LOCK_REQUIRED(bfc->bc_mutex);
  111. /*
  112. * Allocate only one byte at the new desired end of the file.
  113. * It will increase file size and create a zeroed area of
  114. * a given size.
  115. */
  116. file_size = incfs_get_end_offset(bfc->bc_file);
  117. new_last_byte_offset = file_size + len - 1;
  118. result = vfs_fallocate(bfc->bc_file, 0, new_last_byte_offset, 1);
  119. if (result != -EOPNOTSUPP)
  120. return result;
  121. return append_zeros_no_fallocate(bfc, file_size, len);
  122. }
  123. /*
  124. * Append a given metadata record to the backing file and update a previous
  125. * record to add the new record the the metadata list.
  126. */
  127. static int append_md_to_backing_file(struct backing_file_context *bfc,
  128. struct incfs_md_header *record)
  129. {
  130. int result = 0;
  131. loff_t record_offset;
  132. loff_t file_pos;
  133. __le64 new_md_offset;
  134. size_t record_size;
  135. if (!bfc || !record)
  136. return -EFAULT;
  137. if (bfc->bc_last_md_record_offset < 0)
  138. return -EINVAL;
  139. LOCK_REQUIRED(bfc->bc_mutex);
  140. record_size = le16_to_cpu(record->h_record_size);
  141. file_pos = incfs_get_end_offset(bfc->bc_file);
  142. record->h_next_md_offset = 0;
  143. /* Write the metadata record to the end of the backing file */
  144. record_offset = file_pos;
  145. new_md_offset = cpu_to_le64(record_offset);
  146. result = write_to_bf(bfc, record, record_size, file_pos);
  147. if (result)
  148. return result;
  149. /* Update next metadata offset in a previous record or a superblock. */
  150. if (bfc->bc_last_md_record_offset) {
  151. /*
  152. * Find a place in the previous md record where new record's
  153. * offset needs to be saved.
  154. */
  155. file_pos = bfc->bc_last_md_record_offset +
  156. offsetof(struct incfs_md_header, h_next_md_offset);
  157. } else {
  158. /*
  159. * No metadata yet, file a place to update in the
  160. * file_header.
  161. */
  162. file_pos = offsetof(struct incfs_file_header,
  163. fh_first_md_offset);
  164. }
  165. result = write_to_bf(bfc, &new_md_offset, sizeof(new_md_offset),
  166. file_pos);
  167. if (result)
  168. return result;
  169. bfc->bc_last_md_record_offset = record_offset;
  170. return result;
  171. }
  172. /*
  173. * Reserve 0-filled space for the blockmap body, and append
  174. * incfs_blockmap metadata record pointing to it.
  175. */
  176. int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc,
  177. u32 block_count)
  178. {
  179. struct incfs_blockmap blockmap = {};
  180. int result = 0;
  181. loff_t file_end = 0;
  182. size_t map_size = block_count * sizeof(struct incfs_blockmap_entry);
  183. if (!bfc)
  184. return -EFAULT;
  185. blockmap.m_header.h_md_entry_type = INCFS_MD_BLOCK_MAP;
  186. blockmap.m_header.h_record_size = cpu_to_le16(sizeof(blockmap));
  187. blockmap.m_header.h_next_md_offset = cpu_to_le64(0);
  188. blockmap.m_block_count = cpu_to_le32(block_count);
  189. LOCK_REQUIRED(bfc->bc_mutex);
  190. /* Reserve 0-filled space for the blockmap body in the backing file. */
  191. file_end = incfs_get_end_offset(bfc->bc_file);
  192. result = append_zeros(bfc, map_size);
  193. if (result)
  194. return result;
  195. /* Write blockmap metadata record pointing to the body written above. */
  196. blockmap.m_base_offset = cpu_to_le64(file_end);
  197. result = append_md_to_backing_file(bfc, &blockmap.m_header);
  198. if (result)
  199. /* Error, rollback file changes */
  200. truncate_backing_file(bfc, file_end);
  201. return result;
  202. }
  203. int incfs_write_signature_to_backing_file(struct backing_file_context *bfc,
  204. struct mem_range sig, u32 tree_size,
  205. loff_t *tree_offset, loff_t *sig_offset)
  206. {
  207. struct incfs_file_signature sg = {};
  208. int result = 0;
  209. loff_t rollback_pos = 0;
  210. loff_t tree_area_pos = 0;
  211. size_t alignment = 0;
  212. if (!bfc)
  213. return -EFAULT;
  214. LOCK_REQUIRED(bfc->bc_mutex);
  215. rollback_pos = incfs_get_end_offset(bfc->bc_file);
  216. sg.sg_header.h_md_entry_type = INCFS_MD_SIGNATURE;
  217. sg.sg_header.h_record_size = cpu_to_le16(sizeof(sg));
  218. sg.sg_header.h_next_md_offset = cpu_to_le64(0);
  219. if (sig.data != NULL && sig.len > 0) {
  220. sg.sg_sig_size = cpu_to_le32(sig.len);
  221. sg.sg_sig_offset = cpu_to_le64(rollback_pos);
  222. result = write_to_bf(bfc, sig.data, sig.len, rollback_pos);
  223. if (result)
  224. goto err;
  225. }
  226. tree_area_pos = incfs_get_end_offset(bfc->bc_file);
  227. if (tree_size > 0) {
  228. if (tree_size > 5 * INCFS_DATA_FILE_BLOCK_SIZE) {
  229. /*
  230. * If hash tree is big enough, it makes sense to
  231. * align in the backing file for faster access.
  232. */
  233. loff_t offset = round_up(tree_area_pos, PAGE_SIZE);
  234. alignment = offset - tree_area_pos;
  235. tree_area_pos = offset;
  236. }
  237. /*
  238. * If root hash is not the only hash in the tree.
  239. * reserve 0-filled space for the tree.
  240. */
  241. result = append_zeros(bfc, tree_size + alignment);
  242. if (result)
  243. goto err;
  244. sg.sg_hash_tree_size = cpu_to_le32(tree_size);
  245. sg.sg_hash_tree_offset = cpu_to_le64(tree_area_pos);
  246. }
  247. /* Write a hash tree metadata record pointing to the hash tree above. */
  248. result = append_md_to_backing_file(bfc, &sg.sg_header);
  249. err:
  250. if (result)
  251. /* Error, rollback file changes */
  252. truncate_backing_file(bfc, rollback_pos);
  253. else {
  254. if (tree_offset)
  255. *tree_offset = tree_area_pos;
  256. if (sig_offset)
  257. *sig_offset = rollback_pos;
  258. }
  259. return result;
  260. }
  261. static int write_new_status_to_backing_file(struct backing_file_context *bfc,
  262. u32 data_blocks_written,
  263. u32 hash_blocks_written)
  264. {
  265. int result;
  266. loff_t rollback_pos;
  267. struct incfs_status is = {
  268. .is_header = {
  269. .h_md_entry_type = INCFS_MD_STATUS,
  270. .h_record_size = cpu_to_le16(sizeof(is)),
  271. },
  272. .is_data_blocks_written = cpu_to_le32(data_blocks_written),
  273. .is_hash_blocks_written = cpu_to_le32(hash_blocks_written),
  274. };
  275. LOCK_REQUIRED(bfc->bc_mutex);
  276. rollback_pos = incfs_get_end_offset(bfc->bc_file);
  277. result = append_md_to_backing_file(bfc, &is.is_header);
  278. if (result)
  279. truncate_backing_file(bfc, rollback_pos);
  280. return result;
  281. }
  282. int incfs_write_status_to_backing_file(struct backing_file_context *bfc,
  283. loff_t status_offset,
  284. u32 data_blocks_written,
  285. u32 hash_blocks_written)
  286. {
  287. struct incfs_status is;
  288. int result;
  289. if (!bfc)
  290. return -EFAULT;
  291. if (status_offset == 0)
  292. return write_new_status_to_backing_file(bfc,
  293. data_blocks_written, hash_blocks_written);
  294. result = incfs_kread(bfc, &is, sizeof(is), status_offset);
  295. if (result != sizeof(is))
  296. return -EIO;
  297. is.is_data_blocks_written = cpu_to_le32(data_blocks_written);
  298. is.is_hash_blocks_written = cpu_to_le32(hash_blocks_written);
  299. result = incfs_kwrite(bfc, &is, sizeof(is), status_offset);
  300. if (result != sizeof(is))
  301. return -EIO;
  302. return 0;
  303. }
  304. int incfs_write_verity_signature_to_backing_file(
  305. struct backing_file_context *bfc, struct mem_range signature,
  306. loff_t *offset)
  307. {
  308. struct incfs_file_verity_signature vs = {};
  309. int result;
  310. loff_t pos;
  311. /* No verity signature section is equivalent to an empty section */
  312. if (signature.data == NULL || signature.len == 0)
  313. return 0;
  314. pos = incfs_get_end_offset(bfc->bc_file);
  315. vs = (struct incfs_file_verity_signature) {
  316. .vs_header = (struct incfs_md_header) {
  317. .h_md_entry_type = INCFS_MD_VERITY_SIGNATURE,
  318. .h_record_size = cpu_to_le16(sizeof(vs)),
  319. .h_next_md_offset = cpu_to_le64(0),
  320. },
  321. .vs_size = cpu_to_le32(signature.len),
  322. .vs_offset = cpu_to_le64(pos),
  323. };
  324. result = write_to_bf(bfc, signature.data, signature.len, pos);
  325. if (result)
  326. goto err;
  327. result = append_md_to_backing_file(bfc, &vs.vs_header);
  328. if (result)
  329. goto err;
  330. *offset = pos;
  331. err:
  332. if (result)
  333. /* Error, rollback file changes */
  334. truncate_backing_file(bfc, pos);
  335. return result;
  336. }
  337. /*
  338. * Write a backing file header
  339. * It should always be called only on empty file.
  340. * fh.fh_first_md_offset is 0 for now, but will be updated
  341. * once first metadata record is added.
  342. */
  343. int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
  344. incfs_uuid_t *uuid, u64 file_size)
  345. {
  346. struct incfs_file_header fh = {};
  347. loff_t file_pos = 0;
  348. if (!bfc)
  349. return -EFAULT;
  350. fh.fh_magic = cpu_to_le64(INCFS_MAGIC_NUMBER);
  351. fh.fh_version = cpu_to_le64(INCFS_FORMAT_CURRENT_VER);
  352. fh.fh_header_size = cpu_to_le16(sizeof(fh));
  353. fh.fh_first_md_offset = cpu_to_le64(0);
  354. fh.fh_data_block_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
  355. fh.fh_file_size = cpu_to_le64(file_size);
  356. fh.fh_uuid = *uuid;
  357. LOCK_REQUIRED(bfc->bc_mutex);
  358. file_pos = incfs_get_end_offset(bfc->bc_file);
  359. if (file_pos != 0)
  360. return -EEXIST;
  361. return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
  362. }
  363. /*
  364. * Write a backing file header for a mapping file
  365. * It should always be called only on empty file.
  366. */
  367. int incfs_write_mapping_fh_to_backing_file(struct backing_file_context *bfc,
  368. incfs_uuid_t *uuid, u64 file_size, u64 offset)
  369. {
  370. struct incfs_file_header fh = {};
  371. loff_t file_pos = 0;
  372. if (!bfc)
  373. return -EFAULT;
  374. fh.fh_magic = cpu_to_le64(INCFS_MAGIC_NUMBER);
  375. fh.fh_version = cpu_to_le64(INCFS_FORMAT_CURRENT_VER);
  376. fh.fh_header_size = cpu_to_le16(sizeof(fh));
  377. fh.fh_original_offset = cpu_to_le64(offset);
  378. fh.fh_data_block_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
  379. fh.fh_mapped_file_size = cpu_to_le64(file_size);
  380. fh.fh_original_uuid = *uuid;
  381. fh.fh_flags = cpu_to_le32(INCFS_FILE_MAPPED);
  382. LOCK_REQUIRED(bfc->bc_mutex);
  383. file_pos = incfs_get_end_offset(bfc->bc_file);
  384. if (file_pos != 0)
  385. return -EEXIST;
  386. return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
  387. }
  388. /* Write a given data block and update file's blockmap to point it. */
  389. int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
  390. struct mem_range block, int block_index,
  391. loff_t bm_base_off, u16 flags)
  392. {
  393. struct incfs_blockmap_entry bm_entry = {};
  394. int result = 0;
  395. loff_t data_offset = 0;
  396. loff_t bm_entry_off =
  397. bm_base_off + sizeof(struct incfs_blockmap_entry) * block_index;
  398. if (!bfc)
  399. return -EFAULT;
  400. if (block.len >= (1 << 16) || block_index < 0)
  401. return -EINVAL;
  402. LOCK_REQUIRED(bfc->bc_mutex);
  403. data_offset = incfs_get_end_offset(bfc->bc_file);
  404. if (data_offset <= bm_entry_off) {
  405. /* Blockmap entry is beyond the file's end. It is not normal. */
  406. return -EINVAL;
  407. }
  408. /* Write the block data at the end of the backing file. */
  409. result = write_to_bf(bfc, block.data, block.len, data_offset);
  410. if (result)
  411. return result;
  412. /* Update the blockmap to point to the newly written data. */
  413. bm_entry.me_data_offset_lo = cpu_to_le32((u32)data_offset);
  414. bm_entry.me_data_offset_hi = cpu_to_le16((u16)(data_offset >> 32));
  415. bm_entry.me_data_size = cpu_to_le16((u16)block.len);
  416. bm_entry.me_flags = cpu_to_le16(flags);
  417. return write_to_bf(bfc, &bm_entry, sizeof(bm_entry),
  418. bm_entry_off);
  419. }
  420. int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc,
  421. struct mem_range block,
  422. int block_index,
  423. loff_t hash_area_off,
  424. loff_t bm_base_off,
  425. loff_t file_size)
  426. {
  427. struct incfs_blockmap_entry bm_entry = {};
  428. int result;
  429. loff_t data_offset = 0;
  430. loff_t file_end = 0;
  431. loff_t bm_entry_off =
  432. bm_base_off +
  433. sizeof(struct incfs_blockmap_entry) *
  434. (block_index + get_blocks_count_for_size(file_size));
  435. if (!bfc)
  436. return -EFAULT;
  437. LOCK_REQUIRED(bfc->bc_mutex);
  438. data_offset = hash_area_off + block_index * INCFS_DATA_FILE_BLOCK_SIZE;
  439. file_end = incfs_get_end_offset(bfc->bc_file);
  440. if (data_offset + block.len > file_end) {
  441. /* Block is located beyond the file's end. It is not normal. */
  442. return -EINVAL;
  443. }
  444. result = write_to_bf(bfc, block.data, block.len, data_offset);
  445. if (result)
  446. return result;
  447. bm_entry.me_data_offset_lo = cpu_to_le32((u32)data_offset);
  448. bm_entry.me_data_offset_hi = cpu_to_le16((u16)(data_offset >> 32));
  449. bm_entry.me_data_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
  450. return write_to_bf(bfc, &bm_entry, sizeof(bm_entry), bm_entry_off);
  451. }
  452. int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index,
  453. loff_t bm_base_off,
  454. struct incfs_blockmap_entry *bm_entry)
  455. {
  456. int error = incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1,
  457. bm_base_off);
  458. if (error < 0)
  459. return error;
  460. if (error == 0)
  461. return -EIO;
  462. if (error != 1)
  463. return -EFAULT;
  464. return 0;
  465. }
  466. int incfs_read_blockmap_entries(struct backing_file_context *bfc,
  467. struct incfs_blockmap_entry *entries,
  468. int start_index, int blocks_number,
  469. loff_t bm_base_off)
  470. {
  471. loff_t bm_entry_off =
  472. bm_base_off + sizeof(struct incfs_blockmap_entry) * start_index;
  473. const size_t bytes_to_read = sizeof(struct incfs_blockmap_entry)
  474. * blocks_number;
  475. int result = 0;
  476. if (!bfc || !entries)
  477. return -EFAULT;
  478. if (start_index < 0 || bm_base_off <= 0)
  479. return -ENODATA;
  480. result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off);
  481. if (result < 0)
  482. return result;
  483. return result / sizeof(*entries);
  484. }
  485. int incfs_read_file_header(struct backing_file_context *bfc,
  486. loff_t *first_md_off, incfs_uuid_t *uuid,
  487. u64 *file_size, u32 *flags)
  488. {
  489. ssize_t bytes_read = 0;
  490. struct incfs_file_header fh = {};
  491. if (!bfc || !first_md_off)
  492. return -EFAULT;
  493. bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0);
  494. if (bytes_read < 0)
  495. return bytes_read;
  496. if (bytes_read < sizeof(fh))
  497. return -EBADMSG;
  498. if (le64_to_cpu(fh.fh_magic) != INCFS_MAGIC_NUMBER)
  499. return -EILSEQ;
  500. if (le64_to_cpu(fh.fh_version) > INCFS_FORMAT_CURRENT_VER)
  501. return -EILSEQ;
  502. if (le16_to_cpu(fh.fh_data_block_size) != INCFS_DATA_FILE_BLOCK_SIZE)
  503. return -EILSEQ;
  504. if (le16_to_cpu(fh.fh_header_size) != sizeof(fh))
  505. return -EILSEQ;
  506. if (first_md_off)
  507. *first_md_off = le64_to_cpu(fh.fh_first_md_offset);
  508. if (uuid)
  509. *uuid = fh.fh_uuid;
  510. if (file_size)
  511. *file_size = le64_to_cpu(fh.fh_file_size);
  512. if (flags)
  513. *flags = le32_to_cpu(fh.fh_flags);
  514. return 0;
  515. }
  516. /*
  517. * Read through metadata records from the backing file one by one
  518. * and call provided metadata handlers.
  519. */
  520. int incfs_read_next_metadata_record(struct backing_file_context *bfc,
  521. struct metadata_handler *handler)
  522. {
  523. const ssize_t max_md_size = INCFS_MAX_METADATA_RECORD_SIZE;
  524. ssize_t bytes_read = 0;
  525. size_t md_record_size = 0;
  526. loff_t next_record = 0;
  527. int res = 0;
  528. struct incfs_md_header *md_hdr = NULL;
  529. if (!bfc || !handler)
  530. return -EFAULT;
  531. if (handler->md_record_offset == 0)
  532. return -EPERM;
  533. memset(&handler->md_buffer, 0, max_md_size);
  534. bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size,
  535. handler->md_record_offset);
  536. if (bytes_read < 0)
  537. return bytes_read;
  538. if (bytes_read < sizeof(*md_hdr))
  539. return -EBADMSG;
  540. md_hdr = &handler->md_buffer.md_header;
  541. next_record = le64_to_cpu(md_hdr->h_next_md_offset);
  542. md_record_size = le16_to_cpu(md_hdr->h_record_size);
  543. if (md_record_size > max_md_size) {
  544. pr_warn("incfs: The record is too large. Size: %zu",
  545. md_record_size);
  546. return -EBADMSG;
  547. }
  548. if (bytes_read < md_record_size) {
  549. pr_warn("incfs: The record hasn't been fully read.");
  550. return -EBADMSG;
  551. }
  552. if (next_record <= handler->md_record_offset && next_record != 0) {
  553. pr_warn("incfs: Next record (%lld) points back in file.",
  554. next_record);
  555. return -EBADMSG;
  556. }
  557. switch (md_hdr->h_md_entry_type) {
  558. case INCFS_MD_NONE:
  559. break;
  560. case INCFS_MD_BLOCK_MAP:
  561. if (handler->handle_blockmap)
  562. res = handler->handle_blockmap(
  563. &handler->md_buffer.blockmap, handler);
  564. break;
  565. case INCFS_MD_FILE_ATTR:
  566. /*
  567. * File attrs no longer supported, ignore section for
  568. * compatibility
  569. */
  570. break;
  571. case INCFS_MD_SIGNATURE:
  572. if (handler->handle_signature)
  573. res = handler->handle_signature(
  574. &handler->md_buffer.signature, handler);
  575. break;
  576. case INCFS_MD_STATUS:
  577. if (handler->handle_status)
  578. res = handler->handle_status(
  579. &handler->md_buffer.status, handler);
  580. break;
  581. case INCFS_MD_VERITY_SIGNATURE:
  582. if (handler->handle_verity_signature)
  583. res = handler->handle_verity_signature(
  584. &handler->md_buffer.verity_signature, handler);
  585. break;
  586. default:
  587. res = -ENOTSUPP;
  588. break;
  589. }
  590. if (!res) {
  591. if (next_record == 0) {
  592. /*
  593. * Zero offset for the next record means that the last
  594. * metadata record has just been processed.
  595. */
  596. bfc->bc_last_md_record_offset =
  597. handler->md_record_offset;
  598. }
  599. handler->md_prev_record_offset = handler->md_record_offset;
  600. handler->md_record_offset = next_record;
  601. }
  602. return res;
  603. }
  604. ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size,
  605. loff_t pos)
  606. {
  607. const struct cred *old_cred = override_creds(bfc->bc_cred);
  608. int ret = kernel_read(bfc->bc_file, buf, size, &pos);
  609. revert_creds(old_cred);
  610. return ret;
  611. }
  612. ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf,
  613. size_t size, loff_t pos)
  614. {
  615. const struct cred *old_cred = override_creds(bfc->bc_cred);
  616. int ret = kernel_write(bfc->bc_file, buf, size, &pos);
  617. revert_creds(old_cred);
  618. return ret;
  619. }