From 016a7696054f6e6b357cd773389f6adb2e172073 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 19 Mar 2024 13:49:24 +0100 Subject: [PATCH] tresor: check only the last secured superblock Instead of iterating over all superblocks and checking each valid one, check only the one whose hash matches the hash stored in the trust anchor. I.e., the last one that was secured to the trust anchor. We must assume that the other superblocks were corrupted in the meantime by operating the Tresor container and, anyway, these Superblocks are not used anymore. Ref #5077 --- repos/gems/src/app/tresor_check/main.cc | 9 ++- repos/gems/src/app/tresor_tester/main.cc | 2 +- .../src/lib/tresor/include/tresor/sb_check.h | 15 ++-- repos/gems/src/lib/tresor/sb_check.cc | 76 +++++++++---------- 4 files changed, 55 insertions(+), 47 deletions(-) diff --git a/repos/gems/src/app/tresor_check/main.cc b/repos/gems/src/app/tresor_check/main.cc index 523833162d..3b51f132b7 100644 --- a/repos/gems/src/app/tresor_check/main.cc +++ b/repos/gems/src/app/tresor_check/main.cc @@ -43,18 +43,25 @@ class Tresor_check::Main : private Vfs::Env::User Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; Signal_handler
_sigh { _env.ep(), *this, &Main::_handle_signal }; Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) }; + Tresor::Path const _trust_anchor_path { _config_rom.xml().sub_node("trust-anchor").attribute_value("path", Tresor::Path()) }; Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; Block_io _block_io { _block_io_file }; Vbd_check _vbd_check { }; Ft_check _ft_check { }; Sb_check _sb_check { }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; Sb_check::Check _check_superblocks { }; void _wakeup_back_end_services() { _vfs_env.io().commit(); } void _handle_signal() { - while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io)); + while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io, _trust_anchor)); if (_check_superblocks.complete()) _env.parent().exit(_check_superblocks.success() ? 0 : -1); _wakeup_back_end_services(); diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc index c63cc0d484..b7190ee6b1 100644 --- a/repos/gems/src/app/tresor_tester/main.cc +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -868,7 +868,7 @@ class Tresor_tester::Main : Vfs::Env::User, Client_data_interface, Crypto_key_fi case Command::IN_PROGRESS: { Sb_check::Check &req = *cmd.check_superblocks_ptr; - progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io); + progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io, _trust_anchor); _try_complete_command(cmd, req, progress); break; } diff --git a/repos/gems/src/lib/tresor/include/tresor/sb_check.h b/repos/gems/src/lib/tresor/include/tresor/sb_check.h index 1cace44139..672e68c1e4 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_check.h @@ -19,6 +19,7 @@ #include #include #include +#include namespace Tresor { class Sb_check; } @@ -34,23 +35,25 @@ struct Tresor::Sb_check : Noncopyable enum State { INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, CHECK_VBD, CHECK_VBD_SUCCEEDED, CHECK_FT, CHECK_FT_SUCCEEDED, - CHECK_MT, CHECK_MT_SUCCEEDED}; + CHECK_MT, CHECK_MT_SUCCEEDED, READ_SB_HASH, READ_SB_HASH_SUCCEEDED }; using Helper = Request_helper; Helper _helper; - Generation _highest_gen { 0 }; - Superblock_index _highest_gen_sb_idx { 0 }; + Hash _hash { }; bool _scan_for_highest_gen_sb_done { false }; - Superblock_index _sb_idx { 0 }; + Superblock_index _sb_idx { }; Superblock _sb { }; Snapshot_index _snap_idx { 0 }; Constructible _tree_root { }; Block _blk { }; + Generatable_request _read_sb_hash { }; Generatable_request _check_vbd { }; Generatable_request _check_ft { }; Generatable_request _read_block { }; + void _check_snap(bool &); + public: Check() : _helper(*this) { } @@ -59,7 +62,7 @@ struct Tresor::Sb_check : Noncopyable void print(Output &out) const { Genode::print(out, "check"); } - bool execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io); + bool execute(Vbd_check &, Ft_check &, Block_io &, Trust_anchor &); bool complete() const { return _helper.complete(); } bool success() const { return _helper.success(); } @@ -67,7 +70,7 @@ struct Tresor::Sb_check : Noncopyable Sb_check() { } - bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { return check.execute(vbd_check, ft_check, block_io); }; + bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io, Trust_anchor &trust_anchor) { return check.execute(vbd_check, ft_check, block_io, trust_anchor); }; static constexpr char const *name() { return "sb_check"; } }; diff --git a/repos/gems/src/lib/tresor/sb_check.cc b/repos/gems/src/lib/tresor/sb_check.cc index 310d9e3fbc..4b3dbe9f52 100644 --- a/repos/gems/src/lib/tresor/sb_check.cc +++ b/repos/gems/src/lib/tresor/sb_check.cc @@ -13,62 +13,62 @@ /* tresor includes */ #include +#include using namespace Tresor; -bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) +void Sb_check::Check::_check_snap(bool &progress) +{ + Snapshot &snap { _sb.snapshots.items[_snap_idx] }; + if (!snap.valid) { + _helper.state = CHECK_VBD_SUCCEEDED; + progress = true; + if (VERBOSE_CHECK) + log(" skip snap ", _snap_idx, " as it is unused"); + return; + } + _tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves); + _check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root); + if (VERBOSE_CHECK) + log(" check snap ", _snap_idx, " (", snap, ")"); +} + + +bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io, Trust_anchor &trust_anchor) { bool progress = false; switch (_helper.state) { case INIT: - _highest_gen = 0; - _highest_gen_sb_idx = 0; - _snap_idx = 0; - _sb_idx = 0; - _scan_for_highest_gen_sb_done = false; + _read_sb_hash.generate(_helper, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, progress, _hash); + break; + + case READ_SB_HASH: progress |= _read_sb_hash.execute(trust_anchor); break; + case READ_SB_HASH_SUCCEEDED: + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: - _sb.decode_from_blk(_blk); - if (_scan_for_highest_gen_sb_done) { + if (check_hash(_blk, _hash)) { + _sb.decode_from_blk(_blk); + if (VERBOSE_CHECK) + log("check superblock ", _sb_idx, " hash ", _hash, "\n read superblock"); + if (!_sb.valid()) { - _helper.mark_failed(progress, "no valid superblock");; + _helper.mark_failed(progress, "superblock marked invalid");; break; } - Snapshot &snap { _sb.snapshots.items[_snap_idx] }; - if (snap.valid) { - Snapshot &snap { _sb.snapshots.items[_snap_idx] }; - _tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves); - _check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root); - if (VERBOSE_CHECK) - log(" check snap ", _snap_idx, " (", snap, ")"); - } else { - _helper.state = CHECK_VBD_SUCCEEDED; - progress = true; - if (VERBOSE_CHECK) - log(" skip snap ", _snap_idx, " as it is unused"); - } - } else { - Snapshot &snap { _sb.curr_snap() }; - if (_sb.valid() && snap.gen > _highest_gen) { - _highest_gen = snap.gen; - _highest_gen_sb_idx = _sb_idx; - } + _snap_idx = 0; + _check_snap(progress); + } else if (_sb_idx < MAX_SUPERBLOCK_INDEX) { _sb_idx++; _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk); - progress = true; - } else { - _scan_for_highest_gen_sb_done = true; - _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _highest_gen_sb_idx, _blk); - if (VERBOSE_CHECK) - log("check superblock ", _highest_gen_sb_idx, "\n read superblock"); - } - } + } else + _helper.mark_failed(progress, "superblock not found"); break; case CHECK_VBD: progress |= _check_vbd.execute(vbd_check, block_io); break; @@ -76,10 +76,8 @@ bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io if (_snap_idx < MAX_SNAP_IDX) { _snap_idx++; - _helper.state = READ_BLK_SUCCEEDED; - progress = true; + _check_snap(progress); } else { - _snap_idx = 0; _tree_root.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves); _check_ft.generate(_helper, CHECK_FT, CHECK_FT_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK)