diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2019-04-29 17:25:45 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-01 11:02:59 -0700 |
commit | 13089909211c5289c46d22a3cb7fb9b06efcd917 (patch) | |
tree | b77aedebccc921f8f07b86c2dbcadea4ef13315d /test | |
parent | 262ded1e01a374537e56160811bdad5763b311a5 (diff) | |
download | chrome-ec-13089909211c5289c46d22a3cb7fb9b06efcd917.tar.gz |
nvmem: fix delimiter creation during setvar()
The (key, value) objects should not be treated differently from TPM
objects when initializing NVMEM from some inconsistent state.
Saving of a modified (key, value) object should include the
'incomplete delimiter' phase when the new value has been already
saved, but the old value has not yet been eliminated.
Added tests verifying various failure modes.
BRANCH=cr50, cr50-mp
BUG=b:69907320, b:129710256
TEST='make run-nvmem' succeeds
Change-Id: Ia53b6cfa2edd59fef28ace6978d752ca3cfbb2aa
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1590043
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Diffstat (limited to 'test')
-rw-r--r-- | test/nvmem.c | 106 | ||||
-rw-r--r-- | test/nvmem_test.h | 4 |
2 files changed, 104 insertions, 6 deletions
diff --git a/test/nvmem.c b/test/nvmem.c index dc5cde1eee..a7e339ebf1 100644 --- a/test/nvmem.c +++ b/test/nvmem.c @@ -1330,15 +1330,110 @@ static int test_tpm_nvmem_modify_evictable_objects(void) return EC_SUCCESS; } +static int test_nvmem_tuple_updates(void) +{ + size_t i; + const char *modified_var1 = "var one after"; + const struct tuple *t; + + const struct { + uint8_t *key; + uint8_t *value; + } kv_pairs[] = { + /* Use # as the delimiter to allow \0 in keys/values. */ + {"key0", "var zero before"}, + {"key1", "var one before"} + }; + + TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS); + + /* Save vars in the nvmem. */ + for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) + TEST_ASSERT(setvar(kv_pairs[i].key, strlen(kv_pairs[i].key), + kv_pairs[i].value, + strlen(kv_pairs[i].value)) == EC_SUCCESS); + + TEST_ASSERT(nvmem_init() == EC_SUCCESS); + /* Verify the vars are still there. */ + for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) { + const struct tuple *t; + + t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key)); + TEST_ASSERT(t); + TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value)); + TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key), + kv_pairs[i].value, t->val_len)); + freevar(t); + } + + /* + * Now, let's try updating variable 'key1' introducing various failure + * modes. + */ + failure_mode = TEST_FAIL_SAVING_VAR; + TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key), + modified_var1, strlen(modified_var1)) == EC_SUCCESS); + TEST_ASSERT(nvmem_init() == EC_SUCCESS); + /* No change should be seen. */ + for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) { + t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key)); + TEST_ASSERT(t); + TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value)); + TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key), + kv_pairs[i].value, t->val_len)); + freevar(t); + } + failure_mode = TEST_FAIL_FINALIZING_VAR; + TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key), + modified_var1, strlen(modified_var1)) == EC_SUCCESS); + failure_mode = TEST_NO_FAILURE; + TEST_ASSERT(nvmem_init() == EC_SUCCESS); + + /* First variable should be still unchanged. */ + t = getvar(kv_pairs[0].key, strlen(kv_pairs[0].key)); + TEST_ASSERT(t); + TEST_ASSERT(t->val_len == strlen(kv_pairs[0].value)); + TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[0].key), + kv_pairs[0].value, t->val_len)); + freevar(t); + + /* Second variable should be updated. */ + t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)); + TEST_ASSERT(t); + TEST_ASSERT(t->val_len == strlen(modified_var1)); + TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[1].key), modified_var1, + t->val_len)); + freevar(t); + + /* A corrupted attempt to update second variable. */ + failure_mode = TEST_FAIL_FINALIZING_VAR; + TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key), + kv_pairs[1].value, strlen(kv_pairs[1].value)) + == EC_SUCCESS); + failure_mode = TEST_NO_FAILURE; + TEST_ASSERT(nvmem_init() == EC_SUCCESS); + + /* Is there an instance of the second variable still in the flash. */ + t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)); + TEST_ASSERT(t); + freevar(t); + + /* Delete the remaining instance of the variable. */ + TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key), + NULL, 0) == EC_SUCCESS); + + /* Verify that it is indeed deleted before and after re-init. */ + TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key))); + TEST_ASSERT(nvmem_init() == EC_SUCCESS); + TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key))); + + return EC_SUCCESS; +} + void run_test(void) { run_test_setup(); - if (0) { - RUN_TEST(test_nvmem_incomplete_transaction); - test_print_result(); - return; - } RUN_TEST(test_migration); RUN_TEST(test_corrupt_nvmem); RUN_TEST(test_fully_erased_nvmem); @@ -1351,6 +1446,7 @@ void run_test(void) RUN_TEST(test_tpm_nvmem_modify_reserved_objects); RUN_TEST(test_tpm_nvmem_modify_evictable_objects); RUN_TEST(test_nvmem_incomplete_transaction); + RUN_TEST(test_nvmem_tuple_updates); failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */ RUN_TEST(test_nvmem_interrupted_compaction); failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */ diff --git a/test/nvmem_test.h b/test/nvmem_test.h index f8f166dc5e..9e050582ac 100644 --- a/test/nvmem_test.h +++ b/test/nvmem_test.h @@ -17,7 +17,9 @@ enum test_failure_mode { TEST_NO_FAILURE, TEST_FAIL_WHEN_SAVING, TEST_FAIL_WHEN_INVALIDATING, - TEST_FAIL_WHEN_COMPACTING + TEST_FAIL_WHEN_COMPACTING, + TEST_FAIL_SAVING_VAR, + TEST_FAIL_FINALIZING_VAR }; extern enum test_failure_mode failure_mode; |