From 2faf75d24161a7d2d682985812bb9f8f2faea323 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 8 Nov 2019 21:53:42 -0500 Subject: [PATCH] Sync kernel's fix for potential double free in jbd2 Commit 0d52154bb0a7 ("jbd2: fix potential double free") changes the interface exported by revoke.c to initialize and destroy the slab caches. Make the necessary changes to the code in e2fsck and debugfs which calls revoke.c Signed-off-by: Theodore Ts'o --- debugfs/journal.c | 27 ++++++++++++++++++++++----- e2fsck/jfs_user.h | 7 +++++-- e2fsck/journal.c | 12 ++++++++++-- e2fsck/revoke.c | 32 ++++++++++++++++++++------------ lib/ext2fs/jfs_compat.h | 1 + 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/debugfs/journal.c b/debugfs/journal.c index 7908e98..c55a6ef 100644 --- a/debugfs/journal.c +++ b/debugfs/journal.c @@ -741,7 +741,14 @@ static errcode_t recover_ext3_journal(ext2_filsys fs) journal_t *journal; errcode_t retval; - jbd2_journal_init_revoke_caches(); + retval = jbd2_journal_init_revoke_record_cache(); + if (retval) + return retval; + + retval = jbd2_journal_init_revoke_table_cache(); + if (retval) + return retval; + retval = ext2fs_get_journal(fs, &journal); if (retval) return retval; @@ -765,7 +772,8 @@ static errcode_t recover_ext3_journal(ext2_filsys fs) errout: jbd2_journal_destroy_revoke(journal); - jbd2_journal_destroy_revoke_caches(); + jbd2_journal_destroy_revoke_record_cache(); + jbd2_journal_destroy_revoke_table_cache(); ext2fs_journal_release(fs, journal, 1, 0); return retval; } @@ -831,7 +839,14 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j) journal_t *journal; errcode_t retval; - jbd2_journal_init_revoke_caches(); + retval = jbd2_journal_init_revoke_record_cache(); + if (retval) + return retval; + + retval = jbd2_journal_init_revoke_table_cache(); + if (retval) + return retval; + retval = ext2fs_get_journal(fs, &journal); if (retval) return retval; @@ -854,7 +869,8 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j) errout: jbd2_journal_destroy_revoke(journal); - jbd2_journal_destroy_revoke_caches(); + jbd2_journal_destroy_revoke_record_cache(); + jbd2_journal_destroy_revoke_table_cache(); ext2fs_journal_release(fs, journal, 1, 0); return retval; } @@ -864,7 +880,8 @@ errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j) journal_t *journal = *j; jbd2_journal_destroy_revoke(journal); - jbd2_journal_destroy_revoke_caches(); + jbd2_journal_destroy_revoke_record_cache(); + jbd2_journal_destroy_revoke_table_cache(); ext2fs_journal_release(fs, journal, 0, 0); *j = NULL; diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h index 1445c3e..9955578 100644 --- a/e2fsck/jfs_user.h +++ b/e2fsck/jfs_user.h @@ -256,8 +256,11 @@ extern int jbd2_journal_skip_recovery (journal_t *); /* revoke.c */ extern int jbd2_journal_init_revoke(journal_t *, int); extern void jbd2_journal_destroy_revoke(journal_t *); -extern void jbd2_journal_destroy_revoke_caches(void); -extern int jbd2_journal_init_revoke_caches(void); +extern void jbd2_journal_destroy_revoke_record_cache(void); +extern void jbd2_journal_destroy_revoke_table_cache(void); +extern int jbd2_journal_init_revoke_record_cache(void); +extern int jbd2_journal_init_revoke_table_cache(void); + extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t); extern int jbd2_journal_test_revoke(journal_t *, unsigned long long, tid_t); diff --git a/e2fsck/journal.c b/e2fsck/journal.c index 3ab151b..9a0ced5 100644 --- a/e2fsck/journal.c +++ b/e2fsck/journal.c @@ -929,7 +929,14 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx) clear_problem_context(&pctx); - jbd2_journal_init_revoke_caches(); + retval = jbd2_journal_init_revoke_record_cache(); + if (retval) + return retval; + + retval = jbd2_journal_init_revoke_table_cache(); + if (retval) + return retval; + retval = e2fsck_get_journal(ctx, &journal); if (retval) return retval; @@ -957,7 +964,8 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx) errout: jbd2_journal_destroy_revoke(journal); - jbd2_journal_destroy_revoke_caches(); + jbd2_journal_destroy_revoke_record_cache(); + jbd2_journal_destroy_revoke_table_cache(); e2fsck_journal_release(ctx, journal, 1, 0); return retval; } diff --git a/e2fsck/revoke.c b/e2fsck/revoke.c index 3f78330..7779b9d 100644 --- a/e2fsck/revoke.c +++ b/e2fsck/revoke.c @@ -183,33 +183,41 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, return NULL; } -void jbd2_journal_destroy_revoke_caches(void) +void jbd2_journal_destroy_revoke_record_cache(void) { kmem_cache_destroy(jbd2_revoke_record_cache); jbd2_revoke_record_cache = NULL; +} + +void jbd2_journal_destroy_revoke_table_cache(void) +{ kmem_cache_destroy(jbd2_revoke_table_cache); jbd2_revoke_table_cache = NULL; } -int __init jbd2_journal_init_revoke_caches(void) +int __init jbd2_journal_init_revoke_record_cache(void) { J_ASSERT(!jbd2_revoke_record_cache); - J_ASSERT(!jbd2_revoke_table_cache); - jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s, SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY); - if (!jbd2_revoke_record_cache) - goto record_cache_failure; + if (!jbd2_revoke_record_cache) { + pr_emerg("JBD2: failed to create revoke_record cache\n"); + return -ENOMEM; + } + return 0; +} + +int __init jbd2_journal_init_revoke_table_cache(void) +{ + J_ASSERT(!jbd2_revoke_table_cache); jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s, SLAB_TEMPORARY); - if (!jbd2_revoke_table_cache) - goto table_cache_failure; - return 0; -table_cache_failure: - jbd2_journal_destroy_revoke_caches(); -record_cache_failure: + if (!jbd2_revoke_table_cache) { + pr_emerg("JBD2: failed to create revoke_table cache\n"); return -ENOMEM; + } + return 0; } static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) diff --git a/lib/ext2fs/jfs_compat.h b/lib/ext2fs/jfs_compat.h index 42c9e30..c595be3 100644 --- a/lib/ext2fs/jfs_compat.h +++ b/lib/ext2fs/jfs_compat.h @@ -58,6 +58,7 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), #define blkdev_issue_flush(kdev, a, b) sync_blockdev(kdev) #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) +#define pr_emerg(fmt) struct journal_s { -- 1.8.3.1