From: Darrick J. Wong Date: Fri, 25 Feb 2022 22:37:56 +0000 (-0500) Subject: misc: add a crc32c self test to mkfs and repair X-Git-Tag: v5.15.0-rc1~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ca14a5706ffd2f3eb70002a2990e229103d881f6;p=thirdparty%2Fxfsprogs-dev.git misc: add a crc32c self test to mkfs and repair Enhance mkfs and xfs_repair to run the crc32c self test when they start up, and refuse to continue if the self test fails. We don't want to format a filesystem if the checksum algorithm produces incorrect results, and we especially don't want repair to tear a filesystem apart because it thinks the checksum is wrong. Signed-off-by: Darrick J. Wong Reviewed-by: Eric Sandeen Signed-off-by: Eric Sandeen --- diff --git a/io/crc32cselftest.c b/io/crc32cselftest.c index f8f757f6a..49eb5b6d2 100644 --- a/io/crc32cselftest.c +++ b/io/crc32cselftest.c @@ -16,7 +16,7 @@ crc32cselftest_f( int argc, char **argv) { - return crc32c_test() != 0; + return crc32c_test(0) != 0; } static const cmdinfo_t crc32cselftest_cmd = { diff --git a/libfrog/crc32.c b/libfrog/crc32.c index 6a273b715..2499615df 100644 --- a/libfrog/crc32.c +++ b/libfrog/crc32.c @@ -202,7 +202,7 @@ int main(int argc, char **argv) printf("CRC_LE_BITS = %d\n", CRC_LE_BITS); - errors = crc32c_test(); + errors = crc32c_test(0); return errors != 0; } diff --git a/libfrog/crc32cselftest.h b/libfrog/crc32cselftest.h index 08284153c..447a7f7de 100644 --- a/libfrog/crc32cselftest.h +++ b/libfrog/crc32cselftest.h @@ -661,18 +661,22 @@ static struct crc_test { {0xb18a0319, 0x00000026, 0x000007db, 0x9dc0bb48}, }; +/* Don't print anything to stdout. */ +#define CRC32CTEST_QUIET (1U << 0) + static int -crc32c_test(void) +crc32c_test( + unsigned int flags) { - int i; - int errors = 0; - int bytes = 0; - struct timeval start, stop; - uint64_t usec; + int i; + int errors = 0; + int bytes = 0; + struct timeval start, stop; + uint64_t usec; /* keep static to prevent cache warming code from * getting eliminated by the compiler */ - static uint32_t crc; + static uint32_t crc; /* pre-warm the cache */ for (i = 0; i < 100; i++) { @@ -693,6 +697,9 @@ crc32c_test(void) usec = stop.tv_usec - start.tv_usec + 1000000 * (stop.tv_sec - start.tv_sec); + if (flags & CRC32CTEST_QUIET) + return errors; + if (errors) printf("crc32c: %d self tests failed\n", errors); else { diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index a7f70285d..880e949bb 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -121,6 +121,10 @@ If the size of the block or sector is not specified, the default sizes .PP Many feature options allow an optional argument of 0 or 1, to explicitly disable or enable the functionality. + +The correctness of the crc32c checksum implementation will be tested +before formatting the filesystem. +If the test fails, the format will abort. .SH OPTIONS Options may be specified either on the command line or in a configuration file. Not all command line options can be specified in configuration files; only the diff --git a/man/man8/xfs_repair.8 b/man/man8/xfs_repair.8 index cc6a2be8c..6625b47ad 100644 --- a/man/man8/xfs_repair.8 +++ b/man/man8/xfs_repair.8 @@ -184,6 +184,10 @@ usual 0. This option cannot be used together with .B \-V Prints the version number and exits. .SS Checks Performed +The correctness of the crc32c checksum implementation will be tested +before examining the filesystem. +If the test fails, the program will abort. + Inconsistencies corrected include the following: .IP 1. Inode and inode blockmap (addressing) checks: diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 057b3b091..3a41e17f8 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -10,6 +10,7 @@ #include "libxcmd.h" #include "libfrog/fsgeom.h" #include "libfrog/convert.h" +#include "libfrog/crc32cselftest.h" #include "proto.h" #include @@ -4044,6 +4045,13 @@ main( exit(0); } + /* Make sure our checksum algorithm really works. */ + if (crc32c_test(CRC32CTEST_QUIET) != 0) { + fprintf(stderr, + _("crc32c self-test failed, will not create a filesystem here.\n")); + return 1; + } + /* * All values have been validated, discard the old device layout. */ diff --git a/repair/init.c b/repair/init.c index 55f226e97..3a320b4ff 100644 --- a/repair/init.c +++ b/repair/init.c @@ -14,6 +14,7 @@ #include "bmap.h" #include "incore.h" #include "prefetch.h" +#include "libfrog/crc32cselftest.h" #include static void @@ -100,4 +101,8 @@ _("Unmount or use the dangerous (-d) option to repair a read-only mounted filesy ts_create(); increase_rlimit(); pftrace_init(); + + if (crc32c_test(CRC32CTEST_QUIET) != 0) + do_error( + _("crc32c self-test failed, will not examine filesystem.\n")); }