1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_ 18 #define UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_ 19 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include <brillo/streams/stream.h> 28 29 #include "update_engine/common/action.h" 30 #include "update_engine/common/hash_calculator.h" 31 #include "update_engine/payload_consumer/install_plan.h" 32 #include "update_engine/payload_consumer/verity_writer_interface.h" 33 34 // This action will hash all the partitions of the target slot involved in the 35 // update. The hashes are then verified against the ones in the InstallPlan. 36 // If the target hash does not match, the action will fail. In case of failure, 37 // the error code will depend on whether the source slot hashes are provided and 38 // match. 39 40 namespace chromeos_update_engine { 41 42 // The step FilesystemVerifier is on. On kVerifyTargetHash it computes the hash 43 // on the target partitions based on the already populated size and verifies it 44 // matches the one in the target_hash in the InstallPlan. 45 // If the hash matches, then we skip the kVerifySourceHash step, otherwise we 46 // need to check if the source is the root cause of the mismatch. 47 enum class VerifierStep { 48 kVerifyTargetHash, 49 kVerifySourceHash, 50 }; 51 52 class FilesystemVerifyDelegate { 53 public: 54 virtual ~FilesystemVerifyDelegate() = default; 55 virtual void OnVerifyProgressUpdate(double progress) = 0; 56 }; 57 58 class FilesystemVerifierAction : public InstallPlanAction { 59 public: FilesystemVerifierAction(DynamicPartitionControlInterface * dynamic_control)60 explicit FilesystemVerifierAction( 61 DynamicPartitionControlInterface* dynamic_control) 62 : verity_writer_(verity_writer::CreateVerityWriter()), 63 dynamic_control_(dynamic_control) { 64 CHECK(dynamic_control_); 65 } 66 67 ~FilesystemVerifierAction() override = default; 68 69 void PerformAction() override; 70 void TerminateProcessing() override; 71 72 // Used for listening to progress updates set_delegate(FilesystemVerifyDelegate * delegate)73 void set_delegate(FilesystemVerifyDelegate* delegate) { 74 this->delegate_ = delegate; 75 } get_delegate()76 [[nodiscard]] FilesystemVerifyDelegate* get_delegate() const { 77 return this->delegate_; 78 } 79 80 // Debugging/logging StaticType()81 static std::string StaticType() { return "FilesystemVerifierAction"; } Type()82 std::string Type() const override { return StaticType(); } 83 84 private: 85 friend class FilesystemVerifierActionTestDelegate; 86 // Starts the hashing of the current partition. If there aren't any partitions 87 // remaining to be hashed, it finishes the action. 88 void StartPartitionHashing(); 89 90 // Schedules the asynchronous read of the filesystem. 91 void ScheduleRead(); 92 93 // Called from the main loop when a single read from |src_stream_| succeeds or 94 // fails, calling OnReadDoneCallback() and OnReadErrorCallback() respectively. 95 void OnReadDoneCallback(size_t bytes_read); 96 void OnReadErrorCallback(const brillo::Error* error); 97 98 // When the read is done, finalize the hash checking of the current partition 99 // and continue checking the next one. 100 void FinishPartitionHashing(); 101 102 // Cleans up all the variables we use for async operations and tells the 103 // ActionProcessor we're done w/ |code| as passed in. |cancelled_| should be 104 // true if TerminateProcessing() was called. 105 void Cleanup(ErrorCode code); 106 107 // Invoke delegate callback to report progress, if delegate is not null 108 void UpdateProgress(double progress); 109 110 // The type of the partition that we are verifying. 111 VerifierStep verifier_step_ = VerifierStep::kVerifyTargetHash; 112 113 // The index in the install_plan_.partitions vector of the partition currently 114 // being hashed. 115 size_t partition_index_{0}; 116 117 // If not null, the FileStream used to read from the device. 118 brillo::StreamPtr src_stream_; 119 120 // Buffer for storing data we read. 121 brillo::Blob buffer_; 122 123 bool cancelled_{false}; // true if the action has been cancelled. 124 125 // Calculates the hash of the data. 126 std::unique_ptr<HashCalculator> hasher_; 127 128 // Write verity data of the current partition. 129 std::unique_ptr<VerityWriterInterface> verity_writer_; 130 131 // Verifies the untouched dynamic partitions for partial updates. 132 DynamicPartitionControlInterface* dynamic_control_{nullptr}; 133 134 // Reads and hashes this many bytes from the head of the input stream. When 135 // the partition starts to be hashed, this field is initialized from the 136 // corresponding InstallPlan::Partition size which is the total size 137 // update_engine is expected to write, and may be smaller than the size of the 138 // partition in gpt. 139 uint64_t partition_size_{0}; 140 141 // The byte offset that we are reading in the current partition. 142 uint64_t offset_{0}; 143 144 // An observer that observes progress updates of this action. 145 FilesystemVerifyDelegate* delegate_{}; 146 147 DISALLOW_COPY_AND_ASSIGN(FilesystemVerifierAction); 148 }; 149 150 } // namespace chromeos_update_engine 151 152 #endif // UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_ 153