1 ext4 crypto: don't allocate a page when encrypting/decrypting file names
3 Change-Id: I415e4e4c56ab6c7779576fc287b5c4c8d7cdb12b
4 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
6 fs/ext4/crypto_fname.c | 72 ++++++++++++++++++++----------------------------------------------------
8 fs/ext4/ext4_crypto.h | 1 -
9 fs/ext4/namei.c | 4 ++++
10 fs/ext4/symlink.c | 1 +
11 5 files changed, 28 insertions(+), 53 deletions(-)
13 diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c
14 index ad5e328..23d7f1d 100644
15 --- a/fs/ext4/crypto_fname.c
16 +++ b/fs/ext4/crypto_fname.c
17 @@ -65,9 +65,9 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
18 struct crypto_ablkcipher *tfm = ctx->ctfm;
20 char iv[EXT4_CRYPTO_BLOCK_SIZE];
21 - struct scatterlist sg[1];
22 + struct scatterlist src_sg, dst_sg;
23 int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
25 + char *workbuf, buf[32], *alloc_buf = NULL;
27 if (iname->len <= 0 || iname->len > ctx->lim)
29 @@ -78,20 +78,27 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
30 ciphertext_len = (ciphertext_len > ctx->lim)
31 ? ctx->lim : ciphertext_len;
33 + if (ciphertext_len <= sizeof(buf)) {
36 + alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
39 + workbuf = alloc_buf;
42 /* Allocate request */
43 req = ablkcipher_request_alloc(tfm, GFP_NOFS);
46 KERN_ERR "%s: crypto_request_alloc() failed\n", __func__);
50 ablkcipher_request_set_callback(req,
51 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
52 ext4_dir_crypt_complete, &ecr);
54 - /* Map the workpage */
55 - workbuf = kmap(ctx->workpage);
58 memcpy(workbuf, iname->name, iname->len);
59 if (iname->len < ciphertext_len)
60 @@ -101,21 +108,16 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
61 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
63 /* Create encryption request */
64 - sg_init_table(sg, 1);
65 - sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
66 - ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
67 + sg_init_one(&src_sg, workbuf, ciphertext_len);
68 + sg_init_one(&dst_sg, oname->name, ciphertext_len);
69 + ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
70 res = crypto_ablkcipher_encrypt(req);
71 if (res == -EINPROGRESS || res == -EBUSY) {
72 BUG_ON(req->base.data != &ecr);
73 wait_for_completion(&ecr.completion);
77 - /* Copy the result to output */
78 - memcpy(oname->name, workbuf, ciphertext_len);
79 - res = ciphertext_len;
81 - kunmap(ctx->workpage);
83 ablkcipher_request_free(req);
86 @@ -139,11 +141,10 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
87 struct ext4_str tmp_in[2], tmp_out[1];
88 struct ablkcipher_request *req = NULL;
89 DECLARE_EXT4_COMPLETION_RESULT(ecr);
90 - struct scatterlist sg[1];
91 + struct scatterlist src_sg, dst_sg;
92 struct crypto_ablkcipher *tfm = ctx->ctfm;
94 char iv[EXT4_CRYPTO_BLOCK_SIZE];
97 if (iname->len <= 0 || iname->len > ctx->lim)
99 @@ -163,31 +164,19 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
100 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
101 ext4_dir_crypt_complete, &ecr);
103 - /* Map the workpage */
104 - workbuf = kmap(ctx->workpage);
106 - /* Copy the input */
107 - memcpy(workbuf, iname->name, iname->len);
110 memset(iv, 0, EXT4_CRYPTO_BLOCK_SIZE);
112 /* Create encryption request */
113 - sg_init_table(sg, 1);
114 - sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
115 - ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv);
116 + sg_init_one(&src_sg, iname->name, iname->len);
117 + sg_init_one(&dst_sg, oname->name, oname->len);
118 + ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv);
119 res = crypto_ablkcipher_decrypt(req);
120 if (res == -EINPROGRESS || res == -EBUSY) {
121 BUG_ON(req->base.data != &ecr);
122 wait_for_completion(&ecr.completion);
126 - /* Copy the result to output */
127 - memcpy(oname->name, workbuf, iname->len);
130 - kunmap(ctx->workpage);
131 ablkcipher_request_free(req);
134 @@ -267,8 +256,6 @@ void ext4_free_fname_crypto_ctx(struct ext4_fname_crypto_ctx *ctx)
135 crypto_free_ablkcipher(ctx->ctfm);
136 if (ctx->htfm && !IS_ERR(ctx->htfm))
137 crypto_free_hash(ctx->htfm);
138 - if (ctx->workpage && !IS_ERR(ctx->workpage))
139 - __free_page(ctx->workpage);
143 @@ -322,7 +309,6 @@ struct ext4_fname_crypto_ctx *ext4_alloc_fname_crypto_ctx(
144 ctx->ctfm_key_is_ready = 0;
147 - ctx->workpage = NULL;
151 @@ -390,24 +376,6 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
152 ext4_put_fname_crypto_ctx(&ctx);
153 return ERR_PTR(-ENOMEM);
155 - if (ctx->workpage == NULL)
156 - ctx->workpage = alloc_page(GFP_NOFS);
157 - if (IS_ERR(ctx->workpage)) {
158 - res = PTR_ERR(ctx->workpage);
160 - KERN_DEBUG "%s: error (%d) allocating work page\n",
162 - ctx->workpage = NULL;
163 - ext4_put_fname_crypto_ctx(&ctx);
164 - return ERR_PTR(res);
166 - if (ctx->workpage == NULL) {
168 - KERN_DEBUG "%s: could not allocate work page\n",
170 - ext4_put_fname_crypto_ctx(&ctx);
171 - return ERR_PTR(-ENOMEM);
173 ctx->lim = max_ciphertext_len;
174 crypto_ablkcipher_clear_flags(ctx->ctfm, ~0);
175 crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctx->ctfm),
176 diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
177 index 5665d82..d799d5d 100644
180 @@ -247,9 +247,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
181 get_dtype(sb, de->file_type)))
184 + int save_len = fname_crypto_str.len;
186 /* Directory is encrypted */
187 err = ext4_fname_disk_to_usr(enc_ctx,
188 NULL, de, &fname_crypto_str);
189 + fname_crypto_str.len = save_len;
193 diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
194 index d75159c..e9e4365 100644
195 --- a/fs/ext4/ext4_crypto.h
196 +++ b/fs/ext4/ext4_crypto.h
197 @@ -126,7 +126,6 @@ struct ext4_fname_crypto_ctx {
198 char tmp_buf[EXT4_CRYPTO_BLOCK_SIZE];
199 struct crypto_ablkcipher *ctfm;
200 struct crypto_hash *htfm;
201 - struct page *workpage;
202 struct ext4_encryption_key key;
204 unsigned has_valid_key : 1;
205 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
206 index 752d4af..bf66e56 100644
207 --- a/fs/ext4/namei.c
208 +++ b/fs/ext4/namei.c
209 @@ -998,6 +998,8 @@ static int htree_dirblock_to_tree(struct file *dir_file,
210 hinfo->hash, hinfo->minor_hash, de,
213 + int save_len = fname_crypto_str.len;
215 /* Directory is encrypted */
216 err = ext4_fname_disk_to_usr(ctx, hinfo, de,
218 @@ -1008,6 +1010,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
219 err = ext4_htree_store_dirent(dir_file,
220 hinfo->hash, hinfo->minor_hash, de,
222 + fname_crypto_str.len = save_len;
226 @@ -3132,6 +3135,7 @@ static int ext4_symlink(struct inode *dir,
227 istr.name = (const unsigned char *) symname;
229 ostr.name = sd->encrypted_path;
230 + ostr.len = disk_link.len;
231 err = ext4_fname_usr_to_disk(ctx, &istr, &ostr);
232 ext4_put_fname_crypto_ctx(&ctx);
234 diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
235 index ce2ed28..3428c51 100644
236 --- a/fs/ext4/symlink.c
237 +++ b/fs/ext4/symlink.c
238 @@ -74,6 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
243 res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);