Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ext4: disable fast-commit of encrypted dir operations

fast-commit of create, link, and unlink operations in encrypted
directories is completely broken because the unencrypted filenames are
being written to the fast-commit journal instead of the encrypted
filenames. These operations can't be replayed, as encryption keys
aren't present at journal replay time. It is also an information leak.

Until if/when we can get this working properly, make encrypted directory
operations ineligible for fast-commit.

Note that fast-commit operations on encrypted regular files continue to
be allowed, as they seem to work.

Fixes: aa75f4d3daae ("ext4: main fast-commit commit path")
Cc: <stable@vger.kernel.org> # v5.10+
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20221106224841.279231-2-ebiggers@kernel.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by

Eric Biggers and committed by
Theodore Ts'o
0fbcb525 a71248b1

+31 -18
+25 -16
fs/ext4/fast_commit.c
··· 420 420 struct __track_dentry_update_args *dentry_update = 421 421 (struct __track_dentry_update_args *)arg; 422 422 struct dentry *dentry = dentry_update->dentry; 423 - struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 423 + struct inode *dir = dentry->d_parent->d_inode; 424 + struct super_block *sb = inode->i_sb; 425 + struct ext4_sb_info *sbi = EXT4_SB(sb); 424 426 425 427 mutex_unlock(&ei->i_fc_lock); 428 + 429 + if (IS_ENCRYPTED(dir)) { 430 + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_ENCRYPTED_FILENAME, 431 + NULL); 432 + mutex_lock(&ei->i_fc_lock); 433 + return -EOPNOTSUPP; 434 + } 435 + 426 436 node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); 427 437 if (!node) { 428 - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); 438 + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, NULL); 429 439 mutex_lock(&ei->i_fc_lock); 430 440 return -ENOMEM; 431 441 } 432 442 433 443 node->fcd_op = dentry_update->op; 434 - node->fcd_parent = dentry->d_parent->d_inode->i_ino; 444 + node->fcd_parent = dir->i_ino; 435 445 node->fcd_ino = inode->i_ino; 436 446 if (dentry->d_name.len > DNAME_INLINE_LEN) { 437 447 node->fcd_name.name = kmalloc(dentry->d_name.len, GFP_NOFS); 438 448 if (!node->fcd_name.name) { 439 449 kmem_cache_free(ext4_fc_dentry_cachep, node); 440 - ext4_fc_mark_ineligible(inode->i_sb, 441 - EXT4_FC_REASON_NOMEM, NULL); 450 + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, NULL); 442 451 mutex_lock(&ei->i_fc_lock); 443 452 return -ENOMEM; 444 453 } ··· 2258 2249 journal->j_fc_cleanup_callback = ext4_fc_cleanup; 2259 2250 } 2260 2251 2261 - static const char *fc_ineligible_reasons[] = { 2262 - "Extended attributes changed", 2263 - "Cross rename", 2264 - "Journal flag changed", 2265 - "Insufficient memory", 2266 - "Swap boot", 2267 - "Resize", 2268 - "Dir renamed", 2269 - "Falloc range op", 2270 - "Data journalling", 2271 - "FC Commit Failed" 2252 + static const char * const fc_ineligible_reasons[] = { 2253 + [EXT4_FC_REASON_XATTR] = "Extended attributes changed", 2254 + [EXT4_FC_REASON_CROSS_RENAME] = "Cross rename", 2255 + [EXT4_FC_REASON_JOURNAL_FLAG_CHANGE] = "Journal flag changed", 2256 + [EXT4_FC_REASON_NOMEM] = "Insufficient memory", 2257 + [EXT4_FC_REASON_SWAP_BOOT] = "Swap boot", 2258 + [EXT4_FC_REASON_RESIZE] = "Resize", 2259 + [EXT4_FC_REASON_RENAME_DIR] = "Dir renamed", 2260 + [EXT4_FC_REASON_FALLOC_RANGE] = "Falloc range op", 2261 + [EXT4_FC_REASON_INODE_JOURNAL_DATA] = "Data journalling", 2262 + [EXT4_FC_REASON_ENCRYPTED_FILENAME] = "Encrypted filename", 2272 2263 }; 2273 2264 2274 2265 int ext4_fc_info_show(struct seq_file *seq, void *v)
+1
fs/ext4/fast_commit.h
··· 96 96 EXT4_FC_REASON_RENAME_DIR, 97 97 EXT4_FC_REASON_FALLOC_RANGE, 98 98 EXT4_FC_REASON_INODE_JOURNAL_DATA, 99 + EXT4_FC_REASON_ENCRYPTED_FILENAME, 99 100 EXT4_FC_REASON_MAX 100 101 }; 101 102
+5 -2
include/trace/events/ext4.h
··· 104 104 TRACE_DEFINE_ENUM(EXT4_FC_REASON_RENAME_DIR); 105 105 TRACE_DEFINE_ENUM(EXT4_FC_REASON_FALLOC_RANGE); 106 106 TRACE_DEFINE_ENUM(EXT4_FC_REASON_INODE_JOURNAL_DATA); 107 + TRACE_DEFINE_ENUM(EXT4_FC_REASON_ENCRYPTED_FILENAME); 107 108 TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX); 108 109 109 110 #define show_fc_reason(reason) \ ··· 117 116 { EXT4_FC_REASON_RESIZE, "RESIZE"}, \ 118 117 { EXT4_FC_REASON_RENAME_DIR, "RENAME_DIR"}, \ 119 118 { EXT4_FC_REASON_FALLOC_RANGE, "FALLOC_RANGE"}, \ 120 - { EXT4_FC_REASON_INODE_JOURNAL_DATA, "INODE_JOURNAL_DATA"}) 119 + { EXT4_FC_REASON_INODE_JOURNAL_DATA, "INODE_JOURNAL_DATA"}, \ 120 + { EXT4_FC_REASON_ENCRYPTED_FILENAME, "ENCRYPTED_FILENAME"}) 121 121 122 122 TRACE_EVENT(ext4_other_inode_update_time, 123 123 TP_PROTO(struct inode *inode, ino_t orig_ino), ··· 2801 2799 ), 2802 2800 2803 2801 TP_printk("dev %d,%d fc ineligible reasons:\n" 2804 - "%s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u " 2802 + "%s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u, %s:%u" 2805 2803 "num_commits:%lu, ineligible: %lu, numblks: %lu", 2806 2804 MAJOR(__entry->dev), MINOR(__entry->dev), 2807 2805 FC_REASON_NAME_STAT(EXT4_FC_REASON_XATTR), ··· 2813 2811 FC_REASON_NAME_STAT(EXT4_FC_REASON_RENAME_DIR), 2814 2812 FC_REASON_NAME_STAT(EXT4_FC_REASON_FALLOC_RANGE), 2815 2813 FC_REASON_NAME_STAT(EXT4_FC_REASON_INODE_JOURNAL_DATA), 2814 + FC_REASON_NAME_STAT(EXT4_FC_REASON_ENCRYPTED_FILENAME), 2816 2815 __entry->fc_commits, __entry->fc_ineligible_commits, 2817 2816 __entry->fc_numblks) 2818 2817 );