diff options
author | Michael Halcrow <mhalcrow@google.com> | 2015-04-12 00:56:28 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2015-04-12 00:56:28 -0400 |
commit | 4bdfc873ba34e425d6532581b4127b960274272a (patch) | |
tree | bb025d46b0de4bee9a650ef679b0729a82b2772c /fs/ext4 | |
parent | 2f61830ae33e2944ad66bb8bb40916f534b2e494 (diff) |
ext4 crypto: insert encrypted filenames into a leaf directory block
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/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 4 | ||||
-rw-r--r-- | fs/ext4/inline.c | 7 | ||||
-rw-r--r-- | fs/ext4/namei.c | 81 |
3 files changed, 79 insertions, 13 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ba75838f3588..5146e67e8d51 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2151,9 +2151,11 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
2151 | void *buf, int buf_size, | 2151 | void *buf, int buf_size, |
2152 | const char *name, int namelen, | 2152 | const char *name, int namelen, |
2153 | struct ext4_dir_entry_2 **dest_de); | 2153 | struct ext4_dir_entry_2 **dest_de); |
2154 | void ext4_insert_dentry(struct inode *inode, | 2154 | int ext4_insert_dentry(struct inode *dir, |
2155 | struct inode *inode, | ||
2155 | struct ext4_dir_entry_2 *de, | 2156 | struct ext4_dir_entry_2 *de, |
2156 | int buf_size, | 2157 | int buf_size, |
2158 | const struct qstr *iname, | ||
2157 | const char *name, int namelen); | 2159 | const char *name, int namelen); |
2158 | static inline void ext4_update_dx_flag(struct inode *inode) | 2160 | static inline void ext4_update_dx_flag(struct inode *inode) |
2159 | { | 2161 | { |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 661f0b8dcfe0..feb2cafbeace 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -11,11 +11,13 @@ | |||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | */ | 13 | */ |
14 | |||
15 | #include <linux/fiemap.h> | ||
16 | |||
14 | #include "ext4_jbd2.h" | 17 | #include "ext4_jbd2.h" |
15 | #include "ext4.h" | 18 | #include "ext4.h" |
16 | #include "xattr.h" | 19 | #include "xattr.h" |
17 | #include "truncate.h" | 20 | #include "truncate.h" |
18 | #include <linux/fiemap.h> | ||
19 | 21 | ||
20 | #define EXT4_XATTR_SYSTEM_DATA "data" | 22 | #define EXT4_XATTR_SYSTEM_DATA "data" |
21 | #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) | 23 | #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) |
@@ -1014,7 +1016,8 @@ static int ext4_add_dirent_to_inline(handle_t *handle, | |||
1014 | err = ext4_journal_get_write_access(handle, iloc->bh); | 1016 | err = ext4_journal_get_write_access(handle, iloc->bh); |
1015 | if (err) | 1017 | if (err) |
1016 | return err; | 1018 | return err; |
1017 | ext4_insert_dentry(inode, de, inline_size, name, namelen); | 1019 | ext4_insert_dentry(dir, inode, de, inline_size, &dentry->d_name, |
1020 | name, namelen); | ||
1018 | 1021 | ||
1019 | ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); | 1022 | ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); |
1020 | 1023 | ||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 8cef115ee64a..eb11a1b8a3d5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1665,19 +1665,49 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
1665 | return 0; | 1665 | return 0; |
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | void ext4_insert_dentry(struct inode *inode, | 1668 | int ext4_insert_dentry(struct inode *dir, |
1669 | struct ext4_dir_entry_2 *de, | 1669 | struct inode *inode, |
1670 | int buf_size, | 1670 | struct ext4_dir_entry_2 *de, |
1671 | const char *name, int namelen) | 1671 | int buf_size, |
1672 | const struct qstr *iname, | ||
1673 | const char *name, int namelen) | ||
1672 | { | 1674 | { |
1673 | 1675 | ||
1674 | int nlen, rlen; | 1676 | int nlen, rlen; |
1677 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
1678 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; | ||
1679 | struct ext4_str tmp_str; | ||
1680 | int res; | ||
1681 | |||
1682 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
1683 | if (IS_ERR(ctx)) | ||
1684 | return -EIO; | ||
1685 | /* By default, the input name would be written to the disk */ | ||
1686 | tmp_str.name = (unsigned char *)name; | ||
1687 | tmp_str.len = namelen; | ||
1688 | if (ctx != NULL) { | ||
1689 | /* Directory is encrypted */ | ||
1690 | res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
1691 | &fname_crypto_str); | ||
1692 | if (res < 0) { | ||
1693 | ext4_put_fname_crypto_ctx(&ctx); | ||
1694 | return -ENOMEM; | ||
1695 | } | ||
1696 | res = ext4_fname_usr_to_disk(ctx, iname, &fname_crypto_str); | ||
1697 | if (res < 0) { | ||
1698 | ext4_put_fname_crypto_ctx(&ctx); | ||
1699 | ext4_fname_crypto_free_buffer(&fname_crypto_str); | ||
1700 | return res; | ||
1701 | } | ||
1702 | tmp_str.name = fname_crypto_str.name; | ||
1703 | tmp_str.len = fname_crypto_str.len; | ||
1704 | } | ||
1675 | 1705 | ||
1676 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1706 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
1677 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); | 1707 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); |
1678 | if (de->inode) { | 1708 | if (de->inode) { |
1679 | struct ext4_dir_entry_2 *de1 = | 1709 | struct ext4_dir_entry_2 *de1 = |
1680 | (struct ext4_dir_entry_2 *)((char *)de + nlen); | 1710 | (struct ext4_dir_entry_2 *)((char *)de + nlen); |
1681 | de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size); | 1711 | de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size); |
1682 | de->rec_len = ext4_rec_len_to_disk(nlen, buf_size); | 1712 | de->rec_len = ext4_rec_len_to_disk(nlen, buf_size); |
1683 | de = de1; | 1713 | de = de1; |
@@ -1685,9 +1715,14 @@ void ext4_insert_dentry(struct inode *inode, | |||
1685 | de->file_type = EXT4_FT_UNKNOWN; | 1715 | de->file_type = EXT4_FT_UNKNOWN; |
1686 | de->inode = cpu_to_le32(inode->i_ino); | 1716 | de->inode = cpu_to_le32(inode->i_ino); |
1687 | ext4_set_de_type(inode->i_sb, de, inode->i_mode); | 1717 | ext4_set_de_type(inode->i_sb, de, inode->i_mode); |
1688 | de->name_len = namelen; | 1718 | de->name_len = tmp_str.len; |
1689 | memcpy(de->name, name, namelen); | 1719 | |
1720 | memcpy(de->name, tmp_str.name, tmp_str.len); | ||
1721 | ext4_put_fname_crypto_ctx(&ctx); | ||
1722 | ext4_fname_crypto_free_buffer(&fname_crypto_str); | ||
1723 | return 0; | ||
1690 | } | 1724 | } |
1725 | |||
1691 | /* | 1726 | /* |
1692 | * Add a new entry into a directory (leaf) block. If de is non-NULL, | 1727 | * Add a new entry into a directory (leaf) block. If de is non-NULL, |
1693 | * it points to a directory entry which is guaranteed to be large | 1728 | * it points to a directory entry which is guaranteed to be large |
@@ -1724,8 +1759,12 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1724 | return err; | 1759 | return err; |
1725 | } | 1760 | } |
1726 | 1761 | ||
1727 | /* By now the buffer is marked for journaling */ | 1762 | /* By now the buffer is marked for journaling. Due to crypto operations, |
1728 | ext4_insert_dentry(inode, de, blocksize, name, namelen); | 1763 | * the following function call may fail */ |
1764 | err = ext4_insert_dentry(dir, inode, de, blocksize, &dentry->d_name, | ||
1765 | name, namelen); | ||
1766 | if (err < 0) | ||
1767 | return err; | ||
1729 | 1768 | ||
1730 | /* | 1769 | /* |
1731 | * XXX shouldn't update any times until successful | 1770 | * XXX shouldn't update any times until successful |
@@ -1757,8 +1796,13 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1757 | struct inode *inode, struct buffer_head *bh) | 1796 | struct inode *inode, struct buffer_head *bh) |
1758 | { | 1797 | { |
1759 | struct inode *dir = dentry->d_parent->d_inode; | 1798 | struct inode *dir = dentry->d_parent->d_inode; |
1799 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1800 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
1801 | int res; | ||
1802 | #else | ||
1760 | const char *name = dentry->d_name.name; | 1803 | const char *name = dentry->d_name.name; |
1761 | int namelen = dentry->d_name.len; | 1804 | int namelen = dentry->d_name.len; |
1805 | #endif | ||
1762 | struct buffer_head *bh2; | 1806 | struct buffer_head *bh2; |
1763 | struct dx_root *root; | 1807 | struct dx_root *root; |
1764 | struct dx_frame frames[2], *frame; | 1808 | struct dx_frame frames[2], *frame; |
@@ -1772,7 +1816,13 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1772 | struct dx_hash_info hinfo; | 1816 | struct dx_hash_info hinfo; |
1773 | ext4_lblk_t block; | 1817 | ext4_lblk_t block; |
1774 | struct fake_dirent *fde; | 1818 | struct fake_dirent *fde; |
1775 | int csum_size = 0; | 1819 | int csum_size = 0; |
1820 | |||
1821 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1822 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
1823 | if (IS_ERR(ctx)) | ||
1824 | return PTR_ERR(ctx); | ||
1825 | #endif | ||
1776 | 1826 | ||
1777 | if (ext4_has_metadata_csum(inode->i_sb)) | 1827 | if (ext4_has_metadata_csum(inode->i_sb)) |
1778 | csum_size = sizeof(struct ext4_dir_entry_tail); | 1828 | csum_size = sizeof(struct ext4_dir_entry_tail); |
@@ -1839,7 +1889,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1839 | if (hinfo.hash_version <= DX_HASH_TEA) | 1889 | if (hinfo.hash_version <= DX_HASH_TEA) |
1840 | hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; | 1890 | hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; |
1841 | hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; | 1891 | hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
1892 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
1893 | res = ext4_fname_usr_to_hash(ctx, &dentry->d_name, &hinfo); | ||
1894 | if (res < 0) { | ||
1895 | ext4_put_fname_crypto_ctx(&ctx); | ||
1896 | ext4_mark_inode_dirty(handle, dir); | ||
1897 | brelse(bh); | ||
1898 | return res; | ||
1899 | } | ||
1900 | ext4_put_fname_crypto_ctx(&ctx); | ||
1901 | #else | ||
1842 | ext4fs_dirhash(name, namelen, &hinfo); | 1902 | ext4fs_dirhash(name, namelen, &hinfo); |
1903 | #endif | ||
1843 | memset(frames, 0, sizeof(frames)); | 1904 | memset(frames, 0, sizeof(frames)); |
1844 | frame = frames; | 1905 | frame = frames; |
1845 | frame->entries = entries; | 1906 | frame->entries = entries; |