add patch improve-warning-directory-handling-messages
[ext4-patch-queue.git] / allocate-the-right-size-for-on-disk-symlink
blob699a4489e287f04695990ed31f89fa79865606df
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>
8 ---
9  fs/ext4/crypto_fname.c | 25 +++++++++++++++----------
10  fs/ext4/ext4.h         |  1 +
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;
20  }
22 -/**
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;
27 +       int padding = 32;
29 +       if (ci)
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);
36 +/*
37 + * ext4_fname_crypto_alloc_buffer() -
38   *
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)
44  {
45 -       unsigned int olen;
46 -       int padding = 16;
47 -       struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
48 +       unsigned int olen = ext4_fname_encrypted_size(inode, ilen);
50 -       if (ci)
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
60 --- a/fs/ext4/ext4.h
61 +++ b/fs/ext4/ext4.h
62 @@ -2090,6 +2090,7 @@ static inline int ext4_sb_has_crypto(struct super_block *sb)
63  /* crypto_fname.c */
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
72 --- a/fs/ext4/namei.c
73 +++ b/fs/ext4/namei.c
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);
84 +               if (err)
85 +                       return err;
86 +               if (ext4_encryption_info(dir) == NULL)
87 +                       return -EPERM;
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);
91 +               if (!sd)
92 +                       return -ENOMEM;
93 +       }
95 +       if (disk_link.len > dir->i_sb->s_blocksize) {
96 +               err = -ENAMETOOLONG;
97 +               goto err_free_sd;
98 +       }
100         dquot_initialize(dir);
102 @@ -3079,18 +3092,14 @@ static int ext4_symlink(struct inode *dir,
103         if (IS_ERR(inode)) {
104                 if (handle)
105                         ext4_journal_stop(handle);
106 -               return PTR_ERR(inode);
107 +               err = PTR_ERR(inode);
108 +               goto err_free_sd;
109         }
111         if (encryption_required) {
112                 struct qstr istr;
113                 struct ext4_str ostr;
115 -               sd = kzalloc(disk_link.len, GFP_NOFS);
116 -               if (!sd) {
117 -                       err = -ENOMEM;
118 -                       goto err_drop_inode;
119 -               }
120                 istr.name = (const unsigned char *) symname;
121                 istr.len = len;
122                 ostr.name = sd->encrypted_path;
123 @@ -3162,10 +3171,11 @@ static int ext4_symlink(struct inode *dir,
124  err_drop_inode:
125         if (handle)
126                 ext4_journal_stop(handle);
127 -       kfree(sd);
128         clear_nlink(inode);
129         unlock_new_inode(inode);
130         iput(inode);
131 +err_free_sd:
132 +       kfree(sd);
133         return err;