Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: add fs-verity support

Add fs-verity support to f2fs. fs-verity is a filesystem feature that
enables transparent integrity protection and authentication of read-only
files. It uses a dm-verity like mechanism at the file level: a Merkle
tree is used to verify any block in the file in log(filesize) time. It
is implemented mainly by helper functions in fs/verity/. See
Documentation/filesystems/fsverity.rst for the full documentation.

The f2fs support for fs-verity consists of:

- Adding a filesystem feature flag and an inode flag for fs-verity.

- Implementing the fsverity_operations to support enabling verity on an
inode and reading/writing the verity metadata.

- Updating ->readpages() to verify data as it's read from verity files
and to support reading verity metadata pages.

- Updating ->write_begin(), ->write_end(), and ->writepages() to support
writing verity metadata pages.

- Calling the fs-verity hooks for ->open(), ->setattr(), and ->ioctl().

Like ext4, f2fs stores the verity metadata (Merkle tree and
fsverity_descriptor) past the end of the file, starting at the first 64K
boundary beyond i_size. This approach works because (a) verity files
are readonly, and (b) pages fully beyond i_size aren't visible to
userspace but can be read/written internally by f2fs with only some
relatively small changes to f2fs. Extended attributes cannot be used
because (a) f2fs limits the total size of an inode's xattr entries to
4096 bytes, which wouldn't be enough for even a single Merkle tree
block, and (b) f2fs encryption doesn't encrypt xattrs, yet the verity
metadata *must* be encrypted when the file is because it contains hashes
of the plaintext data.

Acked-by: Jaegeuk Kim <jaegeuk@kernel.org>
Acked-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>

+392 -15
+1
fs/f2fs/Makefile
··· 8 8 f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o 9 9 f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o 10 10 f2fs-$(CONFIG_F2FS_IO_TRACE) += trace.o 11 + f2fs-$(CONFIG_FS_VERITY) += verity.o
+65 -10
fs/f2fs/data.c
··· 74 74 enum bio_post_read_step { 75 75 STEP_INITIAL = 0, 76 76 STEP_DECRYPT, 77 + STEP_VERITY, 77 78 }; 78 79 79 80 struct bio_post_read_ctx { ··· 121 120 bio_post_read_processing(ctx); 122 121 } 123 122 123 + static void verity_work(struct work_struct *work) 124 + { 125 + struct bio_post_read_ctx *ctx = 126 + container_of(work, struct bio_post_read_ctx, work); 127 + 128 + fsverity_verify_bio(ctx->bio); 129 + 130 + bio_post_read_processing(ctx); 131 + } 132 + 124 133 static void bio_post_read_processing(struct bio_post_read_ctx *ctx) 125 134 { 135 + /* 136 + * We use different work queues for decryption and for verity because 137 + * verity may require reading metadata pages that need decryption, and 138 + * we shouldn't recurse to the same workqueue. 139 + */ 126 140 switch (++ctx->cur_step) { 127 141 case STEP_DECRYPT: 128 142 if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { 129 143 INIT_WORK(&ctx->work, decrypt_work); 130 144 fscrypt_enqueue_decrypt_work(&ctx->work); 145 + return; 146 + } 147 + ctx->cur_step++; 148 + /* fall-through */ 149 + case STEP_VERITY: 150 + if (ctx->enabled_steps & (1 << STEP_VERITY)) { 151 + INIT_WORK(&ctx->work, verity_work); 152 + fsverity_enqueue_verify_work(&ctx->work); 131 153 return; 132 154 } 133 155 ctx->cur_step++; ··· 632 608 up_write(&io->io_rwsem); 633 609 } 634 610 611 + static inline bool f2fs_need_verity(const struct inode *inode, pgoff_t idx) 612 + { 613 + return fsverity_active(inode) && 614 + idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE); 615 + } 616 + 635 617 static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, 636 - unsigned nr_pages, unsigned op_flag) 618 + unsigned nr_pages, unsigned op_flag, 619 + pgoff_t first_idx) 637 620 { 638 621 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 639 622 struct bio *bio; ··· 656 625 657 626 if (f2fs_encrypted_file(inode)) 658 627 post_read_steps |= 1 << STEP_DECRYPT; 628 + 629 + if (f2fs_need_verity(inode, first_idx)) 630 + post_read_steps |= 1 << STEP_VERITY; 631 + 659 632 if (post_read_steps) { 660 633 ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); 661 634 if (!ctx) { ··· 681 646 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 682 647 struct bio *bio; 683 648 684 - bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0); 649 + bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0, page->index); 685 650 if (IS_ERR(bio)) 686 651 return PTR_ERR(bio); 687 652 ··· 1604 1569 return ret; 1605 1570 } 1606 1571 1572 + static inline loff_t f2fs_readpage_limit(struct inode *inode) 1573 + { 1574 + if (IS_ENABLED(CONFIG_FS_VERITY) && 1575 + (IS_VERITY(inode) || f2fs_verity_in_progress(inode))) 1576 + return inode->i_sb->s_maxbytes; 1577 + 1578 + return i_size_read(inode); 1579 + } 1580 + 1607 1581 static int f2fs_read_single_page(struct inode *inode, struct page *page, 1608 1582 unsigned nr_pages, 1609 1583 struct f2fs_map_blocks *map, ··· 1631 1587 1632 1588 block_in_file = (sector_t)page_index(page); 1633 1589 last_block = block_in_file + nr_pages; 1634 - last_block_in_file = (i_size_read(inode) + blocksize - 1) >> 1590 + last_block_in_file = (f2fs_readpage_limit(inode) + blocksize - 1) >> 1635 1591 blkbits; 1636 1592 if (last_block > last_block_in_file) 1637 1593 last_block = last_block_in_file; ··· 1676 1632 } else { 1677 1633 zero_out: 1678 1634 zero_user_segment(page, 0, PAGE_SIZE); 1635 + if (f2fs_need_verity(inode, page->index) && 1636 + !fsverity_verify_page(page)) { 1637 + ret = -EIO; 1638 + goto out; 1639 + } 1679 1640 if (!PageUptodate(page)) 1680 1641 SetPageUptodate(page); 1681 1642 unlock_page(page); ··· 1699 1650 } 1700 1651 if (bio == NULL) { 1701 1652 bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, 1702 - is_readahead ? REQ_RAHEAD : 0); 1653 + is_readahead ? REQ_RAHEAD : 0, page->index); 1703 1654 if (IS_ERR(bio)) { 1704 1655 ret = PTR_ERR(bio); 1705 1656 bio = NULL; ··· 2101 2052 if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 2102 2053 goto redirty_out; 2103 2054 2104 - if (page->index < end_index) 2055 + if (page->index < end_index || f2fs_verity_in_progress(inode)) 2105 2056 goto write; 2106 2057 2107 2058 /* ··· 2476 2427 struct inode *inode = mapping->host; 2477 2428 loff_t i_size = i_size_read(inode); 2478 2429 2479 - if (to > i_size) { 2430 + /* In the fs-verity case, f2fs_end_enable_verity() does the truncate */ 2431 + if (to > i_size && !f2fs_verity_in_progress(inode)) { 2480 2432 down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 2481 2433 down_write(&F2FS_I(inode)->i_mmap_sem); 2482 2434 ··· 2508 2458 * the block addresses when there is no need to fill the page. 2509 2459 */ 2510 2460 if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && 2511 - !is_inode_flag_set(inode, FI_NO_PREALLOC)) 2461 + !is_inode_flag_set(inode, FI_NO_PREALLOC) && 2462 + !f2fs_verity_in_progress(inode)) 2512 2463 return 0; 2513 2464 2514 2465 /* f2fs_lock_op avoids race between write CP and convert_inline_page */ ··· 2648 2597 if (len == PAGE_SIZE || PageUptodate(page)) 2649 2598 return 0; 2650 2599 2651 - if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode)) { 2600 + if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && 2601 + !f2fs_verity_in_progress(inode)) { 2652 2602 zero_user_segment(page, len, PAGE_SIZE); 2653 2603 return 0; 2654 2604 } ··· 2712 2660 2713 2661 set_page_dirty(page); 2714 2662 2715 - if (pos + copied > i_size_read(inode)) 2663 + if (pos + copied > i_size_read(inode) && 2664 + !f2fs_verity_in_progress(inode)) 2716 2665 f2fs_i_size_write(inode, pos + copied); 2717 2666 unlock_out: 2718 2667 f2fs_put_page(page, 1); ··· 3157 3104 3158 3105 int __init f2fs_init_post_read_processing(void) 3159 3106 { 3160 - bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0); 3107 + bio_post_read_ctx_cache = 3108 + kmem_cache_create("f2fs_bio_post_read_ctx", 3109 + sizeof(struct bio_post_read_ctx), 0, 0, NULL); 3161 3110 if (!bio_post_read_ctx_cache) 3162 3111 goto fail; 3163 3112 bio_post_read_ctx_pool =
+17 -3
fs/f2fs/f2fs.h
··· 25 25 #include <crypto/hash.h> 26 26 27 27 #include <linux/fscrypt.h> 28 + #include <linux/fsverity.h> 28 29 29 30 #ifdef CONFIG_F2FS_CHECK_FS 30 31 #define f2fs_bug_on(sbi, condition) BUG_ON(condition) ··· 152 151 #define F2FS_FEATURE_QUOTA_INO 0x0080 153 152 #define F2FS_FEATURE_INODE_CRTIME 0x0100 154 153 #define F2FS_FEATURE_LOST_FOUND 0x0200 155 - #define F2FS_FEATURE_VERITY 0x0400 /* reserved */ 154 + #define F2FS_FEATURE_VERITY 0x0400 156 155 #define F2FS_FEATURE_SB_CHKSUM 0x0800 157 156 158 157 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ··· 631 630 #define FADVISE_ENC_NAME_BIT 0x08 632 631 #define FADVISE_KEEP_SIZE_BIT 0x10 633 632 #define FADVISE_HOT_BIT 0x20 634 - #define FADVISE_VERITY_BIT 0x40 /* reserved */ 633 + #define FADVISE_VERITY_BIT 0x40 635 634 636 635 #define FADVISE_MODIFIABLE_BITS (FADVISE_COLD_BIT | FADVISE_HOT_BIT) 637 636 ··· 651 650 #define file_is_hot(inode) is_file(inode, FADVISE_HOT_BIT) 652 651 #define file_set_hot(inode) set_file(inode, FADVISE_HOT_BIT) 653 652 #define file_clear_hot(inode) clear_file(inode, FADVISE_HOT_BIT) 653 + #define file_is_verity(inode) is_file(inode, FADVISE_VERITY_BIT) 654 + #define file_set_verity(inode) set_file(inode, FADVISE_VERITY_BIT) 654 655 655 656 #define DEF_DIR_LEVEL 0 656 657 ··· 2415 2412 FI_PROJ_INHERIT, /* indicate file inherits projectid */ 2416 2413 FI_PIN_FILE, /* indicate file should not be gced */ 2417 2414 FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */ 2415 + FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ 2418 2416 }; 2419 2417 2420 2418 static inline void __mark_inode_dirty_flag(struct inode *inode, ··· 2453 2449 if (test_bit(flag, &F2FS_I(inode)->flags)) 2454 2450 clear_bit(flag, &F2FS_I(inode)->flags); 2455 2451 __mark_inode_dirty_flag(inode, flag, false); 2452 + } 2453 + 2454 + static inline bool f2fs_verity_in_progress(struct inode *inode) 2455 + { 2456 + return IS_ENABLED(CONFIG_FS_VERITY) && 2457 + is_inode_flag_set(inode, FI_VERITY_IN_PROGRESS); 2456 2458 } 2457 2459 2458 2460 static inline void set_acl_inode(struct inode *inode, umode_t mode) ··· 3531 3521 int f2fs_register_sysfs(struct f2fs_sb_info *sbi); 3532 3522 void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi); 3533 3523 3524 + /* verity.c */ 3525 + extern const struct fsverity_operations f2fs_verityops; 3526 + 3534 3527 /* 3535 3528 * crypto support 3536 3529 */ ··· 3556 3543 */ 3557 3544 static inline bool f2fs_post_read_required(struct inode *inode) 3558 3545 { 3559 - return f2fs_encrypted_file(inode); 3546 + return f2fs_encrypted_file(inode) || fsverity_active(inode); 3560 3547 } 3561 3548 3562 3549 #define F2FS_FEATURE_FUNCS(name, flagname) \ ··· 3574 3561 F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); 3575 3562 F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); 3576 3563 F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); 3564 + F2FS_FEATURE_FUNCS(verity, VERITY); 3577 3565 F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); 3578 3566 3579 3567 #ifdef CONFIG_BLK_DEV_ZONED
+42 -1
fs/f2fs/file.c
··· 496 496 if (err) 497 497 return err; 498 498 499 + err = fsverity_file_open(inode, filp); 500 + if (err) 501 + return err; 502 + 499 503 filp->f_mode |= FMODE_NOWAIT; 500 504 501 505 return dquot_file_open(inode, filp); ··· 779 775 return err; 780 776 781 777 err = fscrypt_prepare_setattr(dentry, attr); 778 + if (err) 779 + return err; 780 + 781 + err = fsverity_prepare_setattr(dentry, attr); 782 782 if (err) 783 783 return err; 784 784 ··· 1720 1712 FS_PROJINHERIT_FL | \ 1721 1713 FS_ENCRYPT_FL | \ 1722 1714 FS_INLINE_DATA_FL | \ 1723 - FS_NOCOW_FL) 1715 + FS_NOCOW_FL | \ 1716 + FS_VERITY_FL) 1724 1717 1725 1718 #define F2FS_SETTABLE_FS_FL ( \ 1726 1719 FS_SYNC_FL | \ ··· 1766 1757 1767 1758 if (IS_ENCRYPTED(inode)) 1768 1759 fsflags |= FS_ENCRYPT_FL; 1760 + if (IS_VERITY(inode)) 1761 + fsflags |= FS_VERITY_FL; 1769 1762 if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) 1770 1763 fsflags |= FS_INLINE_DATA_FL; 1771 1764 if (is_inode_flag_set(inode, FI_PIN_FILE)) ··· 3088 3077 return ret; 3089 3078 } 3090 3079 3080 + static int f2fs_ioc_enable_verity(struct file *filp, unsigned long arg) 3081 + { 3082 + struct inode *inode = file_inode(filp); 3083 + 3084 + f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 3085 + 3086 + if (!f2fs_sb_has_verity(F2FS_I_SB(inode))) { 3087 + f2fs_warn(F2FS_I_SB(inode), 3088 + "Can't enable fs-verity on inode %lu: the verity feature is not enabled on this filesystem.\n", 3089 + inode->i_ino); 3090 + return -EOPNOTSUPP; 3091 + } 3092 + 3093 + return fsverity_ioctl_enable(filp, (const void __user *)arg); 3094 + } 3095 + 3096 + static int f2fs_ioc_measure_verity(struct file *filp, unsigned long arg) 3097 + { 3098 + if (!f2fs_sb_has_verity(F2FS_I_SB(file_inode(filp)))) 3099 + return -EOPNOTSUPP; 3100 + 3101 + return fsverity_ioctl_measure(filp, (void __user *)arg); 3102 + } 3103 + 3091 3104 long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 3092 3105 { 3093 3106 if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) ··· 3170 3135 return f2fs_ioc_precache_extents(filp, arg); 3171 3136 case F2FS_IOC_RESIZE_FS: 3172 3137 return f2fs_ioc_resize_fs(filp, arg); 3138 + case FS_IOC_ENABLE_VERITY: 3139 + return f2fs_ioc_enable_verity(filp, arg); 3140 + case FS_IOC_MEASURE_VERITY: 3141 + return f2fs_ioc_measure_verity(filp, arg); 3173 3142 default: 3174 3143 return -ENOTTY; 3175 3144 } ··· 3288 3249 case F2FS_IOC_SET_PIN_FILE: 3289 3250 case F2FS_IOC_PRECACHE_EXTENTS: 3290 3251 case F2FS_IOC_RESIZE_FS: 3252 + case FS_IOC_ENABLE_VERITY: 3253 + case FS_IOC_MEASURE_VERITY: 3291 3254 break; 3292 3255 default: 3293 3256 return -ENOIOCTLCMD;
+4 -1
fs/f2fs/inode.c
··· 46 46 new_fl |= S_DIRSYNC; 47 47 if (file_is_encrypt(inode)) 48 48 new_fl |= S_ENCRYPTED; 49 + if (file_is_verity(inode)) 50 + new_fl |= S_VERITY; 49 51 inode_set_flags(inode, new_fl, 50 52 S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| 51 - S_ENCRYPTED); 53 + S_ENCRYPTED|S_VERITY); 52 54 } 53 55 54 56 static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) ··· 735 733 } 736 734 out_clear: 737 735 fscrypt_put_encryption_info(inode); 736 + fsverity_cleanup_inode(inode); 738 737 clear_inode(inode); 739 738 } 740 739
+3
fs/f2fs/super.c
··· 3144 3144 #ifdef CONFIG_FS_ENCRYPTION 3145 3145 sb->s_cop = &f2fs_cryptops; 3146 3146 #endif 3147 + #ifdef CONFIG_FS_VERITY 3148 + sb->s_vop = &f2fs_verityops; 3149 + #endif 3147 3150 sb->s_xattr = f2fs_xattr_handlers; 3148 3151 sb->s_export_op = &f2fs_export_ops; 3149 3152 sb->s_magic = F2FS_SUPER_MAGIC;
+11
fs/f2fs/sysfs.c
··· 131 131 if (f2fs_sb_has_lost_found(sbi)) 132 132 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", 133 133 len ? ", " : "", "lost_found"); 134 + if (f2fs_sb_has_verity(sbi)) 135 + len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", 136 + len ? ", " : "", "verity"); 134 137 if (f2fs_sb_has_sb_chksum(sbi)) 135 138 len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", 136 139 len ? ", " : "", "sb_checksum"); ··· 367 364 FEAT_QUOTA_INO, 368 365 FEAT_INODE_CRTIME, 369 366 FEAT_LOST_FOUND, 367 + FEAT_VERITY, 370 368 FEAT_SB_CHECKSUM, 371 369 }; 372 370 ··· 385 381 case FEAT_QUOTA_INO: 386 382 case FEAT_INODE_CRTIME: 387 383 case FEAT_LOST_FOUND: 384 + case FEAT_VERITY: 388 385 case FEAT_SB_CHECKSUM: 389 386 return snprintf(buf, PAGE_SIZE, "supported\n"); 390 387 } ··· 475 470 F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); 476 471 F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); 477 472 F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); 473 + #ifdef CONFIG_FS_VERITY 474 + F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY); 475 + #endif 478 476 F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); 479 477 480 478 #define ATTR_LIST(name) (&f2fs_attr_##name.attr) ··· 542 534 ATTR_LIST(quota_ino), 543 535 ATTR_LIST(inode_crtime), 544 536 ATTR_LIST(lost_found), 537 + #ifdef CONFIG_FS_VERITY 538 + ATTR_LIST(verity), 539 + #endif 545 540 ATTR_LIST(sb_checksum), 546 541 NULL, 547 542 };
+247
fs/f2fs/verity.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * fs/f2fs/verity.c: fs-verity support for f2fs 4 + * 5 + * Copyright 2019 Google LLC 6 + */ 7 + 8 + /* 9 + * Implementation of fsverity_operations for f2fs. 10 + * 11 + * Like ext4, f2fs stores the verity metadata (Merkle tree and 12 + * fsverity_descriptor) past the end of the file, starting at the first 64K 13 + * boundary beyond i_size. This approach works because (a) verity files are 14 + * readonly, and (b) pages fully beyond i_size aren't visible to userspace but 15 + * can be read/written internally by f2fs with only some relatively small 16 + * changes to f2fs. Extended attributes cannot be used because (a) f2fs limits 17 + * the total size of an inode's xattr entries to 4096 bytes, which wouldn't be 18 + * enough for even a single Merkle tree block, and (b) f2fs encryption doesn't 19 + * encrypt xattrs, yet the verity metadata *must* be encrypted when the file is 20 + * because it contains hashes of the plaintext data. 21 + * 22 + * Using a 64K boundary rather than a 4K one keeps things ready for 23 + * architectures with 64K pages, and it doesn't necessarily waste space on-disk 24 + * since there can be a hole between i_size and the start of the Merkle tree. 25 + */ 26 + 27 + #include <linux/f2fs_fs.h> 28 + 29 + #include "f2fs.h" 30 + #include "xattr.h" 31 + 32 + static inline loff_t f2fs_verity_metadata_pos(const struct inode *inode) 33 + { 34 + return round_up(inode->i_size, 65536); 35 + } 36 + 37 + /* 38 + * Read some verity metadata from the inode. __vfs_read() can't be used because 39 + * we need to read beyond i_size. 40 + */ 41 + static int pagecache_read(struct inode *inode, void *buf, size_t count, 42 + loff_t pos) 43 + { 44 + while (count) { 45 + size_t n = min_t(size_t, count, 46 + PAGE_SIZE - offset_in_page(pos)); 47 + struct page *page; 48 + void *addr; 49 + 50 + page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT, 51 + NULL); 52 + if (IS_ERR(page)) 53 + return PTR_ERR(page); 54 + 55 + addr = kmap_atomic(page); 56 + memcpy(buf, addr + offset_in_page(pos), n); 57 + kunmap_atomic(addr); 58 + 59 + put_page(page); 60 + 61 + buf += n; 62 + pos += n; 63 + count -= n; 64 + } 65 + return 0; 66 + } 67 + 68 + /* 69 + * Write some verity metadata to the inode for FS_IOC_ENABLE_VERITY. 70 + * kernel_write() can't be used because the file descriptor is readonly. 71 + */ 72 + static int pagecache_write(struct inode *inode, const void *buf, size_t count, 73 + loff_t pos) 74 + { 75 + if (pos + count > inode->i_sb->s_maxbytes) 76 + return -EFBIG; 77 + 78 + while (count) { 79 + size_t n = min_t(size_t, count, 80 + PAGE_SIZE - offset_in_page(pos)); 81 + struct page *page; 82 + void *fsdata; 83 + void *addr; 84 + int res; 85 + 86 + res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0, 87 + &page, &fsdata); 88 + if (res) 89 + return res; 90 + 91 + addr = kmap_atomic(page); 92 + memcpy(addr + offset_in_page(pos), buf, n); 93 + kunmap_atomic(addr); 94 + 95 + res = pagecache_write_end(NULL, inode->i_mapping, pos, n, n, 96 + page, fsdata); 97 + if (res < 0) 98 + return res; 99 + if (res != n) 100 + return -EIO; 101 + 102 + buf += n; 103 + pos += n; 104 + count -= n; 105 + } 106 + return 0; 107 + } 108 + 109 + /* 110 + * Format of f2fs verity xattr. This points to the location of the verity 111 + * descriptor within the file data rather than containing it directly because 112 + * the verity descriptor *must* be encrypted when f2fs encryption is used. But, 113 + * f2fs encryption does not encrypt xattrs. 114 + */ 115 + struct fsverity_descriptor_location { 116 + __le32 version; 117 + __le32 size; 118 + __le64 pos; 119 + }; 120 + 121 + static int f2fs_begin_enable_verity(struct file *filp) 122 + { 123 + struct inode *inode = file_inode(filp); 124 + int err; 125 + 126 + if (f2fs_verity_in_progress(inode)) 127 + return -EBUSY; 128 + 129 + if (f2fs_is_atomic_file(inode) || f2fs_is_volatile_file(inode)) 130 + return -EOPNOTSUPP; 131 + 132 + /* 133 + * Since the file was opened readonly, we have to initialize the quotas 134 + * here and not rely on ->open() doing it. This must be done before 135 + * evicting the inline data. 136 + */ 137 + err = dquot_initialize(inode); 138 + if (err) 139 + return err; 140 + 141 + err = f2fs_convert_inline_inode(inode); 142 + if (err) 143 + return err; 144 + 145 + set_inode_flag(inode, FI_VERITY_IN_PROGRESS); 146 + return 0; 147 + } 148 + 149 + static int f2fs_end_enable_verity(struct file *filp, const void *desc, 150 + size_t desc_size, u64 merkle_tree_size) 151 + { 152 + struct inode *inode = file_inode(filp); 153 + u64 desc_pos = f2fs_verity_metadata_pos(inode) + merkle_tree_size; 154 + struct fsverity_descriptor_location dloc = { 155 + .version = cpu_to_le32(1), 156 + .size = cpu_to_le32(desc_size), 157 + .pos = cpu_to_le64(desc_pos), 158 + }; 159 + int err = 0; 160 + 161 + if (desc != NULL) { 162 + /* Succeeded; write the verity descriptor. */ 163 + err = pagecache_write(inode, desc, desc_size, desc_pos); 164 + 165 + /* Write all pages before clearing FI_VERITY_IN_PROGRESS. */ 166 + if (!err) 167 + err = filemap_write_and_wait(inode->i_mapping); 168 + } 169 + 170 + /* If we failed, truncate anything we wrote past i_size. */ 171 + if (desc == NULL || err) 172 + f2fs_truncate(inode); 173 + 174 + clear_inode_flag(inode, FI_VERITY_IN_PROGRESS); 175 + 176 + if (desc != NULL && !err) { 177 + err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_VERITY, 178 + F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc), 179 + NULL, XATTR_CREATE); 180 + if (!err) { 181 + file_set_verity(inode); 182 + f2fs_set_inode_flags(inode); 183 + f2fs_mark_inode_dirty_sync(inode, true); 184 + } 185 + } 186 + return err; 187 + } 188 + 189 + static int f2fs_get_verity_descriptor(struct inode *inode, void *buf, 190 + size_t buf_size) 191 + { 192 + struct fsverity_descriptor_location dloc; 193 + int res; 194 + u32 size; 195 + u64 pos; 196 + 197 + /* Get the descriptor location */ 198 + res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_VERITY, 199 + F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc), NULL); 200 + if (res < 0 && res != -ERANGE) 201 + return res; 202 + if (res != sizeof(dloc) || dloc.version != cpu_to_le32(1)) { 203 + f2fs_warn(F2FS_I_SB(inode), "unknown verity xattr format"); 204 + return -EINVAL; 205 + } 206 + size = le32_to_cpu(dloc.size); 207 + pos = le64_to_cpu(dloc.pos); 208 + 209 + /* Get the descriptor */ 210 + if (pos + size < pos || pos + size > inode->i_sb->s_maxbytes || 211 + pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) { 212 + f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr"); 213 + return -EFSCORRUPTED; 214 + } 215 + if (buf_size) { 216 + if (size > buf_size) 217 + return -ERANGE; 218 + res = pagecache_read(inode, buf, size, pos); 219 + if (res) 220 + return res; 221 + } 222 + return size; 223 + } 224 + 225 + static struct page *f2fs_read_merkle_tree_page(struct inode *inode, 226 + pgoff_t index) 227 + { 228 + index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT; 229 + 230 + return read_mapping_page(inode->i_mapping, index, NULL); 231 + } 232 + 233 + static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf, 234 + u64 index, int log_blocksize) 235 + { 236 + loff_t pos = f2fs_verity_metadata_pos(inode) + (index << log_blocksize); 237 + 238 + return pagecache_write(inode, buf, 1 << log_blocksize, pos); 239 + } 240 + 241 + const struct fsverity_operations f2fs_verityops = { 242 + .begin_enable_verity = f2fs_begin_enable_verity, 243 + .end_enable_verity = f2fs_end_enable_verity, 244 + .get_verity_descriptor = f2fs_get_verity_descriptor, 245 + .read_merkle_tree_page = f2fs_read_merkle_tree_page, 246 + .write_merkle_tree_block = f2fs_write_merkle_tree_block, 247 + };
+2
fs/f2fs/xattr.h
··· 34 34 #define F2FS_XATTR_INDEX_ADVISE 7 35 35 /* Should be same as EXT4_XATTR_INDEX_ENCRYPTION */ 36 36 #define F2FS_XATTR_INDEX_ENCRYPTION 9 37 + #define F2FS_XATTR_INDEX_VERITY 11 37 38 38 39 #define F2FS_XATTR_NAME_ENCRYPTION_CONTEXT "c" 40 + #define F2FS_XATTR_NAME_VERITY "v" 39 41 40 42 struct f2fs_xattr_header { 41 43 __le32 h_magic; /* magic number for identification */