1 ext4 crypto: allocate the right amount of memory for the on-disk symlink
3 Previously we were taking the required padding when allocating space
4 for the on-disk symlink. This caused a buffer overrun which could
5 trigger a krenel crash when running fsstress.
7 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
9 fs/ext4/crypto_fname.c | 25 +++++++++++++++----------
11 fs/ext4/namei.c | 32 +++++++++++++++++++++-----------
12 3 files changed, 37 insertions(+), 21 deletions(-)
14 diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
15 index 23af41f..7dc4eb5 100644
16 --- a/fs/ext4/crypto_fname.c
17 +++ b/fs/ext4/crypto_fname.c
18 @@ -262,8 +262,20 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
19 return ((size+blksize-1)/blksize)*blksize;
23 - * ext4_fname_crypto_alloc_obuff() -
24 +unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen)
26 + struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
30 + padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
31 + if (ilen < EXT4_CRYPTO_BLOCK_SIZE)
32 + ilen = EXT4_CRYPTO_BLOCK_SIZE;
33 + return ext4_fname_crypto_round_up(ilen, padding);
37 + * ext4_fname_crypto_alloc_buffer() -
39 * Allocates an output buffer that is sufficient for the crypto operation
40 * specified by the context and the direction.
41 @@ -271,15 +283,8 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize)
42 int ext4_fname_crypto_alloc_buffer(struct inode *inode,
43 u32 ilen, struct ext4_str *crypto_str)
47 - struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
48 + unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
51 - padding = 4 << (ci->ci_flags & EXT4_POLICY_FLAGS_PAD_MASK);
52 - if (padding < EXT4_CRYPTO_BLOCK_SIZE)
53 - padding = EXT4_CRYPTO_BLOCK_SIZE;
54 - olen = ext4_fname_crypto_round_up(ilen, padding);
55 crypto_str->len = olen;
56 if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
57 olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
58 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
59 index 4a019aa..f4111d2 100644
62 @@ -2090,6 +2090,7 @@ static inline int ext4_sb_has_crypto(struct super_block *sb)
64 bool ext4_valid_filenames_enc_mode(uint32_t mode);
65 u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
66 +unsigned ext4_fname_encrypted_size(struct inode *inode, u32 ilen);
67 int ext4_fname_crypto_alloc_buffer(struct inode *inode,
68 u32 ilen, struct ext4_str *crypto_str);
69 int _ext4_fname_disk_to_usr(struct inode *inode,
70 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
71 index 24fc7a5..b1f45e0 100644
74 @@ -3045,10 +3045,23 @@ static int ext4_symlink(struct inode *dir,
76 encryption_required = (ext4_encrypted_inode(dir) ||
77 DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb)));
78 - if (encryption_required)
79 - disk_link.len = encrypted_symlink_data_len(len) + 1;
80 - if (disk_link.len > dir->i_sb->s_blocksize)
81 - return -ENAMETOOLONG;
82 + if (encryption_required) {
83 + err = ext4_get_encryption_info(dir);
86 + if (ext4_encryption_info(dir) == NULL)
88 + disk_link.len = (ext4_fname_encrypted_size(dir, len) +
89 + sizeof(struct ext4_encrypted_symlink_data));
90 + sd = kzalloc(disk_link.len, GFP_KERNEL);
95 + if (disk_link.len > dir->i_sb->s_blocksize) {
96 + err = -ENAMETOOLONG;
100 dquot_initialize(dir);
102 @@ -3079,18 +3092,14 @@ static int ext4_symlink(struct inode *dir,
105 ext4_journal_stop(handle);
106 - return PTR_ERR(inode);
107 + err = PTR_ERR(inode);
111 if (encryption_required) {
113 struct ext4_str ostr;
115 - sd = kzalloc(disk_link.len, GFP_NOFS);
118 - goto err_drop_inode;
120 istr.name = (const unsigned char *) symname;
122 ostr.name = sd->encrypted_path;
123 @@ -3162,10 +3171,11 @@ static int ext4_symlink(struct inode *dir,
126 ext4_journal_stop(handle);
129 unlock_new_inode(inode);