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 /fs | |
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>
Diffstat (limited to 'fs')
-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) { |