1 |
From 105c78e12468413e426625831faa7db4284e1fec Mon Sep 17 00:00:00 2001 |
2 |
From: Eric Biggers <ebiggers@google.com> |
3 |
Date: Tue, 1 Nov 2022 22:33:12 -0700 |
4 |
Subject: [PATCH] ext4: don't allow journal inode to have encrypt flag |
5 |
|
6 |
Mounting a filesystem whose journal inode has the encrypt flag causes a |
7 |
NULL dereference in fscrypt_limit_io_blocks() when the 'inlinecrypt' |
8 |
mount option is used. |
9 |
|
10 |
The problem is that when jbd2_journal_init_inode() calls bmap(), it |
11 |
eventually finds its way into ext4_iomap_begin(), which calls |
12 |
fscrypt_limit_io_blocks(). fscrypt_limit_io_blocks() requires that if |
13 |
the inode is encrypted, then its encryption key must already be set up. |
14 |
That's not the case here, since the journal inode is never "opened" like |
15 |
a normal file would be. Hence the crash. |
16 |
|
17 |
A reproducer is: |
18 |
|
19 |
mkfs.ext4 -F /dev/vdb |
20 |
debugfs -w /dev/vdb -R "set_inode_field <8> flags 0x80808" |
21 |
mount /dev/vdb /mnt -o inlinecrypt |
22 |
|
23 |
To fix this, make ext4 consider journal inodes with the encrypt flag to |
24 |
be invalid. (Note, maybe other flags should be rejected on the journal |
25 |
inode too. For now, this is just the minimal fix for the above issue.) |
26 |
|
27 |
I've marked this as fixing the commit that introduced the call to |
28 |
fscrypt_limit_io_blocks(), since that's what made an actual crash start |
29 |
being possible. But this fix could be applied to any version of ext4 |
30 |
that supports the encrypt feature. |
31 |
|
32 |
Reported-by: syzbot+ba9dac45bc76c490b7c3@syzkaller.appspotmail.com |
33 |
Fixes: 38ea50daa7a4 ("ext4: support direct I/O with fscrypt using blk-crypto") |
34 |
Cc: stable@vger.kernel.org |
35 |
Signed-off-by: Eric Biggers <ebiggers@google.com> |
36 |
Link: https://lore.kernel.org/r/20221102053312.189962-1-ebiggers@kernel.org |
37 |
Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
38 |
Cc: stable@kernel.org |
39 |
--- |
40 |
fs/ext4/super.c | 2 +- |
41 |
1 file changed, 1 insertion(+), 1 deletion(-) |
42 |
|
43 |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c |
44 |
index 6f944f5e4b3f..9185131e01e5 100644 |
45 |
--- a/fs/ext4/super.c |
46 |
+++ b/fs/ext4/super.c |
47 |
@@ -5155,7 +5155,7 @@ static struct inode *ext4_get_journal_in |
48 |
|
49 |
jbd_debug(2, "Journal inode found at %p: %lld bytes\n", |
50 |
journal_inode, journal_inode->i_size); |
51 |
- if (!S_ISREG(journal_inode->i_mode)) { |
52 |
+ if (!S_ISREG(journal_inode->i_mode) || IS_ENCRYPTED(journal_inode)) { |
53 |
ext4_msg(sb, KERN_ERR, "invalid journal inode"); |
54 |
iput(journal_inode); |
55 |
return NULL; |
56 |
-- |
57 |
2.39.0 |