diff options
| author | Michael Halcrow <mhalcrow@google.com> | 2015-04-12 01:07:01 -0400 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2015-04-12 01:07:01 -0400 |
| commit | b30984864406ad01b72eee486add103e9cb3526f (patch) | |
| tree | 0c0e6cefa0691c6747504e2e4336a2eb488cab67 | |
| parent | 4bdfc873ba34e425d6532581b4127b960274272a (diff) | |
ext4 crypto: partial update to namei.c for fname crypto
Modifies dx_show_leaf and dx_probe to support fname encryption.
Filename encryption not yet enabled.
Signed-off-by: Uday Savagaonkar <savagaon@google.com>
Signed-off-by: Ildar Muslukhov <ildarm@google.com>
Signed-off-by: Michael Halcrow <mhalcrow@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
| -rw-r--r-- | fs/ext4/namei.c | 109 |
1 files changed, 101 insertions, 8 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index eb11a1b8a3d5..85add9a9e1cd 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -585,8 +585,10 @@ struct stats | |||
| 585 | unsigned bcount; | 585 | unsigned bcount; |
| 586 | }; | 586 | }; |
| 587 | 587 | ||
| 588 | static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_entry_2 *de, | 588 | static struct stats dx_show_leaf(struct inode *dir, |
| 589 | int size, int show_names) | 589 | struct dx_hash_info *hinfo, |
| 590 | struct ext4_dir_entry_2 *de, | ||
| 591 | int size, int show_names) | ||
| 590 | { | 592 | { |
| 591 | unsigned names = 0, space = 0; | 593 | unsigned names = 0, space = 0; |
| 592 | char *base = (char *) de; | 594 | char *base = (char *) de; |
| @@ -599,12 +601,80 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_ent | |||
| 599 | { | 601 | { |
| 600 | if (show_names) | 602 | if (show_names) |
| 601 | { | 603 | { |
| 604 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 605 | int len; | ||
| 606 | char *name; | ||
| 607 | struct ext4_str fname_crypto_str | ||
| 608 | = {.name = NULL, .len = 0}; | ||
| 609 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
| 610 | int res; | ||
| 611 | |||
| 612 | name = de->name; | ||
| 613 | len = de->name_len; | ||
| 614 | ctx = ext4_get_fname_crypto_ctx(dir, | ||
| 615 | EXT4_NAME_LEN); | ||
| 616 | if (IS_ERR(ctx)) { | ||
| 617 | printk(KERN_WARNING "Error acquiring" | ||
| 618 | " crypto ctxt--skipping crypto\n"); | ||
| 619 | ctx = NULL; | ||
| 620 | } | ||
| 621 | if (ctx == NULL) { | ||
| 622 | /* Directory is not encrypted */ | ||
| 623 | ext4fs_dirhash(de->name, | ||
| 624 | de->name_len, &h); | ||
| 625 | printk("%*.s:(U)%x.%u ", len, | ||
| 626 | name, h.hash, | ||
| 627 | (unsigned) ((char *) de | ||
| 628 | - base)); | ||
| 629 | } else { | ||
| 630 | /* Directory is encrypted */ | ||
| 631 | res = ext4_fname_crypto_alloc_buffer( | ||
| 632 | ctx, de->name_len, | ||
| 633 | &fname_crypto_str); | ||
| 634 | if (res < 0) { | ||
| 635 | printk(KERN_WARNING "Error " | ||
| 636 | "allocating crypto " | ||
| 637 | "buffer--skipping " | ||
| 638 | "crypto\n"); | ||
| 639 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 640 | ctx = NULL; | ||
| 641 | } | ||
| 642 | res = ext4_fname_disk_to_usr(ctx, de, | ||
| 643 | &fname_crypto_str); | ||
| 644 | if (res < 0) { | ||
| 645 | printk(KERN_WARNING "Error " | ||
| 646 | "converting filename " | ||
| 647 | "from disk to usr" | ||
| 648 | "\n"); | ||
| 649 | name = "??"; | ||
| 650 | len = 2; | ||
| 651 | } else { | ||
| 652 | name = fname_crypto_str.name; | ||
| 653 | len = fname_crypto_str.len; | ||
| 654 | } | ||
| 655 | res = ext4_fname_disk_to_hash(ctx, de, | ||
| 656 | &h); | ||
| 657 | if (res < 0) { | ||
| 658 | printk(KERN_WARNING "Error " | ||
| 659 | "converting filename " | ||
| 660 | "from disk to htree" | ||
| 661 | "\n"); | ||
| 662 | h.hash = 0xDEADBEEF; | ||
| 663 | } | ||
| 664 | printk("%*.s:(E)%x.%u ", len, name, | ||
| 665 | h.hash, (unsigned) ((char *) de | ||
| 666 | - base)); | ||
| 667 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 668 | ext4_fname_crypto_free_buffer( | ||
| 669 | &fname_crypto_str); | ||
| 670 | } | ||
| 671 | #else | ||
| 602 | int len = de->name_len; | 672 | int len = de->name_len; |
| 603 | char *name = de->name; | 673 | char *name = de->name; |
| 604 | while (len--) printk("%c", *name++); | ||
| 605 | ext4fs_dirhash(de->name, de->name_len, &h); | 674 | ext4fs_dirhash(de->name, de->name_len, &h); |
| 606 | printk(":%x.%u ", h.hash, | 675 | printk("%*.s:%x.%u ", len, name, h.hash, |
| 607 | (unsigned) ((char *) de - base)); | 676 | (unsigned) ((char *) de - base)); |
| 677 | #endif | ||
| 608 | } | 678 | } |
| 609 | space += EXT4_DIR_REC_LEN(de->name_len); | 679 | space += EXT4_DIR_REC_LEN(de->name_len); |
| 610 | names++; | 680 | names++; |
| @@ -622,7 +692,6 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, | |||
| 622 | unsigned count = dx_get_count(entries), names = 0, space = 0, i; | 692 | unsigned count = dx_get_count(entries), names = 0, space = 0, i; |
| 623 | unsigned bcount = 0; | 693 | unsigned bcount = 0; |
| 624 | struct buffer_head *bh; | 694 | struct buffer_head *bh; |
| 625 | int err; | ||
| 626 | printk("%i indexed blocks...\n", count); | 695 | printk("%i indexed blocks...\n", count); |
| 627 | for (i = 0; i < count; i++, entries++) | 696 | for (i = 0; i < count; i++, entries++) |
| 628 | { | 697 | { |
| @@ -636,7 +705,8 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, | |||
| 636 | continue; | 705 | continue; |
| 637 | stats = levels? | 706 | stats = levels? |
| 638 | dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): | 707 | dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): |
| 639 | dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0); | 708 | dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) |
| 709 | bh->b_data, blocksize, 0); | ||
| 640 | names += stats.names; | 710 | names += stats.names; |
| 641 | space += stats.space; | 711 | space += stats.space; |
| 642 | bcount += stats.bcount; | 712 | bcount += stats.bcount; |
| @@ -686,8 +756,28 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
| 686 | if (hinfo->hash_version <= DX_HASH_TEA) | 756 | if (hinfo->hash_version <= DX_HASH_TEA) |
| 687 | hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; | 757 | hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; |
| 688 | hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; | 758 | hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
| 759 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 760 | if (d_name) { | ||
| 761 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
| 762 | int res; | ||
| 763 | |||
| 764 | /* Check if the directory is encrypted */ | ||
| 765 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
| 766 | if (IS_ERR(ctx)) { | ||
| 767 | ret_err = ERR_PTR(PTR_ERR(ctx)); | ||
| 768 | goto fail; | ||
| 769 | } | ||
| 770 | res = ext4_fname_usr_to_hash(ctx, d_name, hinfo); | ||
| 771 | if (res < 0) { | ||
| 772 | ret_err = ERR_PTR(res); | ||
| 773 | goto fail; | ||
| 774 | } | ||
| 775 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 776 | } | ||
| 777 | #else | ||
| 689 | if (d_name) | 778 | if (d_name) |
| 690 | ext4fs_dirhash(d_name->name, d_name->len, hinfo); | 779 | ext4fs_dirhash(d_name->name, d_name->len, hinfo); |
| 780 | #endif | ||
| 691 | hash = hinfo->hash; | 781 | hash = hinfo->hash; |
| 692 | 782 | ||
| 693 | if (root->info.unused_flags & 1) { | 783 | if (root->info.unused_flags & 1) { |
| @@ -772,6 +862,7 @@ fail: | |||
| 772 | brelse(frame->bh); | 862 | brelse(frame->bh); |
| 773 | frame--; | 863 | frame--; |
| 774 | } | 864 | } |
| 865 | |||
| 775 | if (ret_err == ERR_PTR(ERR_BAD_DX_DIR)) | 866 | if (ret_err == ERR_PTR(ERR_BAD_DX_DIR)) |
| 776 | ext4_warning(dir->i_sb, | 867 | ext4_warning(dir->i_sb, |
| 777 | "Corrupt dir inode %lu, running e2fsck is " | 868 | "Corrupt dir inode %lu, running e2fsck is " |
| @@ -1604,8 +1695,10 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
| 1604 | initialize_dirent_tail(t, blocksize); | 1695 | initialize_dirent_tail(t, blocksize); |
| 1605 | } | 1696 | } |
| 1606 | 1697 | ||
| 1607 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); | 1698 | dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1, |
| 1608 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); | 1699 | blocksize, 1)); |
| 1700 | dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data2, | ||
| 1701 | blocksize, 1)); | ||
| 1609 | 1702 | ||
| 1610 | /* Which block gets the new entry? */ | 1703 | /* Which block gets the new entry? */ |
| 1611 | if (hinfo->hash >= hash2) { | 1704 | if (hinfo->hash >= hash2) { |
