From b9e66a187f8ff1df4a35244b1d1e87a35aae46f3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 5 Aug 2019 12:47:18 -0400 Subject: [PATCH] e2fsck: add a developer-only extended option: clear_all_uninit_bits This option clears the uninitialized bit on all extents of all inodes. Note that this can end up exposing uninitialized data to userspace. It should only used in very specialized situations. This option is only enabled via a new configure flag, --enable-developer-features. It should *not* be enabled by distributions, as it enables features thare only designed for use by ext4 developers. These features have no documentation in the man page, or regression tests, and if it breaks, you get to keep both pieces. Signed-off-by: Theodore Ts'o --- configure | 27 +++++++++++++++++++++++++++ configure.ac | 21 +++++++++++++++++++++ e2fsck/e2fsck.h | 1 + e2fsck/pass1.c | 15 ++++++++++++++- e2fsck/problem.c | 5 +++++ e2fsck/problem.h | 3 +++ e2fsck/unix.c | 5 +++++ lib/config.h.in | 3 +++ 8 files changed, 79 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 065bff7..6f4da1a 100755 --- a/configure +++ b/configure @@ -785,6 +785,7 @@ LIBUUID PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG +DEV_FEATURES_CMT TEST_IO_CMT PRIVATE_LIBS_CMT LDFLAG_DYNAMIC @@ -894,6 +895,7 @@ enable_hardening enable_jbd_debug enable_blkid_debug enable_testio_debug +enable_developer_features enable_libuuid enable_libblkid enable_subset @@ -1580,6 +1582,7 @@ Optional Features: --enable-jbd-debug enable journal debugging --enable-blkid-debug enable blkid debugging --disable-testio-debug disable the use of the test I/O manager for debugging + --enable-developer-features enable features for use by ext4 developers --enable-libuuid build and use private uuid library --enable-libblkid build and use private blkid library --enable-subset enable subset-only build @@ -5168,6 +5171,30 @@ TEST_IO_CMT= fi +# Check whether --enable-developer-features was given. +if test "${enable_developer_features+set}" = set; then : + enableval=$enable_developer_features; +if test "$enableval" = "yes" +then + DEV_FEATURES_CMT= + $as_echo "#define CONFIG_DEVELOPER_FEATURES 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling ext4 developer features" >&5 +$as_echo "Enabling ext4 developer features" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ext4 developer features" >&5 +$as_echo "Disabling ext4 developer features" >&6; } + DEV_FEATURES_CMT="#" +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ext4 developer features by default" >&5 +$as_echo "Disabling ext4 developer features by default" >&6; } +DEV_FEATURES_CMT= + +fi + + diff --git a/configure.ac b/configure.ac index cf03444..18e434b 100644 --- a/configure.ac +++ b/configure.ac @@ -439,6 +439,27 @@ TEST_IO_CMT= ) AC_SUBST(TEST_IO_CMT) dnl +dnl handle --enable-developer-features +dnl +AC_ARG_ENABLE([developer-features], +[ --enable-developer-features enable features for use by ext4 developers], +AH_TEMPLATE([CONFIG_DEVELOPER_FEATURES], + [Define to 1 for features for use by ext4 developers]) +if test "$enableval" = "yes" +then + DEV_FEATURES_CMT= + AC_DEFINE(CONFIG_DEVELOPER_FEATURES, 1) + AC_MSG_RESULT([Enabling ext4 developer features]) +else + AC_MSG_RESULT([Disabling ext4 developer features]) + DEV_FEATURES_CMT="#" +fi +, +AC_MSG_RESULT([Disabling ext4 developer features by default]) +DEV_FEATURES_CMT= +) +AC_SUBST(DEV_FEATURES_CMT) +dnl dnl handle --disable-libuuid dnl PKG_PROG_PKG_CONFIG diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 2d359b3..fc0e5c8 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -174,6 +174,7 @@ struct resource_track { #define E2F_OPT_NOOPT_EXTENTS 0x10000 /* don't optimize extents */ #define E2F_OPT_ICOUNT_FULLMAP 0x20000 /* use an array for inode counts */ #define E2F_OPT_UNSHARE_BLOCKS 0x40000 +#define E2F_OPT_CLEAR_UNINIT 0x80000 /* Hack to clear the uninit bit */ /* * E2fsck flags diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 524577a..41eac08 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2855,7 +2855,20 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, return; failed_csum = 0; } - +#ifdef CONFIG_DEVELOPER_FEATURES + if (try_repairs && !is_dir && problem == 0 && + (ctx->options & E2F_OPT_CLEAR_UNINIT) && + (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + fix_problem(ctx, PR_1_CLEAR_UNINIT_EXTENT, pctx)) { + extent.e_flags &= ~EXT2_EXTENT_FLAGS_UNINIT; + pb->inode_modified = 1; + pctx->errcode = ext2fs_extent_replace(ehandle, 0, + &extent); + if (pctx->errcode) + return; + failed_csum = 0; + } +#endif if (try_repairs && problem) { report_problem: if (fix_problem(ctx, problem, pctx)) { diff --git a/e2fsck/problem.c b/e2fsck/problem.c index c45c6b7..4863ea7 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1240,6 +1240,11 @@ static struct e2fsck_problem problem_table[] = { N_("EA @i %N for parent @i %i missing EA_INODE flag.\n "), PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 }, + /* Offer to clear uninitialized flag on an extent */ + { PR_1_CLEAR_UNINIT_EXTENT, + /* xgettext:no-c-format */ + N_("@i %i has @x marked uninitialized at @b %c (len %N). "), + PROMPT_CLEAR, PR_PREEN_OK, 0, 0, 0 }, /* Pass 1b errors */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 2c79169..67a9f95 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -693,6 +693,9 @@ struct problem_context { /* EA inode for parent inode does not have EXT4_EA_INODE_FL flag */ #define PR_1_ATTR_SET_EA_INODE_FL 0x010086 +/* Offer to clear uninitialized flag on an extent */ +#define PR_1_CLEAR_UNINIT_EXTENT 0x010087 + /* * Pass 1b errors diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 68f4987..b3ef0f2 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -753,6 +753,11 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) ctx->options |= E2F_OPT_UNSHARE_BLOCKS; ctx->options |= E2F_OPT_FORCE; continue; +#ifdef CONFIG_DEVELOPER_FEATURES + } else if (strcmp(token, "clear_all_uninit_bits") == 0) { + ctx->options |= E2F_OPT_CLEAR_UNINIT; + continue; +#endif } else { fprintf(stderr, _("Unknown extended option: %s\n"), token); diff --git a/lib/config.h.in b/lib/config.h.in index 407911c..b448482 100644 --- a/lib/config.h.in +++ b/lib/config.h.in @@ -9,6 +9,9 @@ /* Define to 1 to compile findfs */ #undef CONFIG_BUILD_FINDFS +/* Define to 1 for features for use by ext4 developers */ +#undef CONFIG_DEVELOPER_FEATURES + /* Define to 1 if debugging ext3/4 journal code */ #undef CONFIG_JBD_DEBUG -- 1.8.3.1