0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/quotaops.h>
0027
0028 #include "ext4.h"
0029 #include "ext4_extents.h"
0030 #include "ext4_jbd2.h"
0031
0032 static inline loff_t ext4_verity_metadata_pos(const struct inode *inode)
0033 {
0034 return round_up(inode->i_size, 65536);
0035 }
0036
0037
0038
0039
0040
0041 static int pagecache_read(struct inode *inode, void *buf, size_t count,
0042 loff_t pos)
0043 {
0044 while (count) {
0045 size_t n = min_t(size_t, count,
0046 PAGE_SIZE - offset_in_page(pos));
0047 struct page *page;
0048
0049 page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT,
0050 NULL);
0051 if (IS_ERR(page))
0052 return PTR_ERR(page);
0053
0054 memcpy_from_page(buf, page, offset_in_page(pos), n);
0055
0056 put_page(page);
0057
0058 buf += n;
0059 pos += n;
0060 count -= n;
0061 }
0062 return 0;
0063 }
0064
0065
0066
0067
0068
0069 static int pagecache_write(struct inode *inode, const void *buf, size_t count,
0070 loff_t pos)
0071 {
0072 struct address_space *mapping = inode->i_mapping;
0073 const struct address_space_operations *aops = mapping->a_ops;
0074
0075 if (pos + count > inode->i_sb->s_maxbytes)
0076 return -EFBIG;
0077
0078 while (count) {
0079 size_t n = min_t(size_t, count,
0080 PAGE_SIZE - offset_in_page(pos));
0081 struct page *page;
0082 void *fsdata;
0083 int res;
0084
0085 res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata);
0086 if (res)
0087 return res;
0088
0089 memcpy_to_page(page, offset_in_page(pos), buf, n);
0090
0091 res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata);
0092 if (res < 0)
0093 return res;
0094 if (res != n)
0095 return -EIO;
0096
0097 buf += n;
0098 pos += n;
0099 count -= n;
0100 }
0101 return 0;
0102 }
0103
0104 static int ext4_begin_enable_verity(struct file *filp)
0105 {
0106 struct inode *inode = file_inode(filp);
0107 const int credits = 2;
0108 handle_t *handle;
0109 int err;
0110
0111 if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX))
0112 return -EINVAL;
0113
0114 if (ext4_verity_in_progress(inode))
0115 return -EBUSY;
0116
0117
0118
0119
0120
0121
0122
0123 err = ext4_inode_attach_jinode(inode);
0124 if (err)
0125 return err;
0126
0127 err = dquot_initialize(inode);
0128 if (err)
0129 return err;
0130
0131 err = ext4_convert_inline_data(inode);
0132 if (err)
0133 return err;
0134
0135 if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
0136 ext4_warning_inode(inode,
0137 "verity is only allowed on extent-based files");
0138 return -EOPNOTSUPP;
0139 }
0140
0141
0142
0143
0144
0145 err = ext4_truncate(inode);
0146 if (err)
0147 return err;
0148
0149 handle = ext4_journal_start(inode, EXT4_HT_INODE, credits);
0150 if (IS_ERR(handle))
0151 return PTR_ERR(handle);
0152
0153 err = ext4_orphan_add(handle, inode);
0154 if (err == 0)
0155 ext4_set_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
0156
0157 ext4_journal_stop(handle);
0158 return err;
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 static int ext4_write_verity_descriptor(struct inode *inode, const void *desc,
0174 size_t desc_size, u64 merkle_tree_size)
0175 {
0176 const u64 desc_pos = round_up(ext4_verity_metadata_pos(inode) +
0177 merkle_tree_size, i_blocksize(inode));
0178 const u64 desc_end = desc_pos + desc_size;
0179 const __le32 desc_size_disk = cpu_to_le32(desc_size);
0180 const u64 desc_size_pos = round_up(desc_end + sizeof(desc_size_disk),
0181 i_blocksize(inode)) -
0182 sizeof(desc_size_disk);
0183 int err;
0184
0185 err = pagecache_write(inode, desc, desc_size, desc_pos);
0186 if (err)
0187 return err;
0188
0189 return pagecache_write(inode, &desc_size_disk, sizeof(desc_size_disk),
0190 desc_size_pos);
0191 }
0192
0193 static int ext4_end_enable_verity(struct file *filp, const void *desc,
0194 size_t desc_size, u64 merkle_tree_size)
0195 {
0196 struct inode *inode = file_inode(filp);
0197 const int credits = 2;
0198 handle_t *handle;
0199 struct ext4_iloc iloc;
0200 int err = 0;
0201
0202
0203
0204
0205
0206 if (desc == NULL)
0207 goto cleanup;
0208
0209
0210 err = ext4_write_verity_descriptor(inode, desc, desc_size,
0211 merkle_tree_size);
0212 if (err)
0213 goto cleanup;
0214
0215
0216
0217
0218
0219
0220
0221 err = filemap_write_and_wait(inode->i_mapping);
0222 if (err)
0223 goto cleanup;
0224
0225
0226
0227
0228
0229
0230 handle = ext4_journal_start(inode, EXT4_HT_INODE, credits);
0231 if (IS_ERR(handle)) {
0232 err = PTR_ERR(handle);
0233 goto cleanup;
0234 }
0235
0236 err = ext4_orphan_del(handle, inode);
0237 if (err)
0238 goto stop_and_cleanup;
0239
0240 err = ext4_reserve_inode_write(handle, inode, &iloc);
0241 if (err)
0242 goto stop_and_cleanup;
0243
0244 ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
0245 ext4_set_inode_flags(inode, false);
0246 err = ext4_mark_iloc_dirty(handle, inode, &iloc);
0247 if (err)
0248 goto stop_and_cleanup;
0249
0250 ext4_journal_stop(handle);
0251
0252 ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
0253 return 0;
0254
0255 stop_and_cleanup:
0256 ext4_journal_stop(handle);
0257 cleanup:
0258
0259
0260
0261
0262
0263
0264 truncate_inode_pages(inode->i_mapping, inode->i_size);
0265 ext4_truncate(inode);
0266 ext4_orphan_del(NULL, inode);
0267 ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
0268 return err;
0269 }
0270
0271 static int ext4_get_verity_descriptor_location(struct inode *inode,
0272 size_t *desc_size_ret,
0273 u64 *desc_pos_ret)
0274 {
0275 struct ext4_ext_path *path;
0276 struct ext4_extent *last_extent;
0277 u32 end_lblk;
0278 u64 desc_size_pos;
0279 __le32 desc_size_disk;
0280 u32 desc_size;
0281 u64 desc_pos;
0282 int err;
0283
0284
0285
0286
0287
0288
0289 if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
0290 EXT4_ERROR_INODE(inode, "verity file doesn't use extents");
0291 return -EFSCORRUPTED;
0292 }
0293
0294 path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
0295 if (IS_ERR(path))
0296 return PTR_ERR(path);
0297
0298 last_extent = path[path->p_depth].p_ext;
0299 if (!last_extent) {
0300 EXT4_ERROR_INODE(inode, "verity file has no extents");
0301 ext4_ext_drop_refs(path);
0302 kfree(path);
0303 return -EFSCORRUPTED;
0304 }
0305
0306 end_lblk = le32_to_cpu(last_extent->ee_block) +
0307 ext4_ext_get_actual_len(last_extent);
0308 desc_size_pos = (u64)end_lblk << inode->i_blkbits;
0309 ext4_ext_drop_refs(path);
0310 kfree(path);
0311
0312 if (desc_size_pos < sizeof(desc_size_disk))
0313 goto bad;
0314 desc_size_pos -= sizeof(desc_size_disk);
0315
0316 err = pagecache_read(inode, &desc_size_disk, sizeof(desc_size_disk),
0317 desc_size_pos);
0318 if (err)
0319 return err;
0320 desc_size = le32_to_cpu(desc_size_disk);
0321
0322
0323
0324
0325
0326
0327 if (desc_size > INT_MAX || desc_size > desc_size_pos)
0328 goto bad;
0329
0330 desc_pos = round_down(desc_size_pos - desc_size, i_blocksize(inode));
0331 if (desc_pos < ext4_verity_metadata_pos(inode))
0332 goto bad;
0333
0334 *desc_size_ret = desc_size;
0335 *desc_pos_ret = desc_pos;
0336 return 0;
0337
0338 bad:
0339 EXT4_ERROR_INODE(inode, "verity file corrupted; can't find descriptor");
0340 return -EFSCORRUPTED;
0341 }
0342
0343 static int ext4_get_verity_descriptor(struct inode *inode, void *buf,
0344 size_t buf_size)
0345 {
0346 size_t desc_size = 0;
0347 u64 desc_pos = 0;
0348 int err;
0349
0350 err = ext4_get_verity_descriptor_location(inode, &desc_size, &desc_pos);
0351 if (err)
0352 return err;
0353
0354 if (buf_size) {
0355 if (desc_size > buf_size)
0356 return -ERANGE;
0357 err = pagecache_read(inode, buf, desc_size, desc_pos);
0358 if (err)
0359 return err;
0360 }
0361 return desc_size;
0362 }
0363
0364 static struct page *ext4_read_merkle_tree_page(struct inode *inode,
0365 pgoff_t index,
0366 unsigned long num_ra_pages)
0367 {
0368 DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
0369 struct page *page;
0370
0371 index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
0372
0373 page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
0374 if (!page || !PageUptodate(page)) {
0375 if (page)
0376 put_page(page);
0377 else if (num_ra_pages > 1)
0378 page_cache_ra_unbounded(&ractl, num_ra_pages, 0);
0379 page = read_mapping_page(inode->i_mapping, index, NULL);
0380 }
0381 return page;
0382 }
0383
0384 static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf,
0385 u64 index, int log_blocksize)
0386 {
0387 loff_t pos = ext4_verity_metadata_pos(inode) + (index << log_blocksize);
0388
0389 return pagecache_write(inode, buf, 1 << log_blocksize, pos);
0390 }
0391
0392 const struct fsverity_operations ext4_verityops = {
0393 .begin_enable_verity = ext4_begin_enable_verity,
0394 .end_enable_verity = ext4_end_enable_verity,
0395 .get_verity_descriptor = ext4_get_verity_descriptor,
0396 .read_merkle_tree_page = ext4_read_merkle_tree_page,
0397 .write_merkle_tree_block = ext4_write_merkle_tree_block,
0398 };