Skip to content

Commit d117b9a

Browse files
committed
Merge tag 'ext4_for_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 fixes from Ted Ts'o: "A security fix (so a maliciously corrupted file system image won't panic the kernel) and some fixes for CONFIG_VMAP_STACK" * tag 'ext4_for_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: sanity check the block and cluster size at mount time fscrypto: don't use on-stack buffer for key derivation fscrypto: don't use on-stack buffer for filename encryption
2 parents 50d438f + 8cdf337 commit d117b9a

File tree

4 files changed

+51
-36
lines changed

4 files changed

+51
-36
lines changed

fs/crypto/fname.c

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,73 +39,62 @@ static void fname_crypt_complete(struct crypto_async_request *req, int res)
3939
static int fname_encrypt(struct inode *inode,
4040
const struct qstr *iname, struct fscrypt_str *oname)
4141
{
42-
u32 ciphertext_len;
4342
struct skcipher_request *req = NULL;
4443
DECLARE_FS_COMPLETION_RESULT(ecr);
4544
struct fscrypt_info *ci = inode->i_crypt_info;
4645
struct crypto_skcipher *tfm = ci->ci_ctfm;
4746
int res = 0;
4847
char iv[FS_CRYPTO_BLOCK_SIZE];
49-
struct scatterlist src_sg, dst_sg;
48+
struct scatterlist sg;
5049
int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK);
51-
char *workbuf, buf[32], *alloc_buf = NULL;
52-
unsigned lim;
50+
unsigned int lim;
51+
unsigned int cryptlen;
5352

5453
lim = inode->i_sb->s_cop->max_namelen(inode);
5554
if (iname->len <= 0 || iname->len > lim)
5655
return -EIO;
5756

58-
ciphertext_len = max(iname->len, (u32)FS_CRYPTO_BLOCK_SIZE);
59-
ciphertext_len = round_up(ciphertext_len, padding);
60-
ciphertext_len = min(ciphertext_len, lim);
57+
/*
58+
* Copy the filename to the output buffer for encrypting in-place and
59+
* pad it with the needed number of NUL bytes.
60+
*/
61+
cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE);
62+
cryptlen = round_up(cryptlen, padding);
63+
cryptlen = min(cryptlen, lim);
64+
memcpy(oname->name, iname->name, iname->len);
65+
memset(oname->name + iname->len, 0, cryptlen - iname->len);
6166

62-
if (ciphertext_len <= sizeof(buf)) {
63-
workbuf = buf;
64-
} else {
65-
alloc_buf = kmalloc(ciphertext_len, GFP_NOFS);
66-
if (!alloc_buf)
67-
return -ENOMEM;
68-
workbuf = alloc_buf;
69-
}
67+
/* Initialize the IV */
68+
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
7069

71-
/* Allocate request */
70+
/* Set up the encryption request */
7271
req = skcipher_request_alloc(tfm, GFP_NOFS);
7372
if (!req) {
7473
printk_ratelimited(KERN_ERR
75-
"%s: crypto_request_alloc() failed\n", __func__);
76-
kfree(alloc_buf);
74+
"%s: skcipher_request_alloc() failed\n", __func__);
7775
return -ENOMEM;
7876
}
7977
skcipher_request_set_callback(req,
8078
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
8179
fname_crypt_complete, &ecr);
80+
sg_init_one(&sg, oname->name, cryptlen);
81+
skcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv);
8282

83-
/* Copy the input */
84-
memcpy(workbuf, iname->name, iname->len);
85-
if (iname->len < ciphertext_len)
86-
memset(workbuf + iname->len, 0, ciphertext_len - iname->len);
87-
88-
/* Initialize IV */
89-
memset(iv, 0, FS_CRYPTO_BLOCK_SIZE);
90-
91-
/* Create encryption request */
92-
sg_init_one(&src_sg, workbuf, ciphertext_len);
93-
sg_init_one(&dst_sg, oname->name, ciphertext_len);
94-
skcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv);
83+
/* Do the encryption */
9584
res = crypto_skcipher_encrypt(req);
9685
if (res == -EINPROGRESS || res == -EBUSY) {
86+
/* Request is being completed asynchronously; wait for it */
9787
wait_for_completion(&ecr.completion);
9888
res = ecr.res;
9989
}
100-
kfree(alloc_buf);
10190
skcipher_request_free(req);
10291
if (res < 0) {
10392
printk_ratelimited(KERN_ERR
10493
"%s: Error (error code %d)\n", __func__, res);
10594
return res;
10695
}
10796

108-
oname->len = ciphertext_len;
97+
oname->len = cryptlen;
10998
return 0;
11099
}
111100

fs/crypto/keyinfo.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ int get_crypt_info(struct inode *inode)
185185
struct crypto_skcipher *ctfm;
186186
const char *cipher_str;
187187
int keysize;
188-
u8 raw_key[FS_MAX_KEY_SIZE];
188+
u8 *raw_key = NULL;
189189
int res;
190190

191191
res = fscrypt_initialize();
@@ -238,6 +238,15 @@ int get_crypt_info(struct inode *inode)
238238
if (res)
239239
goto out;
240240

241+
/*
242+
* This cannot be a stack buffer because it is passed to the scatterlist
243+
* crypto API as part of key derivation.
244+
*/
245+
res = -ENOMEM;
246+
raw_key = kmalloc(FS_MAX_KEY_SIZE, GFP_NOFS);
247+
if (!raw_key)
248+
goto out;
249+
241250
if (fscrypt_dummy_context_enabled(inode)) {
242251
memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE);
243252
goto got_key;
@@ -276,7 +285,8 @@ int get_crypt_info(struct inode *inode)
276285
if (res)
277286
goto out;
278287

279-
memzero_explicit(raw_key, sizeof(raw_key));
288+
kzfree(raw_key);
289+
raw_key = NULL;
280290
if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
281291
put_crypt_info(crypt_info);
282292
goto retry;
@@ -287,7 +297,7 @@ int get_crypt_info(struct inode *inode)
287297
if (res == -ENOKEY)
288298
res = 0;
289299
put_crypt_info(crypt_info);
290-
memzero_explicit(raw_key, sizeof(raw_key));
300+
kzfree(raw_key);
291301
return res;
292302
}
293303

fs/ext4/ext4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ struct ext4_io_submit {
235235
#define EXT4_MAX_BLOCK_SIZE 65536
236236
#define EXT4_MIN_BLOCK_LOG_SIZE 10
237237
#define EXT4_MAX_BLOCK_LOG_SIZE 16
238+
#define EXT4_MAX_CLUSTER_LOG_SIZE 30
238239
#ifdef __KERNEL__
239240
# define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize)
240241
#else

fs/ext4/super.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3565,7 +3565,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
35653565
if (blocksize < EXT4_MIN_BLOCK_SIZE ||
35663566
blocksize > EXT4_MAX_BLOCK_SIZE) {
35673567
ext4_msg(sb, KERN_ERR,
3568-
"Unsupported filesystem blocksize %d", blocksize);
3568+
"Unsupported filesystem blocksize %d (%d log_block_size)",
3569+
blocksize, le32_to_cpu(es->s_log_block_size));
3570+
goto failed_mount;
3571+
}
3572+
if (le32_to_cpu(es->s_log_block_size) >
3573+
(EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
3574+
ext4_msg(sb, KERN_ERR,
3575+
"Invalid log block size: %u",
3576+
le32_to_cpu(es->s_log_block_size));
35693577
goto failed_mount;
35703578
}
35713579

@@ -3697,6 +3705,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
36973705
"block size (%d)", clustersize, blocksize);
36983706
goto failed_mount;
36993707
}
3708+
if (le32_to_cpu(es->s_log_cluster_size) >
3709+
(EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
3710+
ext4_msg(sb, KERN_ERR,
3711+
"Invalid log cluster size: %u",
3712+
le32_to_cpu(es->s_log_cluster_size));
3713+
goto failed_mount;
3714+
}
37003715
sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
37013716
le32_to_cpu(es->s_log_block_size);
37023717
sbi->s_clusters_per_group =

0 commit comments

Comments
 (0)