From: Jan Janssen Date: Fri, 10 Dec 2021 10:55:38 +0000 (+0100) Subject: test: Add BCD unit test X-Git-Tag: v250-rc3~62^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=db7f5ab68f0691ed887224dd64ce7a2b7df91e33;p=thirdparty%2Fsystemd.git test: Add BCD unit test --- diff --git a/meson.build b/meson.build index 4c0dd6f8c99..e77c2aa3ac0 100644 --- a/meson.build +++ b/meson.build @@ -1676,8 +1676,14 @@ conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesync conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests) -##################################################################### +############################################################ + +tests = [] +fuzzers = [] + +############################################################ +# Include these now as they provide gnu-efi detection. subdir('src/fundamental') subdir('src/boot/efi') @@ -1695,7 +1701,7 @@ update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh') xml_helper_py = find_program('tools/xml_helper.py') export_dbus_interfaces_py = find_program('tools/dbus_exporter.py') -##################################################################### +############################################################ config_h = configure_file( output : 'config.h', @@ -1716,9 +1722,6 @@ if dbus_interfaces_dir == '' dbus_interfaces_dir = get_option('datadir') + '/dbus-1' endif -tests = [] -fuzzers = [] - basic_includes = include_directories( 'src/basic', 'src/fundamental', diff --git a/src/boot/efi/bcd.c b/src/boot/efi/bcd.c index 7eabb4da1a5..970c8b1c8ec 100644 --- a/src/boot/efi/bcd.c +++ b/src/boot/efi/bcd.c @@ -1,8 +1,27 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include -#include "macro-fundamental.h" -#include "util.h" +#ifdef SD_BOOT +# include +# include "macro-fundamental.h" +# include "util.h" +# define TEST_STATIC +#else +/* Provide our own "EFI API" if we are running as a unit test. */ +# include +# include +# include +# include "string-util-fundamental.h" + +# define CHAR8 char +# define CHAR16 char16_t +# define UINT8 uint8_t +# define UINT16 uint16_t +# define UINT32 uint32_t +# define UINT64 uint64_t +# define UINTN size_t +# define strncaseeqa(a, b, n) strncaseeq((a), (b), (n)) +# define TEST_STATIC static +#endif enum { SIG_BASE_BLOCK = 1718052210, /* regf */ @@ -206,7 +225,7 @@ static const KeyValue *get_key_value(const UINT8 *bcd, UINT32 bcd_len, const Key * (it always has the GUID 9dea862c-5cdd-4e70-acc1-f32b344d4795). If it contains more than * one GUID, the BCD is multi-boot and we stop looking. Otherwise we take that GUID, look it * up, and return its description property. */ -CHAR16 *get_bcd_title(UINT8 *bcd, UINTN bcd_len) { +TEST_STATIC CHAR16 *get_bcd_title(UINT8 *bcd, UINTN bcd_len) { assert(bcd); if (HIVE_CELL_OFFSET > bcd_len) diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 81e8734452b..a108bf16ab4 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -373,6 +373,14 @@ endforeach ############################################################ +tests += [ + [['src/boot/efi/test-bcd.c'], + [], + [libzstd], + [], + 'HAVE_ZSTD'], +] + test_efi_disk_img = custom_target( 'test-efi-disk.img', input : [efi_stubs[0][0], efi_stubs[1][1]], diff --git a/src/boot/efi/test-bcd.c b/src/boot/efi/test-bcd.c new file mode 100644 index 00000000000..a4d09068a5d --- /dev/null +++ b/src/boot/efi/test-bcd.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "compress.h" +#include "fileio.h" +#include "tests.h" +#include "utf8.h" + +/* Inlcude the implementation directly, so we can poke at some internals. */ +#include "bcd.c" + +static void load_bcd(const char *path, void **ret_bcd, size_t *ret_bcd_len) { + size_t len; + _cleanup_free_ char *fn = NULL, *compressed = NULL; + + assert_se(get_testdata_dir(path, &fn) >= 0); + assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, SIZE_MAX, 0, NULL, &compressed, &len) >= 0); + assert_se(decompress_blob_zstd(compressed, len, ret_bcd, ret_bcd_len, SIZE_MAX) >= 0); +} + +static void test_get_bcd_title_one( + const char *path, + const char16_t *title_expect, + size_t title_len_expect) { + + size_t len; + _cleanup_free_ void *bcd = NULL; + + log_info("/* %s(%s) */", __func__, path); + + load_bcd(path, &bcd, &len); + + char16_t *title = get_bcd_title(bcd, len); + if (title_expect) { + assert_se(title); + assert_se(memcmp(title, title_expect, title_len_expect) == 0); + } else + assert_se(!title); +} + +TEST(get_bcd_title) { + const char16_t win10[] = { 'W', 'i', 'n', 'd', 'o', 'w', 's', ' ', '1', '0', '\0' }; + test_get_bcd_title_one("test-bcd/win10.bcd.zst", win10, sizeof(win10)); + + test_get_bcd_title_one("test-bcd/description-bad-type.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-empty.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-missing.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/description-too-small.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-name.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-size.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/displayorder-bad-type.bcd.zst", NULL, 0); + test_get_bcd_title_one("test-bcd/empty.bcd.zst", NULL, 0); +} + +TEST(base_block) { + size_t len; + BaseBlock backup; + uint8_t *bcd_base; + _cleanup_free_ BaseBlock *bcd = NULL; + + load_bcd("test-bcd/win10.bcd.zst", (void **) &bcd, &len); + backup = *bcd; + bcd_base = (uint8_t *) bcd; + + assert_se(get_bcd_title(bcd_base, len)); + + /* Try various "corruptions" of the base block. */ + + assert_se(!get_bcd_title(bcd_base, sizeof(BaseBlock) - 1)); + + bcd->sig = 0; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->version_minor = 2; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->version_major = 4; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->type = 1; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; + + bcd->primary_seqnum++; + assert_se(!get_bcd_title(bcd_base, len)); + *bcd = backup; +} + +TEST(bad_bcd) { + size_t len; + uint8_t *hbins; + uint32_t offset; + _cleanup_free_ void *bcd = NULL; + + /* This BCD hive has been manipulated to have bad offsets/sizes at various places. */ + load_bcd("test-bcd/corrupt.bcd.zst", &bcd, &len); + + assert_se(len >= HIVE_CELL_OFFSET); + hbins = (uint8_t *) bcd + HIVE_CELL_OFFSET; + len -= HIVE_CELL_OFFSET; + offset = ((BaseBlock *) bcd)->root_cell_offset; + + const Key *root = get_key(hbins, len, offset, "\0"); + assert_se(root); + assert_se(!get_key(hbins, sizeof(Key) - 1, offset, "\0")); + + assert_se(!get_key(hbins, len, offset, "\0BadOffset\0")); + assert_se(!get_key(hbins, len, offset, "\0BadSig\0")); + assert_se(!get_key(hbins, len, offset, "\0BadKeyNameLen\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadOffset\0Dummy\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadSig\0Dummy\0")); + assert_se(!get_key(hbins, len, offset, "\0SubkeyBadNEntries\0Dummy\0")); + + assert_se(!get_key_value(hbins, len, root, "Dummy")); + + const Key *kv_bad_offset = get_key(hbins, len, offset, "\0KeyValuesBadOffset\0"); + assert_se(kv_bad_offset); + assert_se(!get_key_value(hbins, len, kv_bad_offset, "Dummy")); + + const Key *kv_bad_n_key_values = get_key(hbins, len, offset, "\0KeyValuesBadNKeyValues\0"); + assert_se(kv_bad_n_key_values); + assert_se(!get_key_value(hbins, len, kv_bad_n_key_values, "Dummy")); + + const Key *kv = get_key(hbins, len, offset, "\0KeyValues\0"); + assert_se(kv); + + assert_se(!get_key_value(hbins, len, kv, "BadOffset")); + assert_se(!get_key_value(hbins, len, kv, "BadSig")); + assert_se(!get_key_value(hbins, len, kv, "BadNameLen")); + assert_se(!get_key_value(hbins, len, kv, "InlineData")); + assert_se(!get_key_value(hbins, len, kv, "BadDataOffset")); + assert_se(!get_key_value(hbins, len, kv, "BadDataSize")); +} + +TEST(argv_bcds) { + for (int i = 1; i < saved_argc; i++) { + size_t len; + _cleanup_free_ void *bcd = NULL; + + assert_se(read_full_file_full( + AT_FDCWD, + saved_argv[i], + UINT64_MAX, + SIZE_MAX, + 0, + NULL, + (char **) &bcd, + &len) >= 0); + + char16_t *title = get_bcd_title(bcd, len); + if (title) { + _cleanup_free_ char *title_utf8 = utf16_to_utf8(title, char16_strlen(title) * 2); + log_info("%s: \"%s\"", saved_argv[i], title_utf8); + } else + log_info("%s: Bad BCD", saved_argv[i]); + } +} + +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/test/meson.build b/test/meson.build index fad40b89464..7d94032d09e 100644 --- a/test/meson.build +++ b/test/meson.build @@ -67,6 +67,11 @@ if install_tests '../-.mount', testsuite08_dir + '/local-fs.target.wants/-.mount') + if conf.get('HAVE_GNU_EFI') == 1 and conf.get('HAVE_ZSTD') == 1 + install_subdir('test-bcd', + exclude_files : '.gitattributes', + install_dir : testdata_dir) + endif if conf.get('ENABLE_RESOLVE') == 1 install_subdir('test-resolve', exclude_files : '.gitattributes', diff --git a/test/test-bcd/.gitattributes b/test/test-bcd/.gitattributes new file mode 100644 index 00000000000..b5f1b48c1ae --- /dev/null +++ b/test/test-bcd/.gitattributes @@ -0,0 +1,2 @@ +*.bcd binary +*.bcd.zst binary diff --git a/test/test-bcd/corrupt.bcd.zst b/test/test-bcd/corrupt.bcd.zst new file mode 100644 index 00000000000..48b570161cd Binary files /dev/null and b/test/test-bcd/corrupt.bcd.zst differ diff --git a/test/test-bcd/description-bad-type.bcd.zst b/test/test-bcd/description-bad-type.bcd.zst new file mode 100644 index 00000000000..fdf23ca7212 Binary files /dev/null and b/test/test-bcd/description-bad-type.bcd.zst differ diff --git a/test/test-bcd/description-empty.bcd.zst b/test/test-bcd/description-empty.bcd.zst new file mode 100644 index 00000000000..c1c801d271b Binary files /dev/null and b/test/test-bcd/description-empty.bcd.zst differ diff --git a/test/test-bcd/description-missing.bcd.zst b/test/test-bcd/description-missing.bcd.zst new file mode 100644 index 00000000000..a34ad8a4c10 Binary files /dev/null and b/test/test-bcd/description-missing.bcd.zst differ diff --git a/test/test-bcd/description-too-small.bcd.zst b/test/test-bcd/description-too-small.bcd.zst new file mode 100644 index 00000000000..76e739369ef Binary files /dev/null and b/test/test-bcd/description-too-small.bcd.zst differ diff --git a/test/test-bcd/displayorder-bad-name.bcd.zst b/test/test-bcd/displayorder-bad-name.bcd.zst new file mode 100644 index 00000000000..157f54e3559 Binary files /dev/null and b/test/test-bcd/displayorder-bad-name.bcd.zst differ diff --git a/test/test-bcd/displayorder-bad-size.bcd.zst b/test/test-bcd/displayorder-bad-size.bcd.zst new file mode 100644 index 00000000000..ee89b7709be Binary files /dev/null and b/test/test-bcd/displayorder-bad-size.bcd.zst differ diff --git a/test/test-bcd/displayorder-bad-type.bcd.zst b/test/test-bcd/displayorder-bad-type.bcd.zst new file mode 100644 index 00000000000..cc2a8879e7a Binary files /dev/null and b/test/test-bcd/displayorder-bad-type.bcd.zst differ diff --git a/test/test-bcd/empty.bcd.zst b/test/test-bcd/empty.bcd.zst new file mode 100644 index 00000000000..5b3e9384935 Binary files /dev/null and b/test/test-bcd/empty.bcd.zst differ diff --git a/test/test-bcd/win10.bcd.zst b/test/test-bcd/win10.bcd.zst new file mode 100644 index 00000000000..c922eb6042f Binary files /dev/null and b/test/test-bcd/win10.bcd.zst differ