summaryrefslogtreecommitdiff
path: root/payload_consumer/filesystem_verifier_action.h
blob: 6a8823a5e4bba9434bbbfba7c74a96a504b80582 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_
#define UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_

#include <sys/stat.h>
#include <sys/types.h>

#include <memory>
#include <string>
#include <vector>

#include <brillo/streams/stream.h>

#include "update_engine/common/action.h"
#include "update_engine/common/hash_calculator.h"
#include "update_engine/payload_consumer/install_plan.h"
#include "update_engine/payload_consumer/verity_writer_interface.h"

// This action will hash all the partitions of the target slot involved in the
// update. The hashes are then verified against the ones in the InstallPlan.
// If the target hash does not match, the action will fail. In case of failure,
// the error code will depend on whether the source slot hashes are provided and
// match.

namespace chromeos_update_engine {

// The step FilesystemVerifier is on. On kVerifyTargetHash it computes the hash
// on the target partitions based on the already populated size and verifies it
// matches the one in the target_hash in the InstallPlan.
// If the hash matches, then we skip the kVerifySourceHash step, otherwise we
// need to check if the source is the root cause of the mismatch.
enum class VerifierStep {
  kVerifyTargetHash,
  kVerifySourceHash,
};

class FilesystemVerifyDelegate {
 public:
  virtual ~FilesystemVerifyDelegate() = default;
  virtual void OnVerifyProgressUpdate(double progress) = 0;
};

class FilesystemVerifierAction : public InstallPlanAction {
 public:
  explicit FilesystemVerifierAction(
      DynamicPartitionControlInterface* dynamic_control)
      : verity_writer_(verity_writer::CreateVerityWriter()),
        dynamic_control_(dynamic_control) {
    CHECK(dynamic_control_);
  }

  ~FilesystemVerifierAction() override = default;

  void PerformAction() override;
  void TerminateProcessing() override;

  // Used for listening to progress updates
  void set_delegate(FilesystemVerifyDelegate* delegate) {
    this->delegate_ = delegate;
  }
  [[nodiscard]] FilesystemVerifyDelegate* get_delegate() const {
    return this->delegate_;
  }

  // Debugging/logging
  static std::string StaticType() { return "FilesystemVerifierAction"; }
  std::string Type() const override { return StaticType(); }

 private:
  friend class FilesystemVerifierActionTestDelegate;
  // Starts the hashing of the current partition. If there aren't any partitions
  // remaining to be hashed, it finishes the action.
  void StartPartitionHashing();

  // Schedules the asynchronous read of the filesystem.
  void ScheduleRead();

  // Called from the main loop when a single read from |src_stream_| succeeds or
  // fails, calling OnReadDoneCallback() and OnReadErrorCallback() respectively.
  void OnReadDoneCallback(size_t bytes_read);
  void OnReadErrorCallback(const brillo::Error* error);

  // When the read is done, finalize the hash checking of the current partition
  // and continue checking the next one.
  void FinishPartitionHashing();

  // Cleans up all the variables we use for async operations and tells the
  // ActionProcessor we're done w/ |code| as passed in. |cancelled_| should be
  // true if TerminateProcessing() was called.
  void Cleanup(ErrorCode code);

  // Invoke delegate callback to report progress, if delegate is not null
  void UpdateProgress(double progress);

  // The type of the partition that we are verifying.
  VerifierStep verifier_step_ = VerifierStep::kVerifyTargetHash;

  // The index in the install_plan_.partitions vector of the partition currently
  // being hashed.
  size_t partition_index_{0};

  // If not null, the FileStream used to read from the device.
  brillo::StreamPtr src_stream_;

  // Buffer for storing data we read.
  brillo::Blob buffer_;

  bool cancelled_{false};  // true if the action has been cancelled.

  // Calculates the hash of the data.
  std::unique_ptr<HashCalculator> hasher_;

  // Write verity data of the current partition.
  std::unique_ptr<VerityWriterInterface> verity_writer_;

  // Verifies the untouched dynamic partitions for partial updates.
  DynamicPartitionControlInterface* dynamic_control_{nullptr};

  // Reads and hashes this many bytes from the head of the input stream. When
  // the partition starts to be hashed, this field is initialized from the
  // corresponding InstallPlan::Partition size which is the total size
  // update_engine is expected to write, and may be smaller than the size of the
  // partition in gpt.
  uint64_t partition_size_{0};

  // The byte offset that we are reading in the current partition.
  uint64_t offset_{0};

  // An observer that observes progress updates of this action.
  FilesystemVerifyDelegate* delegate_{};

  DISALLOW_COPY_AND_ASSIGN(FilesystemVerifierAction);
};

}  // namespace chromeos_update_engine

#endif  // UPDATE_ENGINE_PAYLOAD_CONSUMER_FILESYSTEM_VERIFIER_ACTION_H_